Building an integration with the slack Event API, to get message reaction events into N8N

Hi there,

I’m trying to figure out how I’d make a workflow to respond when messages in a slack channel have a specific reaction added to them, to mark them for processing and including in a newsletter or similar.

Based on what I see (after a very quick look) in the slack events API here, it looks like you can tell slack to send POST requests to something like a webhook endpoint.

Has anyone here implemented this before?

I’m not experienced enough with n8n to know if I can do it with a webhook trigger node, or whether I’d need to create a whole new Slack Event Trigger node instead.

I’m not against doing that, but I haven’t created a custom node before, so it seemed work asking here before I start on anything.

Ta,

Hey @mrchrisadams,

I haven’t had experience with this particular use case. However, taking a quick look at their docs, I am assuming that using the Webhook node will be a simpler solution. The Real-Time API uses web-socket, and currently, n8n doesn’t support that. Hence, using the Events API would be a better approach.

I have not used the event API yet but we use Slack and n8n with slash commands and that works well for us, Looking at the event api there is an HTTP option and a socket mode so I can’t see why it wouldn’t work.

Ah, thanks @harshil1712 - it looks like the webhook might support this.

I can use the Event API to POST in response to the reaction_added event and set the channel like so on an existing slack app:

And from there, it looks like I need to make the Webhook respond with serve with the challenge sent as a parameter by slack, with a response like this example from their docs:

