You must enable javascript in order to use Slack. You can do this in your browser settings.

Handling user interaction in your Slack apps

The rundown
Read first:An overview of app interactivity

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 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.


The flow of user-triggered interactions

We explained in our overview of app interactivity that interactions are 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 to construct a coherent response.

We end up with an interaction flow that looks like this:

A user triggers an interaction by using one of an app's entry points.

The app receives and processes the interaction payload.

Using this context, the app generates a response to the interaction.

Your app needs to be ready for these last two steps — keep reading to find out how.


Preparing your app for user interactions

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 which indicate a web endpoint belonging to the app.

To configure a request URL for your app:

  • Open your app's management dashboard
  • Click on Interactive Components in the sidebar
  • Toggle the Interactivity switch on.

You'll see a few new options appear — the options that are relevant to us are:

Request URL - the URL we'll send the request payload to when interactive components or app actions are used. You'll need to add a URL that you can set up to handle these payloads, as we'll describe later in this doc. Save your changes after you've added one.

If you are distributing your app, this request URL needs to be an HTTPS URL (note: self-signed certificates are not allowed). If you're just building a single-workspace app, it can be plain HTTP.

This Request URL is also used by modals for view_submission event payloads. Your app can distinguish between the different types of payload using the type field as explained below.

Options Load URL - this is a setting that is used by some Block Kit interactive components — select menus and multi-select menus. These components can load menu options from an external source and Options Load URL determines which URL is queried to return those menu options.

You can leave Options Load URL blank for now — we recommend reading the reference guide for this component if you want to use it later.

If you create Slash Commands for your app, you'll find that each command has its own request URL. Read our guide to creating Slash Commands to learn more.

You're all set — your app can now start receiving payloads. Now let's see how to process them.


Handling interaction payloads

We mentioned above that there were a few different types of interaction payload your app might receive. They'll be sent to your specified request URL in an HTTP POST request.

The body of that 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:

In each case, the fields within the payload will provide a full context of the interaction. This will include the user who interacted, the pre-defined state fields of any interactive component used, where the interaction happens, and many 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. If your app never publishes any interactive components, it will never receive a block_actions payload, for example.

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 decide what it will do after one is sent.


Responding to users

There are a bouquet of potential responses to the receipt of an interaction payload:

Acknowledgment response - a required, immediate response that confirms your app received the payload.

Message responses - optional responses that use a special URL from the payload to publish messages.

Modal responses - optional responses that use a short-lived code from the payload to invoke a modal.

Asynchronous responses - optional responses that are inspired by the info in the payload, but not directly related.

Acknowledgment response

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. Make sure your app responds quickly.

On the flip side, the user won't see anything when your app only sends an acknowledgment response.

If you want to do more, keep reading.

Message responses

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 the place where the interaction happened.

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.

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, with a few exceptions that we'll explain below.

You can use a response_url by making an HTTP POST directly to the URL and including a message payload in the HTTP body.

Here's a simple example:

POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
    "text": "Thanks for your request, we'll process it and get back to you."
}

If your app needs more than 30 minutes to respond with a message, you'll need to publish it in the standard way.

Publishing ephemeral responses

A message published via response_url will be sent to the same conversation as the interaction source, visible to anyone within that conversation.

If you want to publish an ephemeral message, include an attribute response_type with your message JSON, and set its value to ephemeral:

POST https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Content-type: application/json
{
    "text": "Thanks for your request, we'll process it and get back to you.",
    "response_type": "ephemeral"
}

Updating a source message in response

If your app received an interaction payload after an interactive component was used inside of a message, you can use request_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."
}

Non-ephemeral messages can also be updated using chat.update.

Deleting a source message in response

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 wonderful thing about triggers is that trigger_ids 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.

Asynchronous responses

The receipt of an interaction payload may furnish your app with a request_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:

Respond to a user clicking a Complete Task button in an interactive message by a adding a happy reaction emoji to the source message.

Use a modal submission as the trigger for an update of the app's Home tab.

Send data to query and update an external service after the use of an app action.

Order cheeseburgers (hold the onions) for the team after someone clicks the Bring me Lunch button.


Make your garden grow

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.

Enable more opportunities for interaction by using the available app surfaces.