集成

Slack

通过托管 OAuth 代理调用 Slack API,实现发消息、管频道、列用户和定时投递。

它能做什么

通过托管 OAuth 代理访问 Slack,自动注入认证令牌。提供 CLI 命令和 HTTP 接口,支持发送消息、回复帖子线程、定时消息、列出与管理频道、邀请用户、查看会话历史等操作。所有写入操作执行前需经用户明确同意。可同时接入多个 Slack 工作区,并通过 connection ID 区分请求目标。

什么时候用它

  • 向频道发送消息或在帖子线程中回复
  • 列出频道、成员并查看历史消息
  • 设置定时消息,稍后自动投递
  • 按需创建、重命名或归档频道

技能文档

Slack

Access the Slack API with managed OAuth authentication. Send messages, manage channels, list users, and automate Slack workflows.

Quick Start

CLI:

maton slack message send --channel C0123456789 --text 'Hello from Maton!'
maton api '/slack/api/chat.postMessage'

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'channel': 'C0123456789', 'text': 'Hello from Maton!'}).encode()
req = urllib.request.Request('https://api.maton.ai/slack/api/chat.postMessage', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://api.maton.ai/slack/{method}

Maton proxies requests to slack.com and automatically injects your OAuth token.

Installation

NPM:

npm install -g @maton/cli

Homebrew:

brew install maton-ai/cli/maton

Authentication

CLI:

maton login                          # Opens browser for API key
maton login --interactive            # Skip browser, paste API key directly
maton whoami                         # Show current auth state

Manual:

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key
  4. Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"

Connection Management

Manage your Slack OAuth connections at https://api.maton.ai.

List Connections

CLI:

maton connection list slack --status ACTIVE
maton api -X GET /connections -f app=slack -f status=ACTIVE

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=slack&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Connection

CLI:

maton connection create slack
maton api /connections -f app=slack

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'slack'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Connection

CLI:

maton connection view {connection_id}
maton api /connections/{connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "connection": {
    "connection_id": "{connection_id}",
    "status": "ACTIVE",
    "creation_time": "2025-12-08T07:20:53.488460Z",
    "last_updated_time": "2026-01-31T20:03:32.593153Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "slack",
    "metadata": {}
  }
}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

CLI:

maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Specifying Connection

If you have multiple Slack connections, specify which one to use:

CLI:

maton slack message send --channel C0123456789 --text 'Hello!' --connection {connection_id}
maton api /slack/api/chat.postMessage --connection {connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'channel': 'C0123456789', 'text': 'Hello!'}).encode()
req = urllib.request.Request('https://api.maton.ai/slack/api/chat.postMessage', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If you have multiple connections, always specify the connection to ensure requests go to the intended account.

Security & Permissions

  • Access is scoped to messages, channels, users, files, and reactions within the connected Slack account.
  • All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.

API Reference

Authentication

Auth Test

GET /slack/api/auth.test

Returns current user and team info.

Example:

maton slack whoami

Messages

Post Message

POST /slack/api/chat.postMessage
Content-Type: application/json

{
  "channel": "C0123456789",
  "text": "Hello, world!"
}

Example:

maton slack message send --channel C0123456789 --text 'Hello, world!'

With blocks:

POST /slack/api/chat.postMessage
Content-Type: application/json

{
  "channel": "C0123456789",
  "blocks": [
    {"type": "section", "text": {"type": "mrkdwn", "text": "*Bold* and _italic_"}}
  ]
}

Example:

maton slack message send --channel C0123456789 --blocks '[{"type":"section","text":{"type":"mrkdwn","text":"*Bold* and _italic_"}}]'

Post /me-style Message

maton slack message me --channel C0123456789 --text 'is deploying'

Post Thread Reply

POST /slack/api/chat.postMessage
Content-Type: application/json

{
  "channel": "C0123456789",
  "thread_ts": "1234567890.123456",
  "text": "This is a reply in a thread"
}

Example:

maton slack message reply --channel C0123456789 --thread-ts 1234567890.123456 --text 'This is a reply in a thread'

Update Message

POST /slack/api/chat.update
Content-Type: application/json

{
  "channel": "C0123456789",
  "ts": "1234567890.123456",
  "text": "Updated message"
}

Example:

maton slack message update --channel C0123456789 --ts 1234567890.123456 --text 'Updated message'

Delete Message

POST /slack/api/chat.delete
Content-Type: application/json

{
  "channel": "C0123456789",
  "ts": "1234567890.123456"
}

Example:

maton slack message delete --channel C0123456789 --ts 1234567890.123456

Schedule Message

POST /slack/api/chat.scheduleMessage
Content-Type: application/json

{
  "channel": "C0123456789",
  "text": "Scheduled message",
  "post_at": 1734567890
}

Example:

maton slack schedule create --channel C0123456789 --text 'Scheduled message' --post-at 1734567890

List Scheduled Messages

GET /slack/api/chat.scheduledMessages.list

Example:

maton slack schedule list

Delete Scheduled Message

POST /slack/api/chat.deleteScheduledMessage
Content-Type: application/json

{
  "channel": "C0123456789",
  "scheduled_message_id": "Q1234567890"
}

Example:

maton slack schedule delete --channel C0123456789 --id Q1234567890
GET /slack/api/chat.getPermalink?channel=C0123456789&message_ts=1234567890.123456

Example:

maton slack message permalink --channel C0123456789 --message-ts 1234567890.123456

Conversations (Channels)

List Channels

GET /slack/api/conversations.list?types=public_channel,private_channel&limit=100

Types: public_channel, private_channel, im, mpim

Example:

maton slack channel list --types public_channel,private_channel --limit 100

Get Channel Info

GET /slack/api/conversations.info?channel=C0123456789

Example:

maton slack channel view C0123456789

Get Channel History

GET /slack/api/conversations.history?channel=C0123456789&limit=100

Example:

maton slack message list --channel C0123456789 --limit 100

With time range:

GET /slack/api/conversations.history?channel=C0123456789&oldest=1234567890&latest=1234567899

Example:

maton slack message list --channel C0123456789 --oldest 1234567890 --latest 1234567899

Get Thread Replies

GET /slack/api/conversations.replies?channel=C0123456789&ts=1234567890.123456

Example:

maton slack message replies --channel C0123456789 --ts 1234567890.123456

Get Channel Members

GET /slack/api/conversations.members?channel=C0123456789&limit=100

Example:

maton slack channel members C0123456789 --limit 100

Create Channel

POST /slack/api/conversations.create
Content-Type: application/json

{
  "name": "new-channel-name",
  "is_private": false
}

Example:

maton slack channel create --name new-channel-name

Join Channel

POST /slack/api/conversations.join
Content-Type: application/json

{
  "channel": "C0123456789"
}

Example:

maton slack channel join C0123456789

Leave Channel

POST /slack/api/conversations.leave
Content-Type: application/json

{
  "channel": "C0123456789"
}

Example:

maton slack channel leave C0123456789

Archive Channel

POST /slack/api/conversations.archive
Content-Type: application/json

{
  "channel": "C0123456789"
}

Example:

maton slack channel archive C0123456789

Unarchive Channel

POST /slack/api/conversations.unarchive
Content-Type: application/json

{
  "channel": "C0123456789"
}

Example:

maton slack channel unarchive C0123456789

Rename Channel

POST /slack/api/conversations.rename
Content-Type: application/json

{
  "channel": "C0123456789",
  "name": "new-name"
}

Example:

maton slack channel rename C0123456789 --name new-name

Set Channel Topic

POST /slack/api/conversations.setTopic
Content-Type: application/json

{
  "channel": "C0123456789",
  "topic": "Channel topic here"
}

Example:

maton slack channel set-topic C0123456789 --topic 'Channel topic here'

Set Channel Purpose

POST /slack/api/conversations.setPurpose
Content-Type: application/json

{
  "channel": "C0123456789",
  "purpose": "Channel purpose here"
}

Example:

maton slack channel set-purpose C0123456789 --purpose 'Channel purpose here'

Invite to Channel

POST /slack/api/conversations.invite
Content-Type: application/json

{
  "channel": "C0123456789",
  "users": "U0123456789,U9876543210"
}

Example:

maton slack channel invite C0123456789 --users U0123456789,U9876543210

Kick from Channel

POST /slack/api/conversations.kick
Content-Type: application/json

{
  "channel": "C0123456789",
  "user": "U0123456789"
}

Example:

maton slack channel kick C0123456789 --user U0123456789

Mark Channel Read

POST /slack/api/conversations.mark
Content-Type: application/json

{
  "channel": "C0123456789",
  "ts": "1234567890.123456"
}

Example:

maton slack channel mark C0123456789 --ts 1234567890.123456

Direct Messages

Open DM Conversation

POST /slack/api/conversations.open
Content-Type: application/json

{
  "users": "U0123456789"
}

Example:

maton slack conversation open --users U0123456789

For group DM:

POST /slack/api/conversations.open
Content-Type: application/json

{
  "users": "U0123456789,U9876543210"
}

Example:

maton slack conversation open --users U0123456789,U9876543210

List DM Channels

GET /slack/api/conversations.list?types=im

Example:

maton slack channel list --types im

List Group DM Channels

GET /slack/api/conversations.list?types=mpim

Example:

maton slack channel list --types mpim

My Conversations

GET /slack/api/users.conversations?limit=100

Example:

maton slack conversation list --limit 100

Users

List Users

GET /slack/api/users.list?limit=100

Example:

maton slack user list --limit 100

Get User Info

GET /slack/api/users.info?user=U0123456789

Example:

maton slack user view U0123456789

Get User Presence

GET /slack/api/users.getPresence?user=U0123456789

Example:

maton slack user presence U0123456789

Lookup User by Email

GET /slack/api/[email protected]

Example:

maton slack user lookup --email [email protected]

Reactions

Add Reaction

POST /slack/api/reactions.add
Content-Type: application/json

{
  "channel": "C0123456789",
  "name": "thumbsup",
  "timestamp": "1234567890.123456"
}

Example:

maton slack reaction add --channel C0123456789 --ts 1234567890.123456 --emoji thumbsup

Remove Reaction

POST /slack/api/reactions.remove
Content-Type: application/json

{
  "channel": "C0123456789",
  "name": "thumbsup",
  "timestamp": "1234567890.123456"
}

Example:

maton slack reaction remove --channel C0123456789 --ts 1234567890.123456 --emoji thumbsup

Get Reactions on Message

GET /slack/api/reactions.get?channel=C0123456789&timestamp=1234567890.123456

Example:

maton slack reaction get --channel C0123456789 --ts 1234567890.123456

List My Reactions

GET /slack/api/reactions.list?limit=100

Example:

maton slack reaction list --limit 100

Stars

List Stars

GET /slack/api/stars.list?limit=100

Example:

maton slack star list --limit 100

Add Star

POST /slack/api/stars.add
Content-Type: application/json

{
  "channel": "C0123456789",
  "timestamp": "1234567890.123456"
}

Example:

maton slack star add --channel C0123456789 --ts 1234567890.123456

Remove Star

POST /slack/api/stars.remove
Content-Type: application/json

{
  "channel": "C0123456789",
  "timestamp": "1234567890.123456"
}

Example:

maton slack star remove --channel C0123456789 --ts 1234567890.123456

Pins

List Pins

GET /slack/api/pins.list?channel=C0123456789

Example:

maton slack pin list C0123456789

Add Pin

POST /slack/api/pins.add
Content-Type: application/json

{
  "channel": "C0123456789",
  "timestamp": "1234567890.123456"
}

Example:

maton slack pin add --channel C0123456789 --ts 1234567890.123456

Remove Pin

POST /slack/api/pins.remove
Content-Type: application/json

{
  "channel": "C0123456789",
  "timestamp": "1234567890.123456"
}

Example:

maton slack pin remove --channel C0123456789 --ts 1234567890.123456

Bookmarks

List Bookmarks

GET /slack/api/bookmarks.list?channel_id=C0123456789

Example:

maton slack bookmark list --channel C0123456789

Add Bookmark

POST /slack/api/bookmarks.add
Content-Type: application/json

{
  "channel_id": "C0123456789",
  "title": "Team Handbook",
  "type": "link",
  "link": "https://example.com/handbook"
}

Example:

maton slack bookmark add --channel C0123456789 --title 'Team Handbook' --type link --link https://example.com/handbook

Edit Bookmark

POST /slack/api/bookmarks.edit
Content-Type: application/json

{
  "bookmark_id": "Bk0123456789",
  "channel_id": "C0123456789",
  "title": "Updated Title",
  "link": "https://example.com/new"
}

Example:

maton slack bookmark edit --channel C0123456789 --bookmark-id Bk0123456789 --title 'Updated Title' --link https://example.com/new

Remove Bookmark

POST /slack/api/bookmarks.remove
Content-Type: application/json

{
  "bookmark_id": "Bk0123456789",
  "channel_id": "C0123456789"
}

Example:

maton slack bookmark remove --channel C0123456789 --bookmark-id Bk0123456789

Bots

Get Bot Info

GET /slack/api/bots.info?bot=B0123456789

Example:

maton slack bot view B0123456789

Note: this expects the B-prefixed bot ID (from bot_id on a message), not the bot's U-prefixed user ID. Passing a U… ID returns bot_not_found.


Files

List Files

GET /slack/api/files.list?count=100

Filter by channel, user, or file types:

GET /slack/api/files.list?channel=C0123456789&user=U0123456789&types=images,pdfs

Example:

maton slack file list --count 100
maton slack file list --channel C0123456789 --user U0123456789 --types images,pdfs

Upload File

POST /slack/api/files.upload
Content-Type: multipart/form-data

channels=C0123456789
content=file content here
filename=example.txt
title=Example File

Upload File v2 (Get Upload URL)

GET /slack/api/files.getUploadURLExternal?filename=example.txt&length=1024

Complete File Upload

POST /slack/api/files.completeUploadExternal
Content-Type: application/json

{
  "files": [{"id": "F0123456789", "title": "My File"}],
  "channel_id": "C0123456789"
}

Example:

maton slack file upload --file ./example.txt --channel C0123456789 --title 'My File'

Delete File

POST /slack/api/files.delete
Content-Type: application/json

{
  "file": "F0123456789"
}

Example:

maton slack file delete F0123456789

Get File Info

GET /slack/api/files.info?file=F0123456789

Example:

maton slack file view F0123456789

Search Messages

GET /slack/api/search.messages?query=keyword

Example:

maton slack search messages 'keyword'

Search Files

GET /slack/api/search.files?query=keyword

Note: search.files matches against filename and title, not file body content. Newly uploaded files may take a moment to appear in results due to indexing lag.


Code Examples

CLI

# Send a message to a channel
maton slack message send --channel C0123456789 --text 'Hello team'

# List channels
maton slack channel list --types public_channel,private_channel

# Look up a user by email
maton slack user lookup --email [email protected]

# Add a reaction to a message
maton slack reaction add --channel C012 --ts 1700000000.000100 --emoji thumbsup

JavaScript

const response = await fetch('https://api.maton.ai/slack/api/chat.postMessage', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${process.env.MATON_API_KEY}`
  },
  body: JSON.stringify({ channel: 'C0123456', text: 'Hello!' })
});
const result = await response.json();
console.log(result);

Python

import os
import requests

response = requests.post(
    'https://api.maton.ai/slack/api/chat.postMessage',
    headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
    json={'channel': 'C0123456', 'text': 'Hello!'}
)
print(response.json())

Notes

  • Channel IDs: C (public), G (private/group), D (DM)
  • User IDs start with U, Bot IDs start with B, Team IDs start with T
  • Message timestamps (ts) are unique identifiers
  • Use mrkdwn type for Slack-flavored markdown formatting
  • Thread replies use thread_ts to reference the parent message
  • Cursor-based pagination: use cursor from response_metadata.next_cursor

Shell Notes

  • IMPORTANT: When using curl commands, use curl -g when URLs contain brackets (fields[], sort[], records[]) to disable glob parsing
  • IMPORTANT: When piping curl output to jq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.

Error Handling

StatusMeaning
400Missing Slack connection
401Invalid or missing Maton API key
429Rate limited (10 req/sec per account)
4xx/5xxPassthrough error from Slack API

Missing Scope Errors: If you encounter missing_scope errors, contact Maton Support to request additional scopes for your connection.

Troubleshooting: API Key Issues

CLI:

  1. Check your auth state:
maton whoami
  1. Verify the API key is valid by listing connections:
maton connection list

Manual:

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with slack. For example:
  • Correct: https://api.maton.ai/slack/api/chat.postMessage
  • Incorrect: https://api.maton.ai/api/chat.postMessage

Resources

常见问题

Slack 凭证如何管理?
请求通过代理转发到 slack.com,OAuth 令牌由系统自动注入,用户只需通过 Maton CLI 登录流程或设置 MATON_API_KEY 环境变量完成一次认证。
能否接入多个 Slack 工作区?
可以,支持创建多个连接,每次请求通过 connection ID 指定目标工作区(HTTP 用 Maton-Connection 头,CLI 用 --connection 参数)。
写入操作是否需要用户确认?
是的,文档明确说明所有创建、更新、删除操作执行前都需获得用户明确同意。

相关技能

通过托管 OAuth 代理连接 Notion 工作区,支持搜索、数据库查询与读取,写入需用户确认。

339 次安装8 星标

通过托管 OAuth 接入 GitHub REST API,覆盖仓库、Issue、PR、Commit、分支与用户等接口。

595 次安装47 星标

通过 OAuth 认证网关管理 Stripe 客户、订阅、发票、产品、价格和支付。

720 次安装29 星标

通过托管 OAuth 连接 Google Tasks,统一 API 完成任务列表与任务的读写管理。

252 次安装10 星标

通过托管 OAuth 调用 Google Docs API,实现文档创建、读写与样式管理。

278 次安装8 星标

通过托管 OAuth 调用 LinkedIn REST API,覆盖发文、个人资料、广告账户与广告库。

410 次安装45 星标