slack

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Slack API Emulator

Slack API Emulator

Fully stateful Slack Web API emulation with channels, messages, threads, reactions, OAuth v2, and incoming webhooks. State changes dispatch
event_callback
payloads to configured webhook URLs.
具备完整状态的Slack Web API模拟器,支持频道、消息、线程、reactions、OAuth v2和传入webhook。状态变更时会将
event_callback
负载发送到已配置的webhook URL。

Start

启动

bash
undefined
bash
undefined

Slack only

仅启动Slack模拟器

npx emulate --service slack
npx emulate --service slack

Default port (when run alone)

默认端口(单独运行时)


Or programmatically:

```typescript
import { createEmulator } from 'emulate'

const slack = await createEmulator({ service: 'slack', port: 4003 })
// slack.url === 'http://localhost:4003'

也可通过代码方式启动:

```typescript
import { createEmulator } from 'emulate'

const slack = await createEmulator({ service: 'slack', port: 4003 })
// slack.url === 'http://localhost:4003'

Auth

认证

Pass tokens as
Authorization: Bearer <token>
. All Web API endpoints require authentication.
bash
curl -X POST http://localhost:4003/api/auth.test \
  -H "Authorization: Bearer test_token_admin"
When no token is provided, requests fall back to the first seeded user.
通过
Authorization: Bearer <token>
传递令牌。所有Web API端点均需要认证。
bash
curl -X POST http://localhost:4003/api/auth.test \
  -H "Authorization: Bearer test_token_admin"
未提供令牌时,请求会自动使用第一个预配置用户。

Pointing Your App at the Emulator

将应用指向模拟器

Environment Variable

环境变量

bash
SLACK_EMULATOR_URL=http://localhost:4003
bash
SLACK_EMULATOR_URL=http://localhost:4003

Slack SDK / Bolt

Slack SDK / Bolt

typescript
import { WebClient } from '@slack/web-api'

const client = new WebClient(token, {
  slackApiUrl: `${process.env.SLACK_EMULATOR_URL}/api/`,
})
typescript
import { WebClient } from '@slack/web-api'

const client = new WebClient(token, {
  slackApiUrl: `${process.env.SLACK_EMULATOR_URL}/api/`,
})

OAuth URL Mapping

OAuth URL映射

Real Slack URLEmulator URL
https://slack.com/oauth/v2/authorize
$SLACK_EMULATOR_URL/oauth/v2/authorize
https://slack.com/api/oauth.v2.access
$SLACK_EMULATOR_URL/api/oauth.v2.access
真实Slack URL模拟器URL
https://slack.com/oauth/v2/authorize
$SLACK_EMULATOR_URL/oauth/v2/authorize
https://slack.com/api/oauth.v2.access
$SLACK_EMULATOR_URL/api/oauth.v2.access

Auth.js / NextAuth.js

Auth.js / NextAuth.js

typescript
{
  id: 'slack',
  name: 'Slack',
  type: 'oauth',
  authorization: {
    url: `${process.env.SLACK_EMULATOR_URL}/oauth/v2/authorize`,
    params: { scope: 'chat:write,channels:read,users:read' },
  },
  token: {
    url: `${process.env.SLACK_EMULATOR_URL}/api/oauth.v2.access`,
  },
  clientId: process.env.SLACK_CLIENT_ID,
  clientSecret: process.env.SLACK_CLIENT_SECRET,
}
typescript
{
  id: 'slack',
  name: 'Slack',
  type: 'oauth',
  authorization: {
    url: `${process.env.SLACK_EMULATOR_URL}/oauth/v2/authorize`,
    params: { scope: 'chat:write,channels:read,users:read' },
  },
  token: {
    url: `${process.env.SLACK_EMULATOR_URL}/api/oauth.v2.access`,
  },
  clientId: process.env.SLACK_CLIENT_ID,
  clientSecret: process.env.SLACK_CLIENT_SECRET,
}

Seed Config

预配置文件

