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

Events API

The Events API is a streamlined, easy way to build apps and bots that respond to activities in Slack. All you need is a Slack app and a secure place for us to send your events.

Don't call us, we'll call you

Tell us where to send your carefully selected event types and we'll deliver them with grace, security, and respect. We'll even retry when things don't work out.

Subscribe to the event types you need

Subscribe to the event types you want and don't worry about the events you don't need.

Governed by OAuth permission scopes

The event types sent to you are directly tied to the OAuth permission scopes awarded as users install your Slack App.

Perspectival bot users served here

Slack Apps including bot users can subscribe to events related to the channels and direct message conversations they are party to. Build bots without a bothersome bevy of RTM API websockets.

Everything is eventual

Find the right mix of user-based and bot user-based event subscriptions for your needs. Use both the Events and RTM APIs together for more redundancy and concern separation. Choose the technical implementation that's right for you.


Overview

The event loop

Many apps built using the Events API will follow the same abstract event-driven sequence:

  1. A user creates a circumstance that triggers an event subscription to your application
  2. Your server receives a payload of JSON describing that event
  3. Your server acknowledges receipt of the event
  4. Your business logic decides what to do about that event
  5. Your server carries out that decision

If your app is a bot listening to messages with specific trigger phrases, that event loop may play out something like:

  1. Members send messages in a channel the bot belongs to. The messages are about lots of things, but some of them contain today's secret word.
  2. Your server receives a message.channels event, as per its bot subscription and membership in #random.
  3. Your server responds with a swift and confident HTTP 200 OK.
  4. Your bot is trained to listen for today's secret word, and having found it, decides to send a message to the channel, encouraging everyone to keep that word secret.
  5. Your server uses chat.postMessage from the Web API to post that message to #random.

Using the Web API with the Events API empowers your app or bot to do much more than just listen and reply to messages.

Preparing to use the Events API

For many, the Events API is drastically simpler to integrate with than the real time messaging API. If you're already familiar with HTTP and comfortable maintaining your own server, handling the request and response cycle of the Events API should be old hat. If the world of web APIs is new to you, the Events API is a great next step after mastering incoming webhooks or the Web API.

Is the Events API right for your app?

Before starting, you may want to make a few early decisions about your application architecture and approach to consuming events.

One way to use the Events API is as an alternative to opening websocket connections to the real time messaging API. Instead of maintaining one or more long-lived connections for each workspace an application is connected to, you simply set up one or more endpoints on your own servers to receive events atomically in near real-time.

Some developers may want to use the Events API as a kind of redundancy for their existing websocket connections.

And other developers will use the Events API to receive information around the workspaces and users they are acting on behalf, to improve their slash commands, bot users, notifications, or other capabilities. With app events, you can track app uninstallation, token revocation, Enterprise Grid migration, and more.

Permission model

The Events API leverages Slack's existing object-driven OAuth scope system to control access to events. For example, if your app has access to files through the files:read scope, you can choose to subscribe to any or none of the file-related events like file_created and file_deleted.

You will only receive events that users who've authorized your app can "see" on their workspace (that is, if a user authorizes access to private channel history, you'll only see the activity in private channels they are a member of, not all private channels across the workspace).

Bot users may also subscribe to events on their own behalf. The bot scope requested when workspaces install your bot covers events access for both the Events API and the Real Time Messaging API.


Subscribing to event types

To begin working with the Events API, you'll need to create a Slack app if you haven't already. While managing your application, find the "Event Subscriptions" configuration page and use the toggle to turn it on.

The on switch for the Events API

After a little more configuration, you'll be able to select all the event types you want to subscribe to.

Events API Request URLs

Request URLs operate similarly to slash command invocation URLs, and message button action URLs:

They all receive a HTTP POST containing data in response to activity.

In the Events API, your Events API Request URL is the target location where all the events your application is subscribed to will be delivered, regardless of the workspace or event type.

Since your application will have only one Events Request URL, you'll need to do any additional dispatch or routing server-side after receiving event data.

