We know there's a lot to learn and read about all the integration points of the Slack platform. That's why we're giving you this. More to read, easier to skim.
We're sure we're missing critical tips. Let us know by tweeting to @SlackAPI!
There's no explicit sandbox or developer environment available to work against. Instead, you'll need to use a workspace you've created or are a member of.
It's best to keep your integration or app's ownership contained within the workspace that is responsible for it.
Start by building a Slack app to contain all of your work -- by default, it can only (& easily!) be installed on your own workspace. Follow the UI instructions to add features — most require that you provide a HTTP server Slack can reach.
While developing for your own workspaces or if developing internal integrations, HTTPS will not be required for requests sent from Slack. This is for ease in getting started; we strongly recommend using HTTPS even for internal integrations.
Many developers find using HTTP tunneling software effective while building apps. For one such story, consult this tutorial: Tunneling with ngrok.
All three integration types allow you to post messages within a channel but differ in how those messages are triggered and how users interact with your app.
You can use all of these integration types together in your Slack app.
On their own, custom integrations are for a specific workspace to use. An incoming webhook is a single custom integration. A bot user is a single custom integration. Same with a slash command. The tokens and credentials used for these custom integrations are intended only for the workspace that originated them.
A Slack app is a packaged collection of one or more platform features. They can optionally be made available for Slack workspaces to install and utilize. workspaces will use an OAuth 2.0 authorization flow to approve apps, resulting in workspace-specific OAuth tokens for use on their behalf.
Other differences include:
We strongly recommend building internal integrations as part of a Slack app instead. Slack apps are better scoped, allowing your integration to only use the permissions they need. Additionally, you can use new features like interactive messages and the Events API.
Some of the tokens you'll be given while going through the integration creation process. Other tokens you obtain by sending users through the OAuth 2.0 authentication flow.
When you're working with Slack apps, you'll be awarded access tokens after a user approves your application.
Your incoming webhooks URLs are unique for your integration or application and do not require token-based authentication. Slash command response URLs also already encode your integration or application's identity.
Webhook URLs generated by
rtm.start also encode the information you need to connect, though requesting
rtm.start itself requires a
token as described above.
When you configure Outgoing webhooks, Slash commands and [Message buttons](/docs/message-buttons, you specify a URL for Slack to send requests when qualifying conditions are met. Slack also provides you a token related to that integration.
Slack sends that URL a JSON payload containing a
token field. Compare that field to values you've received from Slack. See validating slash commands for more information.
Authorization codes must be exchanged for an access token within 10 minutes by calling oauth.access as part of the authorization flow. Otherwise, the authorization code will expire and you will need to ask the user to go through OAuth again.
There is no programmatic way for you to revoke tokens issued to your integration or app. Members and administrators can remove your app through their workspace administration interface.
Though it's somewhat of a nuclear option, you also have the ability to revoke all tokens from your developer dashboard by selecting your application and using the Revoke all tokens button found there.
To reset your client secret, go to your developer dashboard, select the application you are concerned about, use the Change secret button found there.
Don't forget to use your new secret when exchanging authorization codes for access tokens while authorizing users and workspaces with OAuth 2.0.
Token strings could potentially be as long as 255 characters. Historically and typically, they've been shorter. Learn more.
When a Slack App is approved that contains a bot user, you're awarded two tokens. The bot user token is for performing certain actions directly as the bot user, like posting a message or connecting to the real time messaging API.
If you want to make Web API calls more generally, based on the scopes you've negotiated, you'll want to use the broader token you were awarded at approval time.
Typically, if Slack cannot reach your slash command URL it's because it's either inaccessible, does not have a valid, verifiable SSL certificate, or because our request is timing out for some reason.
Slack invokes slash command URLs from its servers rather than from a Slack client app like Slack for Mac. This means that the URL we're trying to reach must be accessible to Slack's servers.
To determine whether your certificate is valid, consider using this tool provided by SSL Labs.
Keep track of the validation tokens and team IDs Slack gives you when commands are created and teams approve your app. Always validate that the
token field in an incoming slash command request has been issued to you by Slack and scope your data for that workspace.
You won't be able to override any of these fields when using an incoming webhook attached to a Slack app. Instead, those values will be provided from your Slack app configuration and any configuration provided by the team.
If you're using a custom integration, verify that the icon URL you're providing corresponds to a publicly accessible image resource and that the provided username or channel is valid.
No, SSL certificates must be signed by a reputable certificate authority.
Slack rate limits all aspects of platform use with many factors. Rate limits are currently unpublished. Review our rate limiting documentation for more detail.
The guiding spirit of Slack's rate limiting is to ensure that teams are able to communicate effortlessly and without distraction.
Because the limits are unpublished, you won't know that you're about to hit a rate limit in advance. You will receive a
HTTP 429 Too Many Requests rate limited message in response to a request and will then need to wait for the next rate limiting window to open.
The next rate limit is indicated by a HTTP header called
Retry-After, presented in seconds to wait before attempting another request. If the value were
10, then you should wait 10 seconds or more before retrying that request.
You may find that you can't perform certain bursty actions, like attempting to message every member of a large workspace simultaneously. In some cases, hitting rate limits may be a symptom that there are better ways to to accomplish your goal. Some times you just need to work slower.
For more information, consult our rate limiting documentation.
The Real Time Messaging API and other API methods reference file objects that contain a suite of details about the content type of the file and absolute URLs where those files can be retrieved or used for display.
As of January 4th, 2016, applications must provide authentication to access the actual files that file objects reference. There's a blog post discussing this change of behavior.
File objects contain
url_private_download fields, as well as fields for private thumbnail URLs as applicable.
To retrieve these URLs, you must provide a HTTP Authentication header containing a bearer token that's been awarded the
For example, to retrieve a
thumb_360 field containing
https://files.slack.com/files-tmb/Z0CHK-THSCH5-5SZ0UT/cheese.jpg and your bearer token was
VALID_TOKEN, you'd need to send a request like this:
GET https://files.slack.com/files-tmb/Z0CHK-THSCH5-5SZ0UT/cheese.jpg Authorization: VALID_TOKEN
For public channels, use
channels.list to retrieve the list of channels. The list includes each channel's
For private channels, use
groups.list. It works the same way.
Many developers keep the list of channels in memory for swifter lookups. Poll the method occasionally to refresh your inventory.
You can use similar instructions to the question above, or you can use dedicated methods to look up a channel by its ID.
For public channels, use
channels.info to obtain a specific channel's information, including its
For private channels, use
groups.info. You'll find everything you want to know about a specific private channel.
Channel IDs remain the same even when the names are changed, but if a channel becomes private the ID will change.
Private channels were first conceived of as group objects, and the names of the objects, events, and methods were chosen then. We decided that "private channels" made more sense for users, but already had developers, both internal and external, using the
When you see references to these groups, just rewire your brain to call them private channels instead, even though you'll be calling them
group in your code.
channels.history and a token with the
channels:history scope to retrieve a specific message in a channel.
You'll need that message's
ts value, which uniquely identifies it within a channel. You'll also need that channel's ID value.
channels.history takes a
latest parameter, which you'll provide that
ts value for. By specifying
true for the
inclusive parameter and setting the
1, you'll receive exactly that message in return:
The first step is making a typical HTTP request to the
rtm.connect method. Within that response, you'll find a
url field beginning with the URI protocol
Then, use a Websocket client to open a long-lived connection to that time-sensitive URL. While the connection is open, you'll be streamed events associated with the workspace you're connecting on behalf of and can in turn send messages.
Typical HTTP client libraries and tools do not support connecting to websockets directly. You will need to find a client library for your preferred programming environment.
Choose the Events API if:
Or choose the RTM API if:
user_typingevents is important for your app or bot user's sense of self and agency
Or why not use the Events API and RTM API together?
The answer depends on whether you're using the Events API with or without the RTM API.
With the Events API, you must toggle your presence by managing your app's bot user config.
With the RTM API, your bot is marked
active while connected to a websocket.
See bot presence for further
Please be patient as our team regularly reviews submissions. To help the process go as smoothly as possible, we strongly recommend making sure you've followed the checklist before submitting.
If you need to update your approved app to request new OAuth scopes, include message buttons or add other new features, find your application's configuration page at https://api.slack.com/apps and indicate you'd like to make changes.
We'll then automatically create a copy of your published app for you to use while making and testing updates in a sandboxed environment.
Once you're ready to push the updated version of your app to users, simply re-submit it for review using the process described above.
If you've submitted your app to the directory but need to make changes to how your app or bot is described, or changes to the integration types packed into your app, or to request additional permissions, you'll need your app to be reviewed again.
Use the beta application corresponding to your submitted Slack app to make modifications to any of these features:
Your client secret and verification tokens may be regenerated as needed, without requesting further review.
No, only submit your app to the directory if you want your app to be discoverable and installable from the directory. If you don't submit your app, we won't display it there but it will be installable by any workspace you give the authorization URL to.
No, custom integrations are still documented and available to create and configure. We do strongly encourage all developers and users working with custom integrations to utilize internal integrations as part of a Slack app instead.
@colonel_mustard in the
#conservatory with the
:fork_and_knife:. A custom and internal investigation will follow this Slack app fact.
rtm.connectto initiate your websocket connection instead of
rtm.connectreturns just the data you need to open your connection.
rtm.start, use the
no_latestparameter to remove the
latestfield from each channel object.
channels.list, use the
exclude_membersparameter to trim long membership lists from each channel object.
Our bad. We used to overuse the term, team which could mean two different things — the people you talk to, as well as the Slack workspace, where the place you do work!
Now we call workspace for all the Slack workspaces, however our API remains the same as before. Wherever you see some objects contains
team_id, it really is an ID for the workspace! In the API world, we use the two terms interchangeably.