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 存取權杖。

個人存取權杖(建議用於腳本)

個人存取權杖代表您本人,除非您設定過期日期,否則不會過期,且隨時可以撤銷。個人存取權杖預設為關閉:

  1. 系統管理員在系統控制台 › 整合 › 整合管理中啟用啟用個人存取 Token(ServiceSettings.EnableUserAccessTokens、AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS)。
  2. 對於每位可能建立令牌的使用者,系統管理員需開啟系統控制台 › 使用者管理 › 使用者,在該使用者的選單中選擇管理角色,並勾選允許此帳戶產生個人存取令牌。系統管理員隨時都可以建立令牌。
  3. 使用者開啟右上角的頭像,然後選擇個人檔案與設定 › 安全性。在個人存取 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 可結束工作階段。

瀏覽器使用 Cookie 進行身份驗證。透過 Cookie 進行身份驗證的請求,除了 GET 請求外,還必須傳送 X-CSRF-Token 標頭;而 Authorization 標頭中的令牌則不需要 CSRF 標頭。

OAuth 2.0 應用程式

若要讓使用者使用其 Antimatter 帳戶登入您的應用程式,請註冊一個 OAuth 2.0 應用程式。此時 Antimatter 將作為 OAuth 提供者:

  1. 必須開啟啟用 OAuth 2.0 服務提供者(系統控制台 › 整合 › 整合管理,ServiceSettings.EnableOAuthServiceProvider,預設為開啟)。
  2. 具有管理 OAuth 應用程式權限的人員(預設為系統管理員)需點擊頭像,然後選擇整合 › OAuth 2.0 應用程式,並加上應用程式及其回呼 URL。他們將獲得一個客戶端 ID 和一個客戶端密鑰。
  3. 您的應用程式會將使用者導向至 https://chat.example.com/oauth/authorize,並附上 response_type=code、client_id、redirect_uri 和 state。支援使用 code_challenge_method=S256 的 PKCE。
  4. 接著,透過 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/fields
POST 相同路徑
PATCH、DELETE …/fields/{field_id}
社群屬性:社群管理員為成員定義的個人檔案欄位(最多 20 個)。成員可以讀取這些欄位;社群管理員可以建立和修改它們。
GET /teams/{team_id}/members/{user_id}/user_attributes
PATCH 相同路徑
POST /teams/{team_id}/user_attributes/values/search
成員的屬性值,格式為 {field_id: value}。成員可以設定自己的值(管理員管理的欄位除外);管理員可以設定任何人的值。搜尋接受 {"user_ids": [...]}(最多 200 個)。
GET /teams/{team_id}/timeouts
PUT /teams/{team_id}/members/{user_id}/timeout
GET /teams/{team_id}/members/{user_id}/moderation
逾時:{"until": time, "reason": "…"}會阻止使用者在該時間之前(最多 28 天)在社群中發文、反應或上傳;"until": 0則會解除限制。管理檢視會顯示他們加入的時間以及近期的發文量。
GET /channels/{channel_id}/on_top
PUT, 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}/overrides
GET /channels/{channel_id}/overrides/effective
GET, PUT /channels/{channel_id}/role_access
角色或人員在頻道中可執行的動作,以及哪些角色可檢視受角色限制的頻道。
GET, PUT /teams/{team_id}/server_categories
GET, PUT …/server_categories/overrides
社群共用的頻道分類,以及套用於該分類中每個頻道的覆寫設定。
GET /groups/{group_id}/team_role
PUT …/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/connections
GET, PATCH, DELETE /ai/connections/{connection_id}
GET /ai/connections/usable
模型連線,即伺服器 AI 功能和應用程式所使用的 AI 供應商:請參閱 模型連線。
GET /channels/{channel_id}/message_actions
POST /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,並包含 ID api.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。