Your Request URL will receive JSON-based payloads containing wrapped event types. The volume of events will vary depending on the events you subscribe to, and the size and activity of the workspaces that install your application.

Your Request URL might receive many events and requests. Consider decoupling your ingestion of events from the processing and reaction to them. Review the section on rate limiting to better understand the maximum event volume you may receive.

Request URL Configuration & Verification

Your Event Request URL must be confirmed before saving this form. If your server takes some time to "wake up" and your initial attempt at URL verification fails due to a timeout, use the retry button to attempt verification again.

URL verification handshake

The events sent to your Request URL may contain sensitive information associated with the workspaces having approved your Slack app. To ensure that events are being delivered to a server under your direct control, we must verify your ownership by issuing you a challenge request.

After you've completed typing your URL, we'll dispatch a HTTP POST to your request URL. We'll verify your SSL certificate and we'll send a application/json POST body containing three fields:

{
    "token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
    "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
    "type": "url_verification"
}

This event does not require a specific OAuth scope or subscription. You'll automatically receive it whenever configuring an Events API request URL. The attributes we send include:

  • token — Use this as proof that the request is coming from Slack on behalf of your application. You'll find this value in the "App Credentials" section of your app's application management interface. Verifying this value is more important when working with real events following this verification sequence.
  • challenge — a randomly generated string produced by Slack. The point of this little game of cat and mouse is that you're going to respond to this request with a response body containing this value.
  • type — this payload is similarly formatted to other event types you'll encounter in the Events API. To help you differentiate url verification requests form other event types, we inform you that this is of the url_verification variety.

Responding to the challenge

Once you receive the event, respond in plaintext with the challenge attribute value. You'll want to use a 200-series HTTP status code to indicate triumphant success. In the above example, our response might be:

HTTP 200 OK
Content-type: application/x-www-form-urlencoded
3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P

Alternatively, if we're feeling more formal, we can respond with application/x-www-form-urlencoded:

HTTP 200 OK
Content-type: application/x-www-form-urlencoded
challenge=3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P

Or if we're feeling like showing off, we might respond with some application/json:

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

Once URL verification is complete, you'll see a green check mark celebrating your victory.

Finally, you win the game of URL verification.

If we receive an error from your server, a timeout, or other exceptional condition occurs, you'll see error messages that will hopefully help you understand what's amiss and then retry when you're ready.

https://internal-intranet-links-will-not-work-here.local/sorry won't work so a different URL will need to be given before retrying

With this challenging handshake complete, we're ready to open up our event type catalog and decide which events to subscribe to.

Choosing event subscriptions

After configuring and validating your Request URL, it's time to subscribe to the event types you find fascinating, useful, or necessary.

The event subscription configuration process

The subscription manager is split into two sections:

  • Team Events - these are the events that require a corresponding OAuth scope, and are perspectival to a member installing your application.
  • Bot Events - subscribe to events on behalf of your application's bot user, no additional scopes beyond bot required. As with workspace Events, you'll only receive events perspectival to your bot user.

Activating subscriptions

The Events API is backed by the same OAuth permission scoping system powering your Slack App.

If workspaces have already installed your application, your Request URL will soon begin receiving your configured event subscriptions.

For any workspaces that have yet to install your application, you'll need to request the specific OAuth scopes corresponding to the event types you're subscribing to. If you're working on behalf of a bot user, you'll need your bot installed the typical way, using the bot OAuth scope.

Authorize users for your Event Consumer app through the standard OAuth flow. Be sure to include all of the necessary scopes for the events your app wants to receive.

Consult our index of the available event types with corresponding OAuth scopes.


With all this due preparation out of the way, it's time to receive and handle all those event subscriptions.

Receiving Events

Your Request URL will receive a request for each event matching your subscriptions. One request, one event.

You may want to consider the number of workspaces you serve, the number of users on those workspaces, and their volume of messages and other activity to evaluate how many requests your Request URL may receive and scale accordingly.

