slack-web-api
English | 日本語
Typed async Rust client for every Slack Web API method — all 330 of them, including admin.* — built on reqwest and rustls.
- No OpenSSL: reqwest 0.13 + rustls, HTTP/2 and a shared connection pool
- Request and response types for every method, plus typed Block Kit
- 30 second request timeout by default; HTTP 429 is returned with its
Retry-After, and can be retried for you (max_retries) - Cursor pagination and file upload (the replacement for the retired
files.upload) built in
It covers the Web API only. For Socket Mode or receiving Events API payloads, use another crate.
Installation
[]
= "0.2"
Usage
use ChatPostMessageRequest;
use ;
use SlackClient;
async
Method chat.postMessage becomes chat_post_message, with types ChatPostMessageRequest / ChatPostMessageResponse.
Required arguments go to new(...); optional ones are set with methods of the same name.
Sharing your reqwest::Client
let client = builder
.http_client
.token
.build;
A client you pass keeps its own settings, so give it a timeout: the built-in client uses 30 seconds
(10 seconds to connect), but reqwest::Client::new() has none.
For apps installed in many workspaces, client.with_token("xoxb-other") switches the token while keeping the pool.
Pagination
use ConversationsListRequest;
let mut pages = client.pages;
while let Some = pages.next_page.await
Uploading files
files.upload stopped working on 2025-11-12. upload_files runs files.getUploadURLExternal, the upload and
files.completeUploadExternal for you, uploading several files concurrently.
use ;
client
.upload_files
.await?;
Untyped calls
New methods or arguments that are not in the generated types yet can be called with call_raw:
let value = client.call_raw.await?;
Errors
SlackError::Api means Slack answered "ok": false; err.api_error() returns the code such as channel_not_found.
Details for errors like invalid_blocks are in response_metadata.messages.
Supported APIs
Every method listed at https://docs.slack.dev/reference/methods (330 methods) except files.upload,
which Slack retired; use upload_files instead. The per-method list with Rust function names is in the
api module docs and in llms-full.txt.
| Category | Methods | Examples |
|---|---|---|
agents.* |
2 | agents.sessions.rename, agents.sessions.setStatus |
api.* |
1 | api.test |
apps.* |
23 | apps.activities.list, apps.auth.external.delete, apps.auth.external.get, ... |
assistant.* |
5 | assistant.search.context, assistant.search.info, assistant.threads.setStatus, ... |
auth.* |
3 | auth.revoke, auth.teams.list, auth.test |
blocks.* |
1 | blocks.validate |
bookmarks.* |
4 | bookmarks.add, bookmarks.edit, bookmarks.list, ... |
bots.* |
1 | bots.info |
calls.* |
6 | calls.add, calls.end, calls.info, ... |
canvases.* |
7 | canvases.access.delete, canvases.access.set, canvases.create, ... |
chat.* |
13 | chat.appendStream, chat.delete, chat.deleteScheduledMessage, ... |
conversations.* |
28 | conversations.acceptSharedInvite, conversations.approveSharedInvite, conversations.archive, ... |
dialog.* |
1 | dialog.open |
dnd.* |
5 | dnd.endDnd, dnd.endSnooze, dnd.info, ... |
emoji.* |
1 | emoji.list |
entity.* |
3 | entity.acknowledgeCommentAction, entity.presentComments, entity.presentDetails |
files.* |
14 | files.comments.delete, files.completeUploadExternal, files.delete, ... |
functions.* |
8 | functions.completeError, functions.completeSuccess, functions.distributions.permissions.add, ... |
migration.* |
1 | migration.exchange |
oauth.* |
6 | oauth.access, oauth.v2.access, oauth.v2.beginShortTokenRotation, ... |
openid.* |
2 | openid.connect.token, openid.connect.userInfo |
pins.* |
3 | pins.add, pins.list, pins.remove |
reactions.* |
4 | reactions.add, reactions.get, reactions.list, ... |
reminders.* |
5 | reminders.add, reminders.complete, reminders.delete, ... |
rtm.* |
2 | rtm.connect, rtm.start |
search.* |
3 | search.all, search.files, search.messages |
slackLists.* |
12 | slackLists.access.delete, slackLists.access.set, slackLists.create, ... |
stars.* |
3 | stars.add, stars.list, stars.remove |
team.* |
9 | team.accessLogs, team.billableInfo, team.billing.info, ... |
tooling.* |
1 | tooling.tokens.rotate |
usergroups.* |
7 | usergroups.create, usergroups.disable, usergroups.enable, ... |
users.* |
13 | users.conversations, users.deletePhoto, users.discoverableContacts.lookup, ... |
views.* |
4 | views.open, views.publish, views.push, ... |
workflows.* |
8 | workflows.featured.add, workflows.featured.list, workflows.featured.remove, ... |
admin.* |
121 | admin.analytics.getFile, admin.analytics.messages.activity, admin.analytics.messages.metadata, ... |
Block Kit: every block, block element, rich text element and composition object, plus legacy attachments,
views (modal / home) and message metadata, in slack_web_api::blocks.
How the response types are built
Response types are inferred from the documented response examples of all methods, and the core objects
(Message, Conversation, User, File, ...) are shared across methods. Every field is optional (Option or an empty Vec),
and scalar fields are read leniently: Slack sometimes returns the same field as a string in one place and a number in
another, and that must not fail the whole response. Unknown fields are skipped; use call_raw to see everything.
A test calls every method against a mock server returning its documented examples and checks no value is lost.
Development
RUSTDOCFLAGS="-D warnings"
SLACK_BOT_TOKEN=xoxb-...
cargo test never calls Slack: every method is exercised against a mock server that returns the documented
response examples, and the test checks that no value is lost when reading them.
Live tests
tests/live.rs talks to the real Slack API. The tests are #[ignore]d, so cargo test and CI skip them.
Run them with a bot token (chat:write, channels:read, channels:history, files:write, users:read) and a
channel the bot has joined; they post, update and delete one message and upload and delete two files:
SLACK_BOT_TOKEN=xoxb-... SLACK_TEST_CHANNEL=C0123456789 \
They check what a mock cannot: that Slack accepts the form bodies this crate builds, that the upload flow works end to end, that real errors are classified — and they print response fields the typed model does not cover yet.
Changes are recorded in CHANGELOG.md.
Regenerating the types
The types are generated in codegen/ from the Markdown version of the official docs (docs.slack.dev).
# Save each .md listed in docs.slack.dev/reference/methods.md into <dir>/m and the object pages into <dir>/obj, then:
&&
License
MIT