Install
openclaw skills install slack-apiSlack API integration with managed OAuth. Send messages, manage channels, search conversations, and interact with Slack workspaces. Use this skill when users want to post messages, list channels, get user info, or automate Slack workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).
openclaw skills install slack-apiAccess the Slack API with managed OAuth authentication. Send messages, manage channels, list users, and automate Slack workflows.
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
https://api.maton.ai/slack/{method}
Maton proxies requests to slack.com and automatically injects your OAuth token.
NPM:
npm install -g @maton-ai/cli
Homebrew:
brew install maton-ai/cli/maton
CLI:
maton login # Opens browser for API key
maton login --interactive # Skip browser, paste API key directly
maton whoami # Show current auth state
Manual:
MATON_API_KEY:export MATON_API_KEY="YOUR_API_KEY"
Manage your Slack OAuth connections at https://api.maton.ai.
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
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
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.
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
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.
GET /slack/api/auth.test
Returns current user and team info.
Example:
maton slack whoami
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_"}}]'
maton slack message me --channel C0123456789 --text 'is deploying'
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'
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'
POST /slack/api/chat.delete
Content-Type: application/json
{
"channel": "C0123456789",
"ts": "1234567890.123456"
}
Example:
maton slack message delete --channel C0123456789 --ts 1234567890.123456
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
GET /slack/api/chat.scheduledMessages.list
Example:
maton slack schedule list
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
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 /slack/api/conversations.info?channel=C0123456789
Example:
maton slack channel view C0123456789
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 /slack/api/conversations.replies?channel=C0123456789&ts=1234567890.123456
Example:
maton slack message replies --channel C0123456789 --ts 1234567890.123456
GET /slack/api/conversations.members?channel=C0123456789&limit=100
Example:
maton slack channel members C0123456789 --limit 100
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
POST /slack/api/conversations.join
Content-Type: application/json
{
"channel": "C0123456789"
}
Example:
maton slack channel join C0123456789
POST /slack/api/conversations.leave
Content-Type: application/json
{
"channel": "C0123456789"
}
Example:
maton slack channel leave C0123456789
POST /slack/api/conversations.archive
Content-Type: application/json
{
"channel": "C0123456789"
}
Example:
maton slack channel archive C0123456789
POST /slack/api/conversations.unarchive
Content-Type: application/json
{
"channel": "C0123456789"
}
Example:
maton slack channel unarchive C0123456789
POST /slack/api/conversations.rename
Content-Type: application/json
{
"channel": "C0123456789",
"name": "new-name"
}
Example:
maton slack channel rename C0123456789 --name new-name
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'
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'
POST /slack/api/conversations.invite
Content-Type: application/json
{
"channel": "C0123456789",
"users": "U0123456789,U9876543210"
}
Example:
maton slack channel invite C0123456789 --users U0123456789,U9876543210
POST /slack/api/conversations.kick
Content-Type: application/json
{
"channel": "C0123456789",
"user": "U0123456789"
}
Example:
maton slack channel kick C0123456789 --user U0123456789
POST /slack/api/conversations.mark
Content-Type: application/json
{
"channel": "C0123456789",
"ts": "1234567890.123456"
}
Example:
maton slack channel mark C0123456789 --ts 1234567890.123456
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
GET /slack/api/conversations.list?types=im
Example:
maton slack channel list --types im
GET /slack/api/conversations.list?types=mpim
Example:
maton slack channel list --types mpim
GET /slack/api/users.conversations?limit=100
Example:
maton slack conversation list --limit 100
GET /slack/api/users.list?limit=100
Example:
maton slack user list --limit 100
GET /slack/api/users.info?user=U0123456789
Example:
maton slack user view U0123456789
GET /slack/api/users.getPresence?user=U0123456789
Example:
maton slack user presence U0123456789
GET /slack/api/users.lookupByEmail?email=user@example.com
Example:
maton slack user lookup --email user@example.com
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
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 /slack/api/reactions.get?channel=C0123456789×tamp=1234567890.123456
Example:
maton slack reaction get --channel C0123456789 --ts 1234567890.123456
GET /slack/api/reactions.list?limit=100
Example:
maton slack reaction list --limit 100
GET /slack/api/stars.list?limit=100
Example:
maton slack star list --limit 100
POST /slack/api/stars.add
Content-Type: application/json
{
"channel": "C0123456789",
"timestamp": "1234567890.123456"
}
Example:
maton slack star add --channel C0123456789 --ts 1234567890.123456
POST /slack/api/stars.remove
Content-Type: application/json
{
"channel": "C0123456789",
"timestamp": "1234567890.123456"
}
Example:
maton slack star remove --channel C0123456789 --ts 1234567890.123456
GET /slack/api/pins.list?channel=C0123456789
Example:
maton slack pin list C0123456789
POST /slack/api/pins.add
Content-Type: application/json
{
"channel": "C0123456789",
"timestamp": "1234567890.123456"
}
Example:
maton slack pin add --channel C0123456789 --ts 1234567890.123456
POST /slack/api/pins.remove
Content-Type: application/json
{
"channel": "C0123456789",
"timestamp": "1234567890.123456"
}
Example:
maton slack pin remove --channel C0123456789 --ts 1234567890.123456
GET /slack/api/bookmarks.list?channel_id=C0123456789
Example:
maton slack bookmark list --channel C0123456789
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
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
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
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.
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
POST /slack/api/files.upload
Content-Type: multipart/form-data
channels=C0123456789
content=file content here
filename=example.txt
title=Example File
GET /slack/api/files.getUploadURLExternal?filename=example.txt&length=1024
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'
POST /slack/api/files.delete
Content-Type: application/json
{
"file": "F0123456789"
}
Example:
maton slack file delete F0123456789
GET /slack/api/files.info?file=F0123456789
Example:
maton slack file view F0123456789
GET /slack/api/search.messages?query=keyword
Example:
maton slack search messages 'keyword'
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.
# 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 alice@example.com
# Add a reaction to a message
maton slack reaction add --channel C012 --ts 1700000000.000100 --emoji thumbsup
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);
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())
C (public), G (private/group), D (DM)U, Bot IDs start with B, Team IDs start with Tts) are unique identifiersmrkdwn type for Slack-flavored markdown formattingthread_ts to reference the parent messagecursor from response_metadata.next_cursorcurl -g when URLs contain brackets (fields[], sort[], records[]) to disable glob parsingjq 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.| Status | Meaning |
|---|---|
| 400 | Missing Slack connection |
| 401 | Invalid or missing Maton API key |
| 429 | Rate limited (10 req/sec per account) |
| 4xx/5xx | Passthrough error from Slack API |
Missing Scope Errors: If you encounter missing_scope errors, contact Maton Support to request additional scopes for your connection.
CLI:
maton whoami
maton connection list
Manual:
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
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
slack. For example:https://api.maton.ai/slack/api/chat.postMessagehttps://api.maton.ai/api/chat.postMessage