Events dispatched as JSON

When an event in your subscription occurs in an authorized user's account, we'll send an HTTP POST request to your Request URL. The event will be in the Content-Type: application/json format:

{
        "token": "XXYYZZ",
        "team_id": "TXXXXXXXX",
        "api_app_id": "AXXXXXXXXX",
        "event": {
                "type": "name_of_event",
                "event_ts": "1234567890.123456",
                "user": "UXXXXXXX1",
                ...
        },
        "type": "event_callback",
        "authed_users": [
                "UXXXXXXX1",
                "UXXXXXXX2"
        ],
        "event_id": "Ev08MFMKH6",
        "event_time": 1234567890
}

The token, team, and api_app_id fields help you identify the validity, origin, and destination of the request.

The event attribute contains a JSON hash for the corresponding event type. The event wrapper is an event envelope of sorts, and the event field represents the contents of that envelope.

Callback field overview

Also referred to as the "outer event", or the JSON object containing the event that happened itself.

Field Type Description
token String The shared-private callback token that authenticates this callback to the application as having come from Slack. Match this against what you were given when the subscription was created. If it does not match, do not process the event and discard it.

Example: JhjZd2rVax7ZwH7jRYyWjbDl

team_id String The unique identifier for the workspace/team where this event occurred.

Example: T461EG9ZZ

api_app_id String The unique identifier for the application this event is intended for. Your application's ID can be found in the URL of the your application console. If your Request URL manages multiple applications, use this field along with the token field to validate and route incoming requests.

Example: A4ZFV49KK

event Event Type Contains the inner set of fields representing the event that's happening.

Examples below.

type String This reflects the type of callback you're receiving. Typically, that is event_callback. You may encounter url_verification during the configuration process. The `event` fields "inner event" will also contain a type field indicating which event type lurks within (down below)
authed_users Array An array of string-based User IDs. Each member of the collection represents a user that has installed your application/bot and indicates the described event would be visible to those users. You'll receive a single event for a piece of data intended for multiple users in a workspace, rather than a message per user.
event_id String A unique identifier for this specific event, globally unique across all workspaces. Events will include this field beginning March 9, 2017.
event_time Integer The epoch timestamp in seconds indicating when this event was dispatched. Events will include this field beginning March 9, 2017.

Event type structure

The structure of event types vary from type to type, depending on the kind of action or object type they represent.

If you're already familiar with the real time messaging API, you'll find that the inner event structure is identical to corresponding events, but they are wrapped in a kind of event envelope in the callbacks we send to your Event Request URL.

Field Type Description
type String The specific name of the event described by its adjacent fields. This field is included with every inner event type.

Examples: reaction_added, messages.channel, team_join

event_ts String The timestamp of the event. The combination of event_ts, team_id, user_id, or channel_id is intended to be unique. This field is included with every inner event type.

"Time is the moving image of eternity" — Plato.

Example: 1469470591.759709

user String The user ID belonging to the user that incited this action. Not included in all events as not all events are controlled by users. See the top-level callback object's authed_users if you need to calculate event visibility by user.

Example: U061F7AUR

ts String The timestamp of what the event describes, which may occur slightly prior to the event being dispatched as described by event_ts. The combination of ts, team_id, user_id, or channel_id is intended to be unique.

Example: 1469470591.759709

item String Data specific to the underlying object type being described. Often you'll encounter abbreviated versions of full objects. For instance, when file objects are referenced, only the file's ID is presented. See each individual event type for more detail.

If multiple users on one workspace have installed your app and can "see" the same event, we will send one event and include a list of users to whom this event is "visible" in the authed_users field. For example, if a file was uploaded to a channel that two of your authorized users were party to, we would stream the file_uploaded event once and indicate both of those users in the authed_users array.

Here's a full example of a dispatched event for reaction_added:

{
        "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"
        },
        "event_ts": "1465244570.336841",
        "type": "event_callback",
        "authed_users": [
                "U061F7AUR"
        ]
}