HTTP 200 OK
Content-type: application/json
{"challenge":"3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}

From there, once it’s in a workflow we’re good to do all kinds of things, I think

1 Like

That is exactly how I read it, Let me know how you get on as I have a future project that I want to use the events api for :smiley:

1 Like

OK, I think I almost have this working, but I think I’m stuck, and I reckon it’s the kind of thing fresh eyes will see instantly instead of me spending another hour or so fumbling around with a new UI.

I’m still new to n8n, so I’m going to share what I have here.

I’ve given slack an endpoint to send POST requests to, and they look like this when they make it to n8n:

[
  {
    "headers": {
      "host": "my-cool-app.app.n8n.cloud",
      "x-request-id": "8210940278a6a0fc87b4605a9a329f87",
      "x-real-ip": "10.40.4.185",
      "x-forwarded-for": "10.40.4.185",
      "x-forwarded-host": "my-cool-app.app.n8n.cloud",
      "x-forwarded-port": "443",
      "x-forwarded-proto": "https",
      "x-scheme": "https",
      "content-length": "129",
      "user-agent": "Slackbot 1.0 (+https://api.slack.com/robots)",
      "accept": "*/*",
      "accept-encoding": "gzip,deflate",
      "content-type": "application/json",
      "x-slack-signature": "v0=0d684662c7227af9e037559806a4ab66bf5441933687e9a4cc989b5e5250d8c9",
      "x-slack-request-timestamp": "1633684589"
    },
    "params": {},
    "query": {},
    "body": {
      "token": "njbTKVsNP6ewZJ1WbFyZZgBO",
      "challenge": "CSU5fS2WMnX1z6hRiWWisYMmPdI3duz57o4zg4pZIz6sgZrFYrC1",
      "type": "url_verification"
    }
  }
]

I think I need to get the challenge bit out, and return it in a RAW output on the webook

But this is the response I get from slack - it seems this challenge it not being added to the output, as I’m getting this error:

Your URL didn’t respond with the value of the challenge parameter.

Here’s the json slack is saying it gets back

"body": { 
	 "type": "url_verification",
	 "token": "",
	 "challenge": ""
}
Your Response:
"code": 
"error": "challenge_failed"
"body": {
  
}

What am I doing wrong here?

It’s not obvious to me what I’m doing wrong, so I’ve now created a “mock HTTP request” workflow , to trigger the other one for debugging purposes.

The Mock HTTP Request workflow

The Webhook workflow to respond to this

Here’s what the webhook response workflow looks like.

It should just show a response in the UI, and it should be importable into any n8n instance.

I can’t seem to set the response to return a response to slack like so:


{ "challenge": "the-string-sent-by-slack"}

I’ve tried every variant I can think of for setting the response data including messing with the response nodes. Here’s a webhook in its current state.

I’m sure it’s something really obvious that I’m missing, so I’d appreciate some pointers on what i need to change, as it feels like I’m almost there.

What about just doing this…

So we use a Set which only returns the challenge

In the mock test this results in this coming back which might be what you are after.

Hmm… ah, this is almost what we need.

I think slack needs the HTTP Response to look like one of the folllowing, based on Slack’s own API docs:

HTTP 200 OK
Content-type: text/plain
some-long-string

OR form encoded

HTTP 200 OK
Content-type: application/x-www-form-urlencoded
challenge=some-long-string

Or finally, as JSON:

HTTP 200 OK
Content-type: application/json
{ "challenge": "some-long-string" }

Any of these ought to work, but I’m not sure how to control the output to fit these without creating a totally custom node.

How can I do this?

It looks like the example I posted would do the job, Below is a test curl command that posts the same data to my webhook and the response back is what you are after.

n8n does some clever stuff internally so the mock Slack request you made won’t be the actual “raw” response.

curl -X POST https://n8n.mydomain.tld/webhook/whatever-my-path-is -H 'Content-Type: application/json' -d '{"token": "Jhj5dZrVaK7ZwHHjRyZWjbDl", "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P", "type": "url_verification"}'

Reponse

{"challenge":"3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"}

Nice! OK, So this does give slack the return value for setting up the endpoint - huzzah!

Now, the next bit is to figure out how to actually pipe the content of the webhooks to something useful!

I figure if I listen for the reaction_added event, and activate the workflow, based on what I read here in the docs, every time a reaction is added to a message, a JSON payload like the one below should be sent:

{
	"token": "z26uFbvR1xHJEdHE1OQiO6t8",
	"team_id": "T061EG9RZ",
	"api_app_id": "A0FFV41KK",
	"event": {
		"type": "reaction_added",
		"user": "U061F1EUR",
		"item": {
			"type": "message",
			"channel": "C061EG9SL",
			"ts": "1464196127.000002"
		},
		"reaction": "slightly_smiling_face",
		"item_user": "U0M4RL1NY",
		"event_ts": "1465244570.336841"
	},
	"type": "event_callback",
	"authed_users": [
		"U061F7AUR"
	],
	"authorizations": [
        {
            "enterprise_id": "E12345",
            "team_id": "T12345",
            "user_id": "U12345",
            "is_bot": false
        }
    ],
	"event_id": "Ev9UQ52YNA",
	"event_context": "EC12345",
	"event_time": 1234567890
}


This is taken from the helpful reaction_added example in the slack API docs, to the end point I’ve specified in n8n cloud.

How can I tell if I’m triggering events?

This seems sensible enough, and it looks like I have the correct permissions set up, but even after making this workflow as active, I’m not seeing any executions in the workflow after the initial one setting the endpoint up.

At this point, I’m now wondering if I DO need to make a whole specialised node to handle the signup process with the challenge as well as as the actual payloads being sent on a regular afterwards.

I can’t see the if the problem is slack or n8n right now, so I’ll likely write a small server I can exposes at a webhook endpoint point to sanity check what I’m doing, and see where I’m getting this wrong.

I guess on the bright side, we pretty much have a tutorial that can be made if we ever get this working…

Do you maybe need an if statement to check if the request is a verify call or a reaction being sent?

Hmm… I think you’re right.

OK. End of the day. I’ll have another look at this after some sleep. Thanks for your help @Jon :+1:

1 Like

No problem, I plan to use your work for my own stuff later so it all helps.

@mrchrisadams any new update on this flow… The solution could help the community

@Allwynpradip @mrchrisadams I guess, the problem was in permission scopes. But first things first: slack events API needs only one time challange. It’s nice to do so with both production and test URLs. Nodemation webhook node can be set to pass challenge simply returning back all recieved data like below:

Btw, after creating your app you can enable Event subscriptions under Manage distribution - Enable Features & Functionality.

On the same page you have to subscribe to (bot) events you are interested in, e.g. reaction_added. As mentioned in docs, permission scope needed, in our case - reactions:read. Actually, it should happen automatically, but you can check that your App Manifest (YAML) has:

oauth_config:
  scopes:
    bot:
      - reactions:read

Finally, you have to Install App to your workspace and add your bot to channels you are interested in.

3 Likes

I’m successfully sending back the correct JSON (as far as I can tell), but Slack is still not liking my config.

Slack is giving an error saying “Your request URL responded with an HTTP error”.

Here’s the output from Postman making the POST request, in order to validate that the response is correct:

Workflow:

Hey @ShockWave3,

Welcome to the community :cupcake:

I have just given your workflow a run and it works, When you did the test from Slack was the workflow running? Your screenshot shows the test webhook path so hitting the execute workflow button so it listens then testing again should work once for you.

That’s strange that it works for you and not for me.
Yes, I’ve definitely hit the Execute workflow button and I’m sure that the webhook is being intercepted since I can see all of the details in the incoming request.

On the Slack side, it still claims that the “Request URL responded with a HTTP error”.
I can’t replicate any errors in the response when I use Postman to simulate the POST request.

I’m wondering if it may have something to do with the fact that I’m going via CloudFlare for my domain setup. The A record is being proxied. It seems to be fine since I can get to the webhook from Postman just fine.

I tried removing the proxy functionality and just using “direct access” but I noticed that the Docker Compose build is using LetsEncrypt for the SSL cert and web browsers trusting the root certificate being used and so it displays an error.

I just tested out my workflow from above on the n8n cloud and Slack verified the Request URL without any issues.
So that suggests that the issue is specific to my own hosted version of n8n, and my guess is that it may be due to the root certificate not being trusted (if I go direct), or perhaps it has something to do with getting proxied via Cloudflare (if going via the proxy).

I did some digging here on the forum in order to find a solution for the certificate error and found this:

Their advice was to turn off the proxy for the n8n “A record” at Cloudflare, turn off the Docker containers for a while and then then restart them.

After doing the above, LetsEncrypt can now successfully create a cert for my domain, and I can establish a HTTPS connection directly to my domain without being proxied via Cloudflare.

Slack is still not able to verify the Request URL, but I have a feeling that it could be because their DNS cache hasn’t yet flushed out the old IP for my domain.
I’ll re-test tomorrow and see how it goes.

1 Like