User interactions can blossom forth from the seeds planted in Slack apps. Cultivate the healthy growth of these interactions by preparing your app to understand and respond to them.
This guide will explain the nuances of user-triggered interactions and the steps necessary to handle the contextual interaction information your app will receive.
We explained in invocation & interactivity that interactions are essentially a trigger and a response. Apps can implement a number of interaction entry points that allow users to intentionally invoke a response from the app. Read our overview of those entry points to dig deeper into the field of options.
When one of those entry points is triggered, a new aspect is introduced to the interaction transaction β the interaction payload. This payload is a bundle of information that explains the context of the user action, giving the app enough information to construct a coherent response. We end up with an interaction flow that looks like this:
Your app needs to be ready for the last two steps.
In order for your app to receive interaction payloads, Slack needs to know where to send them. Each app can be configured with Request URLs that indicate a web endpoint belonging to the app.
To configure a Request URL for your app:
You'll see a few new options appear.Β The ones relevant to us are:
view_submission
event payloads. Your app can distinguish between the different types of payload using the type
field as explained below.You're all set! Your app can start receiving payloads. Now let's see how to process them.
We mentioned that there were a few different types of interaction payloads your app might receive. They'll be sent to your specified Request URL in an HTTP POST request in the form application/x-www-form-urlencoded
. For more information, refer to Using the Slack Web API: Basics. The body of the request will contain a payload
parameter; your app should parse this payload
parameter as JSON.
The resulting object can have different structures depending on the source. All those structures will have a type
field that indicates the source of the interaction. Our reference docs have a more detailed look at the payload structures for the different type
sources:
block_actions
payloads are received when a user clicks a Block Kit interactive component.shortcut
and message_actions
payloads are received when global and message shortcuts are used.view_submission
payloads are received when a modal is submitted.view_closed
payloads are received when a modal is canceled.In each case, the fields within the payload will provide a full context of the interaction. This will include the interacting user, the pre-defined state fields of any interactive component used, where the interaction happens, and more. Use this structure and these fields to interpret the request. You can use as much or as little of the info as your app needs. The payload types that your app can receive will depend on the other features your app implements. For example, if your app never publishes any interactive components, it will never receive a block_actions
payload.
Read our interaction payload reference docs to examine the detailed structure for the features your app uses, and design the app to be able to process those fields.
Now that your app can receive and process interaction payloads, it needs to know what to do after one is sent.
There are a bouquet of potential responses to the receipt of an interaction payload:
All apps must, as a minimum, acknowledge the receipt of a valid interaction payload.
To do that, your app must reply to the HTTP POST request with an HTTP 200 OK response. This must be sent within 3 seconds of receiving the payload. If your app doesn't do that, the Slack user who interacted with the app will see an error message, so ensure your app responds quickly. Otherwise, the user won't see anything when your app only sends an acknowledgment response. If you want to do more, keep reading.
Depending on the source, the interaction payload your app receives may contain a response_url
. This response_url
is unique to each payload, and can be used to publish messages back to where the interaction happened.
If you don't receive a response_url
in your interaction payload β for example, the payload from a global shortcut will not contain one β you can use a trigger_id
and a modal to get one for your app. Read more.
These responses can be sent up to 5 times within 30 minutes of receiving the payload. Even when sending composed responses, you must still send an acknowledgment response.
If you're developing a GovSlack app for use by public sector customers, point your response_url
to the slack-gov.com
domain instead of the slack.com
domain.
Within these responses, you can include a message payload. This message payload can be composed according to the same message composition guides as any other. You can use a response_url
by making an HTTP POST directly to the URL and including a message payload in the HTTP body.
The response_url
will bypass any channel posting permissions when used as a part of an app's action, since it is opening up a return pathway from the originating action (e.g. slash command, button click, and so on) in order to react to the user's interaction with the app.
If your app needs more than 30 minutes to respond with a message, you'll need to publish it in the standard way.
β¨ Go here for more details about how to handle a response_URL
in Javascript, or here for more details about how to do this in Python.
Below are examples for different types of message responses.
By default, a message published via response_url
will be sent as an ephemeral message:
POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
"text": "Oh hey, this is a nifty ephemeral message response!"
}
If you want to publish a message to the same conversation as the interaction source, include an attribute response_type
and set its value to in_channel
.
POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
"text": "Oh hey, this is a fun message in a channel!",
"response_type": "in_channel"
}
If you want to publish a message to a specific thread, you'll need to include an attribute response_type
and set its value to in_channel
. Then, to specify the thread, include a thread_ts
.
Also, be sure to set replace_original
to false
or you'll overwrite the message you're wanting to respond to!
POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
"text": "Oh hey, this is a marvelous message in a thread!",
"response_type": "in_channel",
"replace_original": false",
"thread_ts": "1234567890"
}
If your app received an interaction payload after an interactive component was used inside of a message, you can use response_url
to update that source message.
Include an attribute replace_original
and set it to true
:
POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
"replace_original": "true",
"text": "Thanks for your request, we'll process it and get back to you."
}
Feel free to include blocks in your response_url
update.
Non-ephemeral messages can also be updated using chat.update
. A message's type cannot be changed from ephemeral
to in_channel
. Once a message is issued, it retains its visibility quality for life.
You cannot use replace_original
to modify the user-posted message that invokes a slash command.
You can also delete a source message of an interaction entirely using response_url
.
Include delete_original
as the sole attribute in your response_url
JSON, with the value set to true
:
POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
"delete_original": "true"
}
Non-ephemeral messages can also be deleted using chat.delete
.
If you include a new message payload and delete_original
, the source message will be deleted, and your new message published.
The delete_original
field is not supported for use with slash commands, so sending it will not remove or retain a user-posted message that is invoked by the slash command.
The wonderful thing about triggers is that
trigger_id
s are wonderful things. They're attached to events and interactions. They expire in three seconds. They're fun fun fun fun fun! But the most wonderful thing about triggers is they can be used only once.
When certain events and interactions occur between users and your app, you'll receive a trigger_id
as part of the interaction payload. If you have a trigger_id
, you can use the value of that field to open a modal.
Triggers expire in three seconds. Use them before you lose them. You'll receive a trigger_expired
error when using a method with an expired trigger_id
.
Triggers may only be used once. You may perform just one operation with a trigger_id
. Subsequent attempts are presented with a trigger_exchanged
error.
response_url
When you're composing your modal, you can use special parameters to generate a response_url
when the modal is submitted. Read our guide to using modals to learn more about this technique. You can then use this newly-generated response_url
to publish a message as described above.
The receipt of an interaction payload may furnish your app with a response_url
or a trigger_id
, but it also imbues a lot of contextual knowledge about the interaction.
That context can be used by your app to do, well, anything. For example, it can:
We're excited about the possibilities opened to your app, when your apps are open to possible interactions.
Get some inspiration by reading our guide to planning your app, and enable more opportunities for interaction by using the available app surfaces.