A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Slack API is how an app or AI agent works with a Slack workspace: posting messages, reading channel history, creating channels, looking up people, and handling files. Access is granted through an access token and a set of permissions, and an app only ever sees the channels it has been added to. Separately, Slack can push live updates to an app the moment something happens.
How an agent connects to Slack determines what it can reach. There are two routes, one for making calls to Slack and one for receiving events from it, each with its own access token. Either way, an agent is limited to the permissions it is granted and the channels the app has been added to.
The actions an app or AI agent calls to read and change Slack, covering messages, channels, people, and files.
Slack sends updates, like messages, reactions, and joins, to an app as they happen.
Acts as the app rather than a person, the default for automation.
Acts on behalf of the installing user, and is needed for search and some user-only methods.
Used to open a live connection for receiving updates, not to call the API.
Slack's API is split into areas like messages, channels, users, and files, and an agent is granted permissions for each area separately. Some areas give access to far more than others.
Public and private channels, DMs, and group DMs.
Send, edit, schedule, and delete messages.
chat:write) lets an agent post as the app in any channel it is in, and a posted message is visible to everyone in that channel.Look up people, profiles, and the channels they are in.
users:read.email) returns people's email addresses.Upload, list, and remove files.
files:read) can reach any file shared in a channel the app is in.Add, remove, and read emoji reactions.
Search messages across the workspace.
search:read) needs a user key and reaches everything that person can see.Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
Channels & conversationsPublic and private channels, DMs, and group DMs.10 | ||||||
| GET | /api/conversations.list | List channels, DMs and group DMs | read | channels:read | Current | |
Paginated; filter by types (public_channel, private_channel, mpim, im). Acts onconversation Permission (capability) channels:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/conversations.info | Get metadata about a conversation | read | channels:read | Current | |
Reads one conversation's settings, not its messages. Acts onconversation Permission (capability) channels:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/conversations.history | Fetch a channel's message history | read | channels:history | Current | |
Needs the history scope for the channel type; cursor-paginated. Acts onmessage Permission (capability) channels:historyVersionAvailable since the API’s base version Webhook eventNone Rate limitNew non-Marketplace apps: 1 request/minute, limit ≤ 15 (since 29 May 2025). SourceOfficial documentation ↗ | ||||||
| GET | /api/conversations.replies | Fetch the replies in a thread | read | channels:history | Current | |
Returns a thread's messages from its parent ts. Acts onmessage Permission (capability) channels:historyVersionAvailable since the API’s base version Webhook eventNone Rate limitNew non-Marketplace apps: 1 request/minute, limit ≤ 15 (since 29 May 2025). SourceOfficial documentation ↗ | ||||||
| GET | /api/conversations.members | List the members of a conversation | read | channels:read | Current | |
Acts onuser Permission (capability) channels:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/conversations.create | Create a public or private channel | write | channels:manage | Current | |
Reshapes the workspace; private needs groups:write. Acts onconversation Permission (capability) channels:manageVersionAvailable since the API’s base version Webhook event channel_createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/conversations.invite | Invite users to a channel | write | channels:manage | Current | |
Acts onuser Permission (capability) channels:manageVersionAvailable since the API’s base version Webhook event member_joined_channelRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/conversations.archive | Archive a channel | write | channels:manage | Current | |
Acts onconversation Permission (capability) channels:manageVersionAvailable since the API’s base version Webhook event channel_archiveRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/conversations.open | Open or resume a DM or group DM | write | im:write | Current | |
Acts onconversation Permission (capability) im:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/conversations.setTopic | Set a channel's topic | write | channels:manage | Current | |
Acts onconversation Permission (capability) channels:manageVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
MessagesSend, edit, schedule, and delete messages.6 | ||||||
| POST | /api/chat.postMessage | Send a message to a channel | write | chat:write | Current | |
Posts as the app; supports Block Kit. chat:write.public lets it post to public channels it hasn't joined; chat:write.customize to override the name or icon. About 1 message a second per channel. Acts onmessage Permission (capability) chat:writeVersionAvailable since the API’s base version Webhook event messageRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/chat.postEphemeral | Send a message visible to only one user | write | chat:write | Current | |
Acts onmessage Permission (capability) chat:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/chat.update | Edit an existing message | write | chat:write | Current | |
Acts onmessage Permission (capability) chat:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/chat.delete | Delete a message | write | chat:write | Current | |
Acts onmessage Permission (capability) chat:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/chat.scheduleMessage | Schedule a message to send later | write | chat:write | Current | |
Acts onmessage Permission (capability) chat:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/chat.getPermalink | Get a permalink URL for a message | read | — | Current | |
No special scope beyond access to the channel. Acts onmessage Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
UsersLook up people, profiles, and the channels they are in.5 | ||||||
| GET | /api/users.list | List the members of the workspace | read | users:read | Current | |
Cursor-paginated. Acts onuser Permission (capability) users:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/users.info | Get a user's profile and details | read | users:read | Current | |
Acts onuser Permission (capability) users:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/users.lookupByEmail | Find a user by email address | read | users:read.email | Current | |
Requires the email scope; exposes the email-to-user mapping. Acts onuser Permission (capability) users:read.emailVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/users.profile.get | Get a user's profile fields | read | users.profile:read | Current | |
Acts onuser Permission (capability) users.profile:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/users.conversations | List the conversations a user is in | read | channels:read | Current | |
Acts onconversation Permission (capability) channels:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
FilesUpload, list, and remove files.6 | ||||||
| POST | /api/files.getUploadURLExternal | Begin a file upload (step 1 of 2) | write | files:write | Current | |
Current upload flow; pair with files.completeUploadExternal. Acts onfile Permission (capability) files:writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/files.completeUploadExternal | Finish and share an uploaded file (step 2 of 2) | write | files:write | Current | |
Acts onfile Permission (capability) files:writeVersionAvailable since the API’s base version Webhook event file_sharedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/files.upload | Upload a file (legacy) | write | files:write | Deprecated | |
Deprecated. Use the external-upload flow instead. Acts onfile Permission (capability) files:writeVersionDeprecated 2025-03-11 Webhook event file_sharedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/files.list | List files visible to the app | read | files:read | Current | |
Acts onfile Permission (capability) files:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/files.info | Get a file's metadata | read | files:read | Current | |
Acts onfile Permission (capability) files:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/files.delete | Delete a file | write | files:write | Current | |
Acts onfile Permission (capability) files:writeVersionAvailable since the API’s base version Webhook event file_deletedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
ReactionsAdd, remove, and read emoji reactions.3 | ||||||
| POST | /api/reactions.add | Add an emoji reaction to a message | write | reactions:write | Current | |
Acts onreaction Permission (capability) reactions:writeVersionAvailable since the API’s base version Webhook event reaction_addedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/reactions.remove | Remove an emoji reaction | write | reactions:write | Current | |
Acts onreaction Permission (capability) reactions:writeVersionAvailable since the API’s base version Webhook event reaction_removedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/reactions.get | Get the reactions on a message | read | reactions:read | Current | |
Acts onreaction Permission (capability) reactions:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
SearchSearch messages across the workspace.1 | ||||||
| GET | /api/search.messages | Search messages across the workspace | read | search:read | Current | |
User token only; reaches everything the searching user can see. Acts onmessage Permission (capability) search:readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Alongside the methods an agent calls, Slack can push events to an app the moment something happens, like a message being posted, a reaction being added, or a member joining a channel. This lets an agent react to activity rather than repeatedly checking for it. Subscriptions are set in the app's settings.
| Event | What it signals | Triggered by |
|---|---|---|
message | A message was posted to a channel. | /api/chat.postMessage |
app_mention | The app was @-mentioned. | In-app only |
reaction_added | An emoji reaction was added to an item. | /api/reactions.add |
reaction_removed | An emoji reaction was removed. | /api/reactions.remove |
channel_created | A channel was created. | /api/conversations.create |
channel_archive | A channel was archived. | /api/conversations.archive |
member_joined_channel | A member joined a channel. | /api/conversations.invite |
file_shared | A file was shared into a channel. | /api/files.completeUploadExternal/api/files.upload |
file_created | A file was created in the workspace. | In-app only |
file_deleted | A file was deleted. | /api/files.delete |
team_join | A new member joined the workspace. | In-app only |
user_change | A member's profile changed. | In-app only |
Slack caps how much an agent can do, and hitting those caps is a common cause of failed calls in production. The caps fall into three kinds: how often an agent can call, how much it can send in one request, and how results are paginated. Limits that apply to a single method are shown on its row above.
Slack sorts each method into one of four rate-limit tiers that set how often it can be called, from Tier 1, the most restrictive (around 1 call a minute), up to Tier 4 (100+ a minute). Posting is handled separately: chat.postMessage allows about one message a second per channel. And since 29 May 2025, newly-created non-Marketplace apps are capped at 1 call a minute on conversations.history and conversations.replies, returning at most 15 results. Going over any limit returns an HTTP 429 with a Retry-After header giving the number of seconds to wait.
Pagination is cursor-based: a call passes limit and cursor, and responses carry response_metadata.next_cursor. For new non-Marketplace apps the conversations.history and conversations.replies limit is capped at 15 (default 15) since 29 May 2025.
Message text runs up to 40,000 characters and up to 50 Block Kit blocks per message. File uploads run up to 1 GB depending on plan.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 200 | ok:false | Slack returns HTTP 200 with "ok": false and an error field for most failures, so check the body, not the status. | Always read the JSON ok and error fields, not just the HTTP status. |
| 200 | not_authed | No authentication token was provided. | Send a valid Bearer token in the Authorization header. |
| 200 | invalid_auth | The token is invalid or has been revoked. | Re-install the app or refresh the token. |
| 200 | missing_scope | The token lacks a scope the method requires. | Add the named scope and re-install the app. |
| 200 | channel_not_found | The channel doesn't exist or the app isn't in it. | Add the app to the channel, or check the channel ID. |
| 200 | not_in_channel | The app must be a member of the channel to act there. | Invite the app to the channel first. |
| 200 | msg_too_long | The message text exceeded the limit (40,000 characters). | Shorten the message or split it. |
| 429 | rate_limited | Too many requests for this method's tier. | Honour the Retry-After header (seconds) and back off, then retry. |
How an API handles change determines how much maintenance it asks for. Slack doesn't use version numbers. There is a single, continuously updated API. When a method is retired, Slack announces it in advance in the changelog, with a removal date, like the two examples below.
Slack's Web API updates continuously, in place. There is no version number to pin to.
The old one-step file upload was retired in favour of a safer two-step upload.
Bot keys moved to specific, per-action permissions.
One unified set of conversation methods replaced Slack's older per-type ones.
There is no version to lock to. Instead, an integration watches Slack's changelog and moves off any retired method on its own schedule.
Slack's API changelog ↗xoxb-…) acts as the app and is best for most automation. A user token (xoxp-…) acts on behalf of a specific person and is required for a few methods like search.messages.channels:history) and the app being added to the channel. Access doesn't flow workspace-wide. The app only sees channels it's in.files.upload was deprecated in 2025. Uploading now happens in two steps instead: files.getUploadURLExternal then files.completeUploadExternal. See the new flow.200 and a body of {"ok": false, "error": "…"}, so the body needs checking, not just the status code. Rate limiting is the exception: it returns 429 with a Retry-After header.chat.postMessage is about one message per second per channel. Going over the limit returns 429; honour the Retry-After header.Bollard AI sits between a team's AI agents and Slack. Grant each agent exactly the access it needs, read or write, channel by channel, and every call is checked and logged.