Responding to Events

Your app should respond to the event request with an HTTP 2xx within three seconds. If it does not, we'll consider the event delivery attempt failed. After a failure, we'll retry three times, backing off exponentially.

We recommend responding to events with a HTTP 200 OK as soon as you can. You may want to avoid processing and reacting to events within the same process handling event reception.

What you do with the event depends on what your application or service does.

Maybe it'll trigger you to send a message using chat.postMessage. Maybe you'll update a leaderboard. Maybe you'll update a piece of data you're storing. Maybe you'll change the world or just decide to do nothing at all.

Rate limiting

Chances are, you won't be rate limited. But we also don't want to flood your servers with an unwanted flurry of events.

We'll send a maximum of 5,000 events per hour on behalf of each workspace your application is installed on. We'll let a workspace burst up to 2,000 events in a brief period of time but we'll limit the number of events above that in short periods.

When rate limited, your Request URL will receive typically formatted event callbacks with three important fields to look at, in JSON:

  • type - this specific event type: app_rate_limited
  • minute_rate_limited - a rounded epoch time value indicating the minute your application became rate limited for this workspace
  • team_id - subscriptions between your app and the workspace with this ID are being rate limited
  • token - the same token you're verifying for other events api_app_id - your application's ID, especially useful if you have multiple applications working with the Events API

You'll receive these callbacks for each of the minutes you are rate limited for that workspace.

Error handling

As Slack sends your request URL events, we ask that you return a HTTP 200 OK for each event you successfully receive.

You may respond with a HTTP 301 or 302 and we'll follow up to two redirects in our quest for you to provide us a HTTP 200 success code.

Failure conditions

We consider any of these scenarios a single failure condition:

  • we are unable to negotiate or validate your server's SSL certificate
  • we wait longer than 3 seconds to receive a valid response from your server
  • we encounter more than 2 HTTP redirects to follow
  • we receive any other response than a HTTP 200-series response (besides allowed redirects mentioned above)

While we limit the number of failure conditions we'll tolerate over time, we also gracefully retry sending your events according to an exponential backoff strategy.

Graceful retries

We'll knock knock knock on your server's door, retrying a failed request up to 3 times in a gradually increasing timetable:

  1. the first retry will be sent nearly immediately
  2. the second retry will be attempted after 1 minute
  3. the third and final retry will be sent after 5 minutes

With each retry attempt, you'll also be given a X-Slack-Retry-Num HTTP header indicating the attempt number: 1, 2, or 3.

Retries count against the failure limits mentioned below.

We'll tell you why we're retrying the request in the X-Slack-Retry-Reason HTTP header. These possible values describe their inciting events:

  • http_timeout - Your server took longer than 3 seconds to respond to the previous event delivery attempt
  • too_many_redirects - We'll follow you down the rabbit hole of HTTP redirects only so far. If we encounter more than 2, we'll retry the request in hopes it won't be that many this time.
  • connection_failed - we just couldn't seem to connect to your server. Maybe we couldn't find it in DNS or maybe your host is unreachable
  • ssl_error - we couldn't verify the veracity of your SSL certificate. Find tips on producing valid SSL certificates here.
  • http_error - we encountered an HTTP status code that was not in the HTTP 200 OK range. Maybe the request was forbidden. Or you rate limited us. Or the document just could not be found. So we're trying again in case that's all rectified now.
  • unknown_error - we didn't anticipate this condition arising but prepared for it nonetheless. For some reason it didn't work and we don't know why yet.
Turning retries off

If your server is having trouble handling our requests or you'd rather we not retry failed deliveries, provide a HTTP header in your responses indicating that you'd prefer no further attempts.

Just provide us this HTTP header and value as part of your non-200 OK response:

X-Slack-No-Retry: 1

By presenting this header, We'll understand it to mean you'd rather this specific event not be redelivered. Other event deliveries will remain unaffected.

Failure limits

If you're responding with errors, we won't keep sending events to your servers forever.

