REST API
Antimatter 應用程式執行的所有操作都透過同一個 HTTP API,因此您的腳本也可以做到。本頁說明如何進行驗證、您最常使用的資源、回應與錯誤的格式,以及如何透過 WebSocket 即時追蹤事件。
基礎知識
- 基礎 URL:
https://chat.example.com/api/v4。以下所有端點皆相對於此 URL。 - 格式:輸入與輸出皆為 JSON,檔案上傳(multipart)除外。請傳送
Content-Type: application/json。 - ID:每個物件都有一個 26 個字元的
id。時間為 Unix 紀元以來的毫秒數(create_at、update_at、delete_at;0 表示「未刪除」)。 - 社群即團隊:API 將其稱為
teams,並包含team_id。 - 您自己:凡是路徑接受
user_id的地方,me代表已登入的使用者,例如GET /users/me。
完整的端點清單位於伺服器程式碼中:路由宣告於 server/channels/api4/*.go,型別則位於 server/public/model。儲存庫中 api/v4/source 資料夾內的 OpenAPI 描述涵蓋了從 Mattermost 繼承的端點,以及 Antimatter 的部分新增功能,例如移動討論串、模型連線和訊息操作。其餘端點僅存在於程式碼中。
驗證
除了登入和少數公開端點外,每個請求都需要在 Authorization 標頭中提供權杖:
curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me
該標頭接受三種權杖:個人存取權杖、工作階段權杖和 OAuth 存取權杖。也接受 Authorization: Token … 格式。查詢字串中的權杖(?access_token=)僅接受 OAuth 存取權杖。
個人存取權杖(建議用於腳本)
個人存取權杖代表您本人,除非您設定過期日期,否則不會過期,且隨時可以撤銷。個人存取權杖預設為關閉:
- 系統管理員在系統控制台 › 整合 › 整合管理中啟用啟用個人存取 Token(
ServiceSettings.EnableUserAccessTokens、AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS)。 - 對於每位可能建立令牌的使用者,系統管理員需開啟系統控制台 › 使用者管理 › 使用者,在該使用者的選單中選擇管理角色,並勾選允許此帳戶產生個人存取令牌。系統管理員隨時都可以建立令牌。
- 使用者開啟右上角的頭像,然後選擇個人檔案與設定 › 安全性。在個人存取 Token下方,說明該 Token 的用途並選擇建立新 Token。Token 只會顯示一次:請複製它。
透過 API:POST /users/{user_id}/tokens,並附上 {"description": "backup script", "expires_at": 0}(expires_at 以毫秒為單位;0 表示永不過期)。回應中的 token 欄位即為密鑰;其 id 可用於撤銷令牌(POST /users/tokens/revoke,附上 {"token_id": "…"})。從命令列執行:amctl token generate <user> <description>。
系統管理員可以在同一個系統控制台頁面,使用個人存取權杖最長有效期(天)來限制 Token 的有效期。
工作階段令牌
使用密碼登入時,會在 Token 回應標頭中回傳一個工作階段令牌,這與應用程式使用的工作階段類型相同:
curl -i -X POST https://chat.example.com/api/v4/users/login \
-H 'Content-Type: application/json' \
-d '{"login_id": "maya", "password": "…"}'
對於啟用了多因素驗證的帳戶,請加上 "token": "123456"。工作階段會依照伺服器的工作階段設定過期,且登入端點有速率限制(每秒 5 個請求)。POST /users/logout 可結束工作階段。
X-CSRF-Token 標頭;而 Authorization 標頭中的令牌則不需要 CSRF 標頭。OAuth 2.0 應用程式
若要讓使用者使用其 Antimatter 帳戶登入您的應用程式,請註冊一個 OAuth 2.0 應用程式。此時 Antimatter 將作為 OAuth 提供者:
- 必須開啟啟用 OAuth 2.0 服務提供者(系統控制台 › 整合 › 整合管理,
ServiceSettings.EnableOAuthServiceProvider,預設為開啟)。 - 具有管理 OAuth 應用程式權限的人員(預設為系統管理員)需點擊頭像,然後選擇整合 › OAuth 2.0 應用程式,並加上應用程式及其回呼 URL。他們將獲得一個客戶端 ID 和一個客戶端密鑰。
- 您的應用程式會將使用者導向至
https://chat.example.com/oauth/authorize,並附上response_type=code、client_id、redirect_uri和state。支援使用code_challenge_method=S256的 PKCE。 - 接著,透過
POST https://chat.example.com/oauth/access_token交換授權碼(先使用grant_type=authorization_code,之後使用refresh_token進行更新),並呼叫 API 時附上Authorization: Bearer <access token>。
使用者可以在 個人檔案與設定 › 安全性 › 已授權的應用程式 中查看他們已授權的應用程式。
主要資源
| 項目 | 端點 |
|---|---|
| 您與其他使用者 | GET /users/me、GET /users/{user_id}、GET /users/username/{username}、POST /users/ids(ID 清單)、POST /users/search、GET /users?in_team=…&in_channel=… |
| 社群 | GET /users/me/teams, GET /teams/{team_id}, GET /teams/name/{name}, PUT /teams/{team_id}/patch, GET /teams/{team_id}/members, POST /teams/{team_id}/members |
| 頻道 | GET /users/me/teams/{team_id}/channels、GET /teams/name/{team}/channels/name/{channel}、POST /channels、POST /channels/direct(兩個使用者 ID)、POST /channels/group、POST /channels/{channel_id}/members |
| 訊息(貼文) | POST /posts, GET /posts/{post_id}, PUT /posts/{post_id}/patch, DELETE /posts/{post_id}, GET /channels/{channel_id}/posts, GET /posts/{post_id}/thread, POST /teams/{team_id}/posts/search |
| 反應 | POST /reactions,參數為 {"user_id", "post_id", "emoji_name"};DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name} |
| 檔案 | POST /files(多部分上傳:包含 channel_id 和 files),然後將回傳的 ID 放入貼文的 file_ids 中;GET /files/{file_id} |
| 偏好設定 | GET /users/me/preferences, PUT /users/me/preferences |
| 整合 | /hooks/incoming、/hooks/outgoing、/commands、/bots、/oauth/apps(請參閱後續頁面) |
| 伺服器 | GET /system/ping(健康狀態檢查,無需令牌)、GET /config/client?format=old(客戶端看到的設定) |
發佈訊息
curl -X POST https://chat.example.com/api/v4/posts \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"channel_id": "'$CHANNEL_ID'", "message": "Backup finished: **42 GB** in 3 min"}'
訊息使用 Markdown 格式。若要回覆討論串,請加上 "root_id"(討論串的第一則貼文);若要附上檔案,請加上 "file_ids";若要附加其他額外資訊,請加上 "props"(請參閱 附件)。
查找頻道 ID
curl -H "Authorization: Bearer $TOKEN" \
https://chat.example.com/api/v4/teams/name/lumen-labs/channels/name/ops-alerts
名稱即為頻道連結中的內容:/lumen-labs/channels/ops-alerts。
分頁
清單端點接受 page(從 0 開始)和 per_page(預設為 60,最多 200)。持續請求下一頁,直到回傳的頁面長度小於 per_page 為止。
頻道的訊息(GET /channels/{channel_id}/posts)也接受 since(時間:該時間之後所有變更過的內容),或 before 與 after(訊息 ID)。回傳結果為訊息列表:{"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}。
錯誤
錯誤使用標準的 HTTP 狀態碼(400 輸入錯誤、401 未登入、403 無權限、404 找不到、501 功能已停用)以及 JSON 回應主體:
{
"id": "api.context.permissions.app_error",
"message": "You do not have the appropriate permissions.",
"detailed_error": "",
"request_id": "jz8zm5nunpbt8f3gpqsz5dq6so",
"status_code": 403
}
在程式碼中使用 id:message 會依使用者語言進行翻譯。除非伺服器執行於開發者模式(ServiceSettings.EnableDeveloper),否則 detailed_error 為空。請向伺服器管理員引用 request_id:它記錄在日誌中。
速率限制
速率限制預設為停用。當系統管理員將其開啟(系統控制台 › 環境 › 速率限制)時,每個客戶端預設每秒可發送 10 個請求,並允許 100 的突發量,依 IP 位址或使用者計算。回應包含 X-RateLimit-Limit、X-RateLimit-Remaining 與 X-RateLimit-Reset;超過限制時,伺服器會回應 429,並附上以秒為單位的 Retry-After 標頭。某些端點(例如登入)無論設定為何,都有獨立的限制。
請撰寫在收到 429 時等待並重試的腳本,並避免輪詢:改用追蹤 WebSocket。
WebSocket 事件串流
連線至 wss://chat.example.com/api/v4/websocket。認證方式可透過連線請求中的 Authorization: Bearer 標頭,或將以下內容作為第一則訊息發送:
{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}
伺服器會先發送 hello 事件,接著發送您有權查看的所有事件:
{
"event": "posted",
"data": {"channel_id": "…", "channel_type": "O", "post": "{\"id\":\"…\",\"message\":\"Hello\",…}"},
"broadcast": {"channel_id": "…", "team_id": "", "user_id": "", "omit_users": null},
"seq": 4
}
請注意 data.post 是作為 JSON 字串儲存的訊息。常見事件包括:posted、post_edited、post_deleted、reaction_added、reaction_removed、typing、status_change、user_added、direct_added。應用程式會發送自己的事件,命名格式為 custom_<app id>_<event>。
您也可以發送動作,每個動作都帶有遞增的 seq:user_typing 搭配 {"channel_id", "parent_id"},或 get_statuses。當連線中斷時請重新連線,並使用 since 取得遺漏的內容(請參閱 分頁)。
Antimatter 新增了以下事件:community_attributes_updated、member_timeouts_updated、post_put_on_top、post_removed_from_top、server_categories_updated、channel_overrides_updated 以及 category_overrides_updated。
用戶端程式庫
- 前往:
server/public/model中的model.Client4(匯入github.com/mattermost/mattermost/server/public/model)。使用model.NewAPIv4Client(url),然後執行client.SetToken(token);model.NewWebSocketClient4(wsURL, token)可追蹤事件。Antimatter 的副本新增了用於其自身端點的方法,例如UpdateMessageRequest、PutPostOnTop和ExportChannel。 - TypeScript:
webapp/platform/client中的@mattermost/client的Client4類別,其型別位於webapp/platform/types。Antimatter 儲存庫中的副本包含 Antimatter 的端點;Mattermost 在 npm 上發布的套件則不包含。
package main
import (
"context"
"log"
"github.com/mattermost/mattermost/server/public/model"
)
func main() {
client := model.NewAPIv4Client("https://chat.example.com")
client.SetToken("…")
post, _, err := client.CreatePost(context.Background(), &model.Post{
ChannelId: "…",
Message: "Hello from Go",
})
if err != nil {
log.Fatal(err)
}
log.Println("posted", post.Id)
}
Antimatter 對 API 的新增內容
這些端點和欄位在 Mattermost 伺服器上並不存在。它們都需要一個工作階段。
| 端點 | 功能說明 |
|---|---|
GET /teams/{team_id}/user_attributes/fieldsPOST 相同路徑PATCH、DELETE …/fields/{field_id} | 社群屬性:社群管理員為成員定義的個人檔案欄位(最多 20 個)。成員可以讀取這些欄位;社群管理員可以建立和修改它們。 |
GET /teams/{team_id}/members/{user_id}/user_attributesPATCH 相同路徑POST /teams/{team_id}/user_attributes/values/search | 成員的屬性值,格式為 {field_id: value}。成員可以設定自己的值(管理員管理的欄位除外);管理員可以設定任何人的值。搜尋接受 {"user_ids": [...]}(最多 200 個)。 |
GET /teams/{team_id}/timeoutsPUT /teams/{team_id}/members/{user_id}/timeoutGET /teams/{team_id}/members/{user_id}/moderation | 逾時:{"until": time, "reason": "…"}會阻止使用者在該時間之前(最多 28 天)在社群中發文、反應或上傳;"until": 0則會解除限制。管理檢視會顯示他們加入的時間以及近期的發文量。 |
GET /channels/{channel_id}/on_topPUT, DELETE /posts/{post_id}/on_top | 保留在頻道頂端的訊息(最多 10 則)。{"duration": ms},最長 30 天;0 表示保留直到移除。任何能讀取該頻道的人皆可列出這些訊息。將訊息置頂或取消置頂需要擁有在該頻道發布訊息的權限;在社群的頻道中,還需是該頻道或社群的管理員,或擁有 管理訊息(delete_others_posts)權限。在私人訊息或群組訊息中,其成員皆可執行此操作。已封存的頻道不允許此操作。 |
POST /channels/{channel_id}/message_request | 對您自己的訊息請求採取動作:{"action": "accept"}、"dismiss",或 "request" 以將對話重新放回請求清單中。會回傳您的頻道成員。 |
GET, PUT /channels/{channel_id}/overridesGET /channels/{channel_id}/overrides/effectiveGET, PUT /channels/{channel_id}/role_access | 角色或人員在頻道中可執行的動作,以及哪些角色可檢視受角色限制的頻道。 |
GET, PUT /teams/{team_id}/server_categoriesGET, PUT …/server_categories/overrides | 社群共用的頻道分類,以及套用於該分類中每個頻道的覆寫設定。 |
GET /groups/{group_id}/team_rolePUT …/team_role/permissions | 社群角色所授予的權限。 |
POST /teams/{team_id}/autolinks/preview | 在文字上測試社群的自動連結規則。 |
POST /channels/{channel_id}/export?format=csv&since=&until= | 將頻道的訊息下載為 CSV 檔案(最多 50,000 則),供可讀取該頻道的人員使用。 |
GET /posts/{post_id}/speech | 當設定文字轉語音時,以音訊形式朗讀的訊息。 |
POST /posts/{post_id}/move_to_channel | 將討論串移至同一社群的另一個頻道:請參閱 移動討論串。 |
GET, POST /ai/connectionsGET, PATCH, DELETE /ai/connections/{connection_id}GET /ai/connections/usable | 模型連線,即伺服器 AI 功能和應用程式所使用的 AI 供應商:請參閱 模型連線。 |
GET /channels/{channel_id}/message_actionsPOST /posts/{post_id}/message_actions/{hook_id}GET, POST /hooks/outgoing/{hook_id}/icon | 訊息操作:使用者從訊息選單執行的出站 Webhook。請參閱 訊息操作。 |
新增欄位
- 社群(
Team,以及PUT /teams/{team_id}/patch):all_channels_membership(所有成員皆加入其可見的所有頻道)、default_channel_id(新成員加入時的預設頻道;留空則為 General)、kind(community或workplace:在工作區中,頻道管理員也可封存其頻道;新社群預設使用伺服器的TeamSettings.DefaultCommunityKind,即community)、member_list_view(成員清單如何分組:choice為預設值,允許每位成員自行選擇;roles或teams則固定分組方式)、hide_role_colors、require_team_badges、onboarding和autolinks(皆為 JSON 字串)。 - 新社群的預設頻道是
general(General),而非town-square。0.9.0 升級會將每個社群的town-square重新命名為general,並保留其 ID,除非該社群已存在general頻道。舊名稱仍然有效:當沒有頻道使用該名稱時,GET /teams/{team_id}/channels/name/town-square、GET /teams/name/{team}/channels/name/town-square以及傳入 Webhook 的channel參數都會指向社群的預設頻道。請在新的程式碼中使用default_channel_id或名稱general。 - 頻道連結:
#channel-name可連結至頻道,與~channel-name的效果相同。貼文的channel_mentions屬性會列出以任一方式連結的頻道;若#word未對應到任何頻道,則會保留為標籤。Antimatter 的網頁介面與行動應用程式會寫成#name。 - 已封存的頻道仍可加入新成員(
POST /channels/{channel_id}/members),這些成員可以閱讀歷史訊息。但任何人都無法在其中發文、反應、釘選、將訊息置頂、重新命名頻道或變更成員角色。 - 內嵌回覆:包含
"props": {"reply_to": "<post id>"}的貼文會引用同一頻道中的該則訊息。加入"reply_to_mention": false可避免通知該訊息的作者。伺服器會以被引用訊息的簡短描述填入metadata.reply_to。 - 劇透:
"props": {"spoiler": true}會隱藏貼文的文字與檔案,直到讀者選擇顯示為止。 - 忽略與封鎖屬於個人偏好設定:分類為
user_block,名稱以對方的 ID 命名,值為ignore或block。私人訊息是否作為請求等待,取決於您頻道成員的notify_props.dm_request(pending、accepted或dismissed)。 - 訊息附件可包含
stages與chart:請參閱 卡片。
移動討論串
POST /posts/{post_id}/move_to_channel 可將討論串、其第一則訊息以及所有回覆移動至同一社群的另一個頻道。post_id 可以是第一則訊息或任何一則回覆。
curl -X POST https://chat.example.com/api/v4/posts/$POST_ID/move_to_channel \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"channel_id": "'$TARGET_CHANNEL_ID'", "flatten": false}'
channel_id(必填):討論串要移動到的目標頻道。flatten(預設值為false):若設為true,回覆將成為目標頻道的獨立訊息,而非討論串。Fusion 的Make it a channel功能會使用此參數。
這些訊息會保留其作者、時間、反應與檔案。其副本會帶有 silent_notification 屬性,因此不會通知任何人。原始訊息會被刪除。回應內容為移動後的第一則訊息,並包含其新的 ID。
誰可以移動討論串
- 您必須能夠閱讀該討論串,並能在目標頻道中發文。
- 頻道管理員、社群管理員、在該頻道中具有管理訊息(
delete_others_posts)權限的人員,以及系統管理員,可以移動任何討論串。 - 討論串的作者可以在兩個頻道皆為公開頻道,或討論串中的所有訊息皆由其本人發佈時,移動該討論串。否則,回應將為
403,並包含 IDapi.post.move_thread.private_needs_moderator.app_error。 - 兩個頻道必須屬於同一個社群(不能是私人訊息或群組訊息)、彼此不同,且未被封存。系統訊息與阅後即焚訊息無法移動。
- 若討論串的訊息數超過
WranglerSettings.MoveThreadMaxCount(預設為 100;0 表示不限),則移動請求將被拒絕。
指標與筆記
移動操作會留下兩則 system_wrangler 類型的系統訊息:一則指標位於原頻道(「一則包含 13 則訊息的討論串已移動至 #target」),另一則筆記位於目標頻道(「此討論串從 #source 移動而來」),位置在已移動的討論串下方,若使用 flatten,則位於其訊息之後。除了訊息文字外,其屬性(props)可讓用戶端將頻道名稱顯示為連結:
- 指標包含:
MovedThreadPermalink、NumMessages、MovedThreadChannelId、MovedThreadTeamName、MovedThreadPostId,若目標為公開頻道,還包含MovedThreadChannelName與MovedThreadChannelDisplayName。 - 筆記包含:
MovedFromChannelId、MovedFromTeamName、MovedFromPostId(即指標)、MovedFromPermalink,若來源為公開頻道,還包含MovedFromChannelName與MovedFromChannelDisplayName。
兩者也都包含 TranslationID。私人頻道的名稱不會顯示:讀者會看到「另一個頻道」。Antimatter 中 Mattermost 原生的 POST /posts/{post_id}/move 端點已停用;請使用此端點。
模型連線
模型連線是 AI 供應商的金鑰與位址,由管理員設定。伺服器的 AI 功能以及呼叫 AI 服務的應用程式都會使用這些連線。系統管理員管理伺服器層級的連線(manage_ai_connections);社群管理員管理其社群的連線(manage_team_ai_connections)。金鑰為唯寫:回應中不會包含金鑰,僅包含 api_key_set 與 api_key_last4。
| 端點 | 功能說明 |
|---|---|
GET /ai/connections?scope= | 列出您管理的連線。scope 為 server 或社群 ID;若未指定,則列出您管理的所有範圍。 |
POST /ai/connections | 新增連線(回應 201)。 |
POST /ai/connections/test, POST /ai/connections/models | 在儲存前測試連線或列出其模型。請求體與新增時相同;不會儲存任何內容。 |
GET、PATCH(或 PUT)、DELETE /ai/connections/{connection_id} | 讀取、修改或刪除連線。Patch 請求僅包含要修改的欄位;若省略 api_key,則保留現有金鑰。 |
POST /ai/connections/{connection_id}/test | 測試已儲存的連線:{"ok", "error", "status_code", "latency_ms", "model_count"}。 |
GET /ai/connections/{connection_id}/models | 供應商所提供的模型。 |
GET /ai/connections/{connection_id}/usage | 本月的請求與 Token 數量。 |
GET /ai/connections/usable?channel_id=&team_id= | 供所有登入者使用:您可在該處使用的連線,包含其模型與功能,但不包含金鑰或位址。 |
新連線的請求主體:
{
"name": "Local models",
"scope": "server",
"provider": "openai_compatible",
"base_url": "http://llm.internal:8000/v1",
"api_key": "…",
"extra_headers": {},
"models": {"chat": "qwen3-32b", "embeddings": "", "transcription": "", "decisions": ""},
"limits": {"requests_per_minute": 0, "monthly_token_budget": 0, "per_user_requests_per_minute": 0, "per_user_monthly_token_budget": 0},
"sharing": {"all_teams": true, "team_ids": []},
"audience": {"everyone": true, "group_ids": [], "roles": [], "allow_guests": false}
}
provider 為 openai_compatible 或 anthropic。scope 預設為 server;若填入社群 ID,則成為該社群的連線。在 limits 中,0 表示無限制;每分鐘的請求數以每台伺服器計算,Token 預算則以整個叢集為單位,按日曆月(UTC)計算。sharing 指定哪些社群可使用伺服器級連線(私人訊息與群組訊息需設定為 all_teams),audience 則指定誰可使用;訪客僅在 allow_guests 啟用時可用。變更將記錄於稽核日誌。管理員指南中有詳細的設定說明:請參閱 AI。