yaml
slack:
  team:
    name: My Workspace
    domain: my-workspace
  users:
    - name: developer
      real_name: Developer
      email: dev@example.com
      is_admin: true
    - name: designer
      real_name: Designer
      email: designer@example.com
  channels:
    - name: general
      topic: General discussion
    - name: engineering
      topic: Engineering discussions
      is_private: true
  bots:
    - name: my-bot
  oauth_apps:
    - client_id: "12345.67890"
      client_secret: example_client_secret
      name: My Slack App
      redirect_uris:
        - http://localhost:3000/api/auth/callback/slack
  incoming_webhooks:
    - channel: general
      label: CI Notifications
  signing_secret: my_signing_secret
When no OAuth apps are configured, the emulator accepts any
client_id
. With apps configured, strict validation is enforced for
client_id
,
client_secret
, and
redirect_uri
.
yaml
slack:
  team:
    name: My Workspace
    domain: my-workspace
  users:
    - name: developer
      real_name: Developer
      email: dev@example.com
      is_admin: true
    - name: designer
      real_name: Designer
      email: designer@example.com
  channels:
    - name: general
      topic: General discussion
    - name: engineering
      topic: Engineering discussions
      is_private: true
  bots:
    - name: my-bot
  oauth_apps:
    - client_id: "12345.67890"
      client_secret: example_client_secret
      name: My Slack App
      redirect_uris:
        - http://localhost:3000/api/auth/callback/slack
  incoming_webhooks:
    - channel: general
      label: CI Notifications
  signing_secret: my_signing_secret
未配置OAuth应用时,模拟器接受任意
client_id
。配置应用后,会严格验证
client_id
client_secret
redirect_uri

API Endpoints

API端点

Auth

认证

bash
undefined
bash
undefined

Test authentication

测试认证

curl -X POST http://localhost:4003/api/auth.test
-H "Authorization: Bearer $TOKEN"
undefined
curl -X POST http://localhost:4003/api/auth.test
-H "Authorization: Bearer $TOKEN"
undefined

Chat

聊天

bash
undefined
bash
undefined

Post message

发送消息

curl -X POST http://localhost:4003/api/chat.postMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "Hello from the emulator!"}'
curl -X POST http://localhost:4003/api/chat.postMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "Hello from the emulator!"}'

Post threaded reply

发送线程回复

curl -X POST http://localhost:4003/api/chat.postMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "Thread reply", "thread_ts": "1234567890.123456"}'
curl -X POST http://localhost:4003/api/chat.postMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "Thread reply", "thread_ts": "1234567890.123456"}'

Update message

更新消息

curl -X POST http://localhost:4003/api/chat.update
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "ts": "1234567890.123456", "text": "Updated message"}'
curl -X POST http://localhost:4003/api/chat.update
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "ts": "1234567890.123456", "text": "Updated message"}'

Delete message

删除消息

curl -X POST http://localhost:4003/api/chat.delete
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "ts": "1234567890.123456"}'
curl -X POST http://localhost:4003/api/chat.delete
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "ts": "1234567890.123456"}'

/me message

/me 格式消息

curl -X POST http://localhost:4003/api/chat.meMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "is thinking..."}'
undefined
curl -X POST http://localhost:4003/api/chat.meMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "is thinking..."}'
undefined

Conversations

会话

bash
undefined
bash
undefined

List channels (cursor pagination)

列出频道(游标分页)

curl -X POST http://localhost:4003/api/conversations.list
-H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:4003/api/conversations.list
-H "Authorization: Bearer $TOKEN"

Get channel info

获取频道信息

curl -X POST http://localhost:4003/api/conversations.info
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'
curl -X POST http://localhost:4003/api/conversations.info
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'

Create channel

创建频道

curl -X POST http://localhost:4003/api/conversations.create
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"name": "new-channel", "is_private": false}'
curl -X POST http://localhost:4003/api/conversations.create
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"name": "new-channel", "is_private": false}'

Channel history (top-level messages only)