When your application enters any combination of these failure conditions more than 500 times within 30 minutes, your application's event subscriptions will be temporarily disabled.

We'll also send you, the Slack app's creator and owner, an email alerting you to the situation. You'll have the opportunity to re-enable deliveries when you're ready.

Manually re-enable event subscriptions by visiting your application's settings.


Change management

Inevitably, the status of your subscriptions will change. New workspaces will sign up for your application. Installing users may leave a workspace. Maybe you make some tweaks to your subscriptions or incite users to request a different set of OAuth scopes.

Beyond your app being disabled, there are a few different types of changes that will affect which events your app is receiving:

App installation

When a user installs your app, you'll immediately begin receiving events for them based on your subscription. Your application's granted OAuth scopes dictate which events in your subscription you receive.

If you've configured your subscription to receive reaction_added, reaction_removed, and file_created events, you won't receive all three unless you request the reactions:read and files:read scopes from the user. For example, If you'd only requested files:read, you'll only receive file_created events and not reaction_added or reaction_removed.

App revocation

If a user uninstalls your app (or the tokens issued to your app are revoked), events for that user will immediately stop being sent to your app.

You change the events in your subscription

If you modify your subscription through the application management interface, the modifications will immediately take effect.

Depending on the modification, the events types, and OAuth scopes you've been requesting from users, a few different things can happen:

Adding event subscriptions you already have scopes for

For example, you've been requesting files:read from users and decide to add the file_created event. Because you already have access to this resource (files), you'll begin receiving file_created events as soon as you update your subscription.

Adding event subscriptions you aren't yet scoped for

For example, you've been requesting channels:read from users and decide to add the file_created event. Because you don't have access to this resource (files), you won't receive file_created events immediately.

You must send your existing users through the OAuth flow again, requesting the files:read scope. You'll begin to receive file_created events for each user after they authorize files:read for your app.

Removing event subscriptions, regardless of granted scopes

Events will immediately stop being sent for all users who have installed your app. Their OAuth scopes and authorizations will not be affected.

If you weren't granted the permission scopes for the removed event subscription, then nothing really changes. You weren't receiving those events anyway and you won't be receiving them now either.

Toggling presence

To toggle your bot user's presence when connected exclusively to the Events API, visit your app management console's Bot Users tab.

Toggling bot user presence for the events API

Learn more about the nuances of bot user presence.


Event types compatible with the Events API

You may subscribe to these events using the Events API:

Event Description Required Scope
app_uninstalled

Your Slack app was uninstalled.

None
channel_archive

A channel was archived

channels:read
channel_created

A channel was created

channels:read
channel_deleted

A channel was deleted

channels:read
channel_history_changed

Bulk updates were made to a channel's history

channels:history
channel_rename

A channel was renamed

channels:read
channel_unarchive

A channel was unarchived

channels:read
dnd_updated

Do not Disturb settings changed for the current user

dnd:read
dnd_updated_user

Do not Disturb settings changed for a member

dnd:read
email_domain_changed

The workspace email domain has changed

team:read
emoji_changed

A custom emoji has been added or changed

emoji:read
file_change

A file was changed

files:read
file_comment_added

A file comment was added

files:read
file_comment_deleted

A file comment was deleted

files:read
file_comment_edited

A file comment was edited

files:read
file_created

A file was created

files:read
file_deleted

A file was deleted

files:read
file_public

A file was made public

files:read
file_shared

A file was shared

files:read
file_unshared

A file was unshared

files:read
grid_migration_finished

An enterprise grid migration has finished on this workspace.

None
grid_migration_started

An enterprise grid migration has started on this workspace.

None
group_archive

A private channel was archived

groups:read
group_close

You closed a private channel

groups:read
group_history_changed

Bulk updates were made to a private channel's history

groups:history
group_open

You opened a private channel

groups:read
group_rename

A private channel was renamed

groups:read
group_unarchive

A private channel was unarchived

groups:read
im_close

You closed a DM

im:read
im_created

A DM was created

im:read
im_history_changed

Bulk updates were made to a DM's history

im:history
im_open

You opened a DM

im:read
link_shared

A message was posted containing one or more links relevant to your application

links:read
member_joined_channel

A user joined a public or private channel

channels:read
member_left_channel

A user left a public or private channel

channels:read
message

A message was sent to a channel

channels:history
message.channels

A message was posted to a channel

channels:history
message.groups

A message was posted to a private channel

groups:history
message.im

A message was posted in a direct message channel

im:history
message.mpim

A message was posted in a multiparty direct message channel

mpim:history
pin_added

A pin was added to a channel

pins:read
pin_removed

A pin was removed from a channel

pins:read
reaction_added

A member has added an emoji reaction to an item

reactions:read
reaction_removed

A member removed an emoji reaction

reactions:read
resources_added

Access to a set of resources was granted for your app

None
resources_removed

Access to a set of resources was removed for your app

None
scope_denied

OAuth scopes were denied to your app

None
scope_granted

OAuth scopes were granted to your app

None
star_added

A member has starred an item

stars:read
star_removed

A member removed a star

stars:read
subteam_created

A User Group has been added to the workspace

usergroups:read
subteam_members_changed

The membership of an existing User Group has changed

usergroups:read
subteam_self_added

You have been added to a User Group

usergroups:read
subteam_self_removed

You have been removed from a User Group

usergroups:read
subteam_updated

An existing User Group has been updated or its members changed

usergroups:read
team_domain_change

The workspace domain has changed

team:read
team_join

A new member has joined

users:read
team_rename

The workspace name has changed

team:read
tokens_revoked

API tokens for your app were revoked.

None
url_verification

Verifies ownership of an Events API Request URL

None
user_change

A member's data has changed

users:read

If you want to bookmark that handy list, do so here.

App Events

Your application has a life of its own. You built it, you cultivate it, you maintain and improve it. But still, stuff happens to your app in the wild — tokens get revoked, workspaces "accidentally" uninstall it, and sometimes teams grow up and become part of a massive Enterprise Grid.

Sophisticated apps want to know what's happening, to situationally respond, tidy up data messes, pause and resume activity, or to help you contemplate the many-folded nuances of building invaluable social software. Your app is interesting, wouldn't you like to subscribe to its newsletter?

Subscriptions to App Events require no special OAuth scopes — just subscribe to the events you're interested in below and you'll receive them as appropriate for each workspace your app is installed on.

Event Description Required Scope
app_uninstalled

Your Slack app was uninstalled.

None
grid_migration_finished

An enterprise grid migration has finished on this workspace.

None
grid_migration_started

An enterprise grid migration has started on this workspace.

None
tokens_revoked

API tokens for your app were revoked.

None

Operational detail for each event is available in its respective documentation.


Tips

  • Why choose the Events API over the RTM API? Find out why to choose one or the other (or both!) in the Events API FAQ.
  • Tolerate minor changes in event type and object type structures. Expect additional fields you haven't encountered before and fields that are only conditionally present.
  • Bot users using the Events API exclusively must toggle their presence status using their app management console.
  • The Events API is best used in conjunction with other platform features. In particular, to send messages as a bot user or on behalf of your application, use chat.postMessage. Handle anything else your app does by using incoming webhooks and other write-based web API methods.
  • De-couple your ingestion of events from processing and reacting to them. Especially when working with large workspaces, many workspaces, or subscribing to a large number of events. Quickly respond to events with HTTP 200 and add them to a queue before doing amazing things with them.
  • Some event types are not available in bot user subscriptions. Consult an event's documentation page for information on whether that event is supported for bot users.
  • Some event types are less likely to happen than others. Events like message.channels happen frequently on typical workspaces. im_history_changed on the other hand is a rare occurrence on even the busiest of workspaces.
  • Building an integration for Enterprise Grid workspaces? Consult the Enterprise Grid docs for notes on Events API usage and shared channels.