Slack API in Postman: A 16-Request Collection We Ran With Newman, and the Errors It Catches
How to call the Slack Web API from Postman with a bearer token and variables, plus a 16-request collection we ran against a real workspace with newman: 16 requests, 17 assertions, 0 failures, and the five mistakes it checks.
On this page
To call the Slack Web API from Postman, send requests to https://slack.com/api/<method> and put your token in the Authorization tab as Bearer Token, using a variable such as {{token}}. Send JSON bodies with the header Content-Type: application/json; charset=utf-8, or use x-www-form-urlencoded. On 7 October 2026 we built a 16-request collection that way and ran it against our free-plan test workspace with newman, Postman's command-line runner: 16 requests, 17 assertions, 0 failures, in 5.1 seconds. Five of the requests send something wrong on purpose, and their exact replies are below.
Set up the token and variables
- Create a Slack app at api.slack.com/apps, add the bot scopes you need under OAuth & Permissions, and install it. Copy the
xoxb-Bot User OAuth Token; our bot token guide shows where it appears. - In Postman, create an environment with three variables:
token(thexoxb-value, as a secret),channel(a channel ID such asC0123ABCD) andbot_user(the bot's user ID fromauth.test). - On the collection, set Authorization to Bearer Token with the value
{{token}}, and let each request inherit it. - Invite the bot to the channel, or
chat.postMessagereturnsnot_in_channel.
Our bot had chat:write, chat:write.public, channels:read, channels:history, channels:manage, users:read and team:read. Each request below needs only the scopes its method lists.
A request from the collection
This is the chat.postMessage request from our collection file, in Postman's v2.1 format. The test script saves the message timestamp so the next requests can edit and delete the same message:
{
"info": {
"name": "Slack Web API smoke test",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "chat.postMessage (JSON)",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json; charset=utf-8"
}
],
"url": {
"raw": "https://slack.com/api/chat.postMessage",
"protocol": "https",
"host": [
"slack",
"com"
],
"path": [
"api",
"chat.postMessage"
]
},
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{token}}",
"type": "string"
}
]
},
"body": {
"mode": "raw",
"raw": "{\n \"channel\": \"{{channel}}\",\n \"text\": \"Hello from Postman :wave:\"\n}"
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"const j = pm.response.json();",
"pm.test('ok is true', () => pm.expect(j.ok).to.eql(true));",
"pm.collectionVariables.set('ts', j.ts);"
]
}
}
]
}
],
"variable": [
{
"key": "ts",
"value": ""
}
]
}
The other requests follow the same pattern. In order, the collection runs auth.test, conversations.info, chat.postMessage, chat.update and chat.getPermalink on that message, conversations.history, conversations.setTopic as a form post, users.info, team.info, chat.delete, a second post sent as JSON without a charset and its delete, then four requests that should fail. The message cleans up after itself, so the channel ends with only the topic change.
One thing we noticed in Slack: after chat.update, the bot's message showed the new text, Edited from Postman, without an "(edited)" label in Slack web.
Never appear "away" on Slack again
Cloud-based. No downloads. Works 24/7 even when your laptop is off.
Running it with newman
We ran the collection from a terminal with the environment file:
npx -y newman@6 run slack-smoke.postman_collection.json -e slack-env.json
newman 6.2.2 printed one line per request and this summary:
┌─────────────────────────┬─────────────────────┬────────────────────┐
│ │ executed │ failed │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ iterations │ 1 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ requests │ 16 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ test-scripts │ 16 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ prerequest-scripts │ 0 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ assertions │ 17 │ 0 │
├─────────────────────────┴─────────────────────┴────────────────────┤
│ total run duration: 5.1s │
├────────────────────────────────────────────────────────────────────┤
│ total data received: 10.93kB (approx) │
├────────────────────────────────────────────────────────────────────┤
│ average response time: 309ms [min: 200ms, max: 609ms, s.d.: 123ms] │
└────────────────────────────────────────────────────────────────────┘
Our first run had two failed assertions, because we had guessed two of the error codes wrong. newman listed each one with the expected and the actual value (expected 'missing_scope' to deeply equal 'method_deprecated'), which is how we found the real errors in the table below. Keep the token in the environment file or a CI secret, not in the collection.
Five requests that check mistakes
These five requests send something wrong on purpose. Each test asserts the error we got, so a change in Slack's behavior would fail the run.
| Request | What Slack returned |
|---|---|
Raw JSON body with Postman's default Content-Type: text/plain | invalid_arguments, [ERROR] missing required field: channel, warning missing_charset |
Raw JSON with Content-Type: application/json and no charset | ok: true, but with warning: missing_charset |
auth.test with No Auth | not_authed |
Token as a token query parameter on a GET | invalid_auth |
files.upload with a token that lacks files:write | missing_scope, needed: files:write |
The first one catches most people. In Postman's Body > raw mode the type menu defaults to Text, which sends text/plain. Slack then ignores the body and reports the first missing field, here channel, even though the JSON visibly contains it. Switch the menu to JSON, or add the header yourself.
The token in the query string failed with invalid_auth, not not_authed, so Slack saw a token but would not take it from the URL. Send it in the Authorization header.
files.upload is the old upload method. Without files:write it answered missing_scope before anything else; with the scope, our earlier upload test got method_deprecated. Use files.getUploadURLExternal and files.completeUploadExternal instead.
Slack also publishes its own collection on Postman's API network (the "Slack API" workspace by slackhq). We did not import or run that one for this test.
Stop Jiggling Your Mouse.
Join hundreds of remote workers who never worry about their Slack status. Set it up once, stay green forever.
Related Articles
Slack Spell Check Not Working: The Setting, and the Grammarly Conflict We Measured
Slack has one spell check switch, under Preferences > Language & region. In our test browser it was on, yet Slack web showed no red underlines: the Grammarly extension had set spellcheck to false on the message box. How to check yours.
Slack Block Kit Input Block: Modal Fields, state.values and Inline Errors, Tested
We opened a modal with seven input blocks in a test workspace and captured every payload: what Slack checks before your app sees anything, the exact view_submission state.values, response_action errors, dispatch_action, and input blocks in messages.
Slack Workspace Icon: Size, Crop and Transparency, Tested on a Real Workspace
We uploaded six workspace icons to a test Slack workspace: 100 px, 1024 px, a wide image, a transparent PNG and two oversize files. What Slack accepted, what it stored, and how to remove an icon.