频道历史记录(仅顶层消息)

curl -X POST http://localhost:4003/api/conversations.history
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'
curl -X POST http://localhost:4003/api/conversations.history
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'

Thread replies

线程回复列表

curl -X POST http://localhost:4003/api/conversations.replies
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "ts": "1234567890.123456"}'
curl -X POST http://localhost:4003/api/conversations.replies
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "ts": "1234567890.123456"}'

Join / leave channel

加入/退出频道

curl -X POST http://localhost:4003/api/conversations.join
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'
curl -X POST http://localhost:4003/api/conversations.join
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'

List members

列出成员

curl -X POST http://localhost:4003/api/conversations.members
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'
undefined
curl -X POST http://localhost:4003/api/conversations.members
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001"}'
undefined

Users

用户

bash
undefined
bash
undefined

List users (cursor pagination)

列出用户(游标分页)

curl -X POST http://localhost:4003/api/users.list
-H "Authorization: Bearer $TOKEN"
curl -X POST http://localhost:4003/api/users.list
-H "Authorization: Bearer $TOKEN"

Get user info

获取用户信息

curl -X POST http://localhost:4003/api/users.info
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"user": "U000000001"}'
curl -X POST http://localhost:4003/api/users.info
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"user": "U000000001"}'

Lookup by email

通过邮箱查找用户

curl -X POST http://localhost:4003/api/users.lookupByEmail
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"email": "dev@example.com"}'
undefined
curl -X POST http://localhost:4003/api/users.lookupByEmail
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"email": "dev@example.com"}'
undefined

Reactions

表情反应

bash
undefined
bash
undefined

Add reaction

添加表情反应

curl -X POST http://localhost:4003/api/reactions.add
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "1234567890.123456", "name": "thumbsup"}'
curl -X POST http://localhost:4003/api/reactions.add
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "1234567890.123456", "name": "thumbsup"}'

Remove reaction

移除表情反应

curl -X POST http://localhost:4003/api/reactions.remove
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "1234567890.123456", "name": "thumbsup"}'
curl -X POST http://localhost:4003/api/reactions.remove
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "1234567890.123456", "name": "thumbsup"}'

Get reactions

获取表情反应

curl -X POST http://localhost:4003/api/reactions.get
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "1234567890.123456"}'
undefined
curl -X POST http://localhost:4003/api/reactions.get
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "1234567890.123456"}'
undefined

Team

团队

bash
undefined
bash
undefined

Get workspace info

获取工作区信息

curl -X POST http://localhost:4003/api/team.info
-H "Authorization: Bearer $TOKEN"
undefined
curl -X POST http://localhost:4003/api/team.info
-H "Authorization: Bearer $TOKEN"
undefined

Bots

机器人

bash
undefined
bash
undefined

Get bot info

获取机器人信息

curl -X POST http://localhost:4003/api/bots.info
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"bot": "B000000001"}'
undefined
curl -X POST http://localhost:4003/api/bots.info
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"bot": "B000000001"}'
undefined

Incoming Webhooks

传入Webhook

bash
undefined
bash
undefined

Post via incoming webhook

通过传入Webhook发送消息

curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Deployment complete!"}'
curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Deployment complete!"}'

Post to a specific channel

发送到指定频道

curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Alert!", "channel": "C000000002"}'
curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Alert!", "channel": "C000000002"}'

Post threaded webhook message

发送线程Webhook消息

curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Thread update", "thread_ts": "1234567890.123456"}'
undefined
curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Thread update", "thread_ts": "1234567890.123456"}'
undefined

OAuth

OAuth

bash
undefined
bash
undefined

Authorize (browser flow, shows user picker)

授权(浏览器流程,显示用户选择器)

GET /oauth/v2/authorize?client_id=...&redirect_uri=...&scope=...&state=...

GET /oauth/v2/authorize?client_id=...&redirect_uri=...&scope=...&state=...

Token exchange

令牌交换

curl -X POST http://localhost:4003/api/oauth.v2.access
-H "Content-Type: application/json"
-d '{"client_id": "12345.67890", "client_secret": "example_client_secret", "code": "<code>"}'

Returns a Slack-style response:

```json
{
  "ok": true,
  "access_token": "xoxb-...",
  "token_type": "bot",
  "bot_user_id": "B000000001",
  "team": { "id": "T000000001", "name": "Emulate" },
  "authed_user": { "id": "U000000001" }
}
curl -X POST http://localhost:4003/api/oauth.v2.access
-H "Content-Type: application/json"
-d '{"client_id": "12345.67890", "client_secret": "example_client_secret", "code": "<code>"}'

返回Slack格式的响应:

```json
{
  "ok": true,
  "access_token": "xoxb-...",
  "token_type": "bot",
  "bot_user_id": "B000000001",
  "team": { "id": "T000000001", "name": "Emulate" },
  "authed_user": { "id": "U000000001" }
}

Event Dispatching

事件分发

When messages are posted or reactions are added/removed, the emulator dispatches
event_callback
payloads to configured webhook URLs. These payloads match Slack's Events API format:
  • message
    events on
    chat.postMessage
    ,
    chat.update
    ,
    chat.delete
  • reaction_added
    /
    reaction_removed
    events on
    reactions.add
    /
    reactions.remove
  • message
    with
    subtype: bot_message
    on incoming webhook posts
当消息发送或表情反应添加/移除时,模拟器会将
event_callback
负载发送到已配置的webhook URL。这些负载与Slack Events API格式一致:
  • chat.postMessage
    chat.update
    chat.delete
    操作触发
    message
    事件
  • reactions.add
    /
    reactions.remove
    操作触发
    reaction_added
    /
    reaction_removed
    事件
  • 传入webhook发送消息时触发带有
    subtype: bot_message
    message
    事件

Common Patterns

常见使用场景

Post Messages and React

发送消息并添加反应

bash
TOKEN="test_token_admin"
BASE="http://localhost:4003"
bash
TOKEN="test_token_admin"
BASE="http://localhost:4003"

Post a message

发送消息

curl -X POST $BASE/api/chat.postMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "Hello!"}'
curl -X POST $BASE/api/chat.postMessage
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "text": "Hello!"}'

React to it (use the ts from the response)

添加反应(使用响应中的ts值)

curl -X POST $BASE/api/reactions.add
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "<ts>", "name": "wave"}'
undefined
curl -X POST $BASE/api/reactions.add
-H "Authorization: Bearer $TOKEN"
-H "Content-Type: application/json"
-d '{"channel": "C000000001", "timestamp": "<ts>", "name": "wave"}'
undefined

OAuth Flow

OAuth流程

  1. Redirect user to
    $SLACK_EMULATOR_URL/oauth/v2/authorize?client_id=...&redirect_uri=...&scope=chat:write,channels:read&state=...
  2. User picks a seeded user on the emulator's UI
  3. Emulator redirects back with
    ?code=...&state=...
  4. Exchange code for token via
    POST /api/oauth.v2.access
  5. Use
    xoxb-
    token to call Web API endpoints
  1. 将用户重定向到
    $SLACK_EMULATOR_URL/oauth/v2/authorize?client_id=...&redirect_uri=...&scope=chat:write,channels:read&state=...
  2. 用户在模拟器UI中选择一个预配置用户
  3. 模拟器重定向回应用并携带
    ?code=...&state=...
  4. 通过
    POST /api/oauth.v2.access
    交换令牌
  5. 使用
    xoxb-
    令牌调用Web API端点

CI Notifications via Webhook

通过Webhook发送CI通知

bash
undefined
bash
undefined

Use the default incoming webhook

使用默认传入Webhook

curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Build passed on main"}'
undefined
curl -X POST http://localhost:4003/services/T000000001/B000000001/X000000001
-H "Content-Type: application/json"
-d '{"text": "Build passed on main"}'
undefined