Die REST-API
Alles, was die Antimatter-Apps tun, läuft über dieselbe HTTP-API – Ihre Skripte können das also auch. Diese Seite erklärt, wie Sie sich authentifizieren, welche Ressourcen Sie am häufigsten verwenden, wie Antworten und Fehler aussehen und wie Sie Ereignisse live über den WebSocket verfolgen können.
Grundlagen
- Basis-URL:
https://chat.example.com/api/v4. Alle unten genannten Endpunkte sind relativ dazu. - Format: JSON als Eingang und Ausgang, außer bei Datei-Uploads (multipart). Senden Sie
Content-Type: application/json. - IDs: Jedes Objekt hat eine 26 Zeichen lange
id. Zeitangaben sind Millisekunden seit dem Unix-Epoch (create_at,update_at,delete_at; 0 bedeutet „nicht gelöscht“). - Communities sind Teams: Die API bezeichnet sie als
teamsmit einerteam_id. - Sie selbst: Wo immer ein Pfad eine
user_iderwartet, bedeutetmedie angemeldete Person, wie inGET /users/me.
Die vollständige Liste der Endpunkte finden Sie im Code des Servers: Die Routen sind in server/channels/api4/*.go und die Typen in server/public/model deklariert. Die OpenAPI-Beschreibung im Ordner api/v4/source des Repositorys deckt die von Mattermost geerbten Endpunkte sowie einige Erweiterungen von Antimatter ab: das Verschieben von Threads, Modellverbindungen, Agenten, Community-Regeln, den Fokusmodus und Nachrichtenaktionen. Die übrigen sind nur im Code enthalten.
Authentifizierung
Jede Anfrage, mit Ausnahme des Anmeldevorgangs und einiger öffentlicher Endpunkte, benötigt ein Token im Authorization-Header:
curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me
Dort werden drei Arten von Tokens akzeptiert: persönliche Zugriffstokens, Sitzungstokens und OAuth-Zugriffstokens. Auch Authorization: Token … wird akzeptiert. Tokens in der Abfragezeichenfolge (?access_token=) werden nur für OAuth-Zugriffstokens akzeptiert.
Persönliche Zugriffstokens (empfohlen für Skripte)
Ein persönliches Zugriffstoken handelt in Ihrem Namen, läuft nicht ab, es sei denn, Sie vergeben ein Ablaufdatum, und kann jederzeit widerrufen werden. Persönliche Zugriffstokens sind standardmäßig deaktiviert:
- Ein Systemadministrator aktiviert Persönliche Zugriffs-Token aktivieren in Systemkonsole › Integrationen › Integrationsverwaltung (
ServiceSettings.EnableUserAccessTokens,AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS). - Für jede Person, die Tokens erstellen darf, öffnet ein Systemadministrator die Systemkonsole › Benutzerverwaltung › Benutzer, wählt im Menü der Person Rollen verwalten und aktiviert Diesem Konto die Erstellung persönlicher Zugriffstokens erlauben. Systemadministratoren können diese immer erstellen.
- Die Person öffnet oben rechts das eigene Avatar und dann Profil & Einstellungen › Sicherheit. Unter Persönliche Zugriffs-Token wird beschrieben, wofür das Token verwendet wird, und Token erstellen ausgewählt. Das Token wird nur einmal angezeigt: Es muss kopiert werden.
Über die API: POST /users/{user_id}/tokens mit {"description": "backup script", "expires_at": 0} (expires_at in Millisekunden; 0 für keine Ablaufzeit). Das Feld token in der Antwort ist das Geheimnis; die id wird verwendet, um es zu widerrufen (POST /users/tokens/revoke mit {"token_id": "…"}). Von der Kommandozeile: amctl token generate <user> <description>.
Ein Systemadministrator kann die Gültigkeitsdauer von Tokens über Maximale Gültigkeitsdauer für persönliche Zugriffstokens (Tage) auf derselben Systemkonsole-Seite begrenzen.
Sitzungstokens
Bei der Anmeldung mit einem Passwort wird ein Sitzungstoken im Antwort-Header Token zurückgegeben, die gleiche Art von Sitzung, die die Apps verwenden:
curl -i -X POST https://chat.example.com/api/v4/users/login \
-H 'Content-Type: application/json' \
-d '{"login_id": "maya", "password": "…"}'
Fügen Sie für ein Konto mit Multi-Faktor-Authentifizierung "token": "123456" hinzu. Sitzungen laufen ab, wie es die Sitzungseinstellungen des Servers vorsehen, und der Anmelde-Endpunkt ist ratenbegrenzt (5 Anfragen pro Sekunde). POST /users/logout beendet die Sitzung.
X-CSRF-Token senden; ein Token im Header Authorization benötigt keinen CSRF-Header.OAuth-2.0-Apps
Um es Personen zu ermöglichen, sich mit ihrem Antimatter-Konto in Ihrer Anwendung anzumelden, registrieren Sie eine OAuth-2.0-App. Antimatter ist dann der OAuth-Anbieter:
- Aktiviere OAuth-2.0-Dienstprovider muss aktiviert sein (Systemkonsole › Integrationen › Integrationsverwaltung,
ServiceSettings.EnableOAuthServiceProvider, standardmäßig aktiviert). - Eine Person mit der Berechtigung zur Verwaltung von OAuth-Apps (standardmäßig Systemadministratoren) öffnet Integrationen › OAuth-2.0-Apps (Community-Menü › Teameinstellungen › Integrationen) und fügt die App mit ihren Rückruf-URLs hinzu. Sie erhält eine Client-ID und ein Client-Secret.
- Ihre Anwendung leitet Personen an
https://chat.example.com/oauth/authorizeweiter, mitresponse_type=code,client_id,redirect_uriundstate. PKCE mitcode_challenge_method=S256wird unterstützt. - Sie tauscht den Code an
POST https://chat.example.com/oauth/access_tokenein (grant_type=authorization_code, dannrefresh_tokenzur Erneuerung) und ruft die API mitAuthorization: Bearer <access token>auf.
Personen sehen die Apps, die sie autorisiert haben, unter Profil & Einstellungen › Sicherheit › Von dir autorisierte Apps.
Wichtige Ressourcen
| Was | Endpunkte |
|---|---|
| Sie und andere Personen | GET /users/me, GET /users/{user_id}, GET /users/username/{username}, POST /users/ids (eine Liste von IDs), POST /users/search, GET /users?in_team=…&in_channel=… |
| Communities | 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 |
| Kanäle | GET /users/me/teams/{team_id}/channels, GET /teams/name/{team}/channels/name/{channel}, POST /channels, POST /channels/direct (zwei Benutzer-IDs), POST /channels/group, POST /channels/{channel_id}/members |
| Nachrichten (Posts) | 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 |
| Reaktionen | POST /reactions mit {"user_id", "post_id", "emoji_name"}, DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name} |
| Dateien | POST /files (Multipart: channel_id und files), dann die zurückgegebenen IDs in file_ids des Posts einfügen; GET /files/{file_id} |
| Einstellungen | GET /users/me/preferences, PUT /users/me/preferences |
| Integrationen | /hooks/incoming, /hooks/outgoing, /commands, /bots, /oauth/apps (siehe folgende Seiten) |
| Server | GET /system/ping (Status, kein Token erforderlich), GET /config/client?format=old (die Einstellungen, die Clients sehen) |
Eine Nachricht senden
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"}'
Nachrichten sind Markdown. Fügen Sie "root_id" (der erste Post eines Threads) hinzu, um in einem Thread zu antworten, "file_ids" für Dateien und "props" für Anhänge und andere Zusatzinformationen (siehe Anhänge).
Die ID eines Kanals finden
curl -H "Authorization: Bearer $TOKEN" \
https://chat.example.com/api/v4/teams/name/lumen-labs/channels/name/ops-alerts
Die Namen sind die aus dem Link des Kanals: /lumen-labs/channels/ops-alerts.
Paginierung
Liste-Endpunkte akzeptieren page (ab 0) und per_page (Standard 60, höchstens 200). Fordern Sie die nächste Seite an, bis eine Seite zurückkommt, die kürzer ist als per_page.
Die Nachrichten eines Kanals (GET /channels/{channel_id}/posts) akzeptieren auch since (eine Zeit: alles, was sich seitdem geändert hat) oder before und after (eine Beitrags-ID). Sie werden als Beitragsliste zurückgegeben: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.
Fehler
Fehler verwenden die üblichen HTTP-Statuscodes (400 ungültige Eingabe, 401 nicht angemeldet, 403 nicht erlaubt, 404 nicht gefunden, 501 Funktion deaktiviert) und einen JSON-Body:
{
"id": "api.context.permissions.app_error",
"message": "You do not have the appropriate permissions.",
"detailed_error": "",
"request_id": "jz8zm5nunpbt8f3gpqsz5dq6so",
"status_code": 403
}
Verwenden Sie id in Ihrem Code: message wird in die Sprache des Nutzers übersetzt. detailed_error ist leer, es sei denn, der Server läuft im Entwicklermodus (ServiceSettings.EnableDeveloper). Nennen Sie dem Server-Administrator die request_id: Sie ist in den Logs zu finden.
Ratenbegrenzung
Die Geschwindigkeitsbegrenzung ist standardmäßig deaktiviert. Wenn ein Systemadministrator sie aktiviert (Systemkonsole › Umgebung › Geschwindigkeitsbegrenzung), erhält jeder Client standardmäßig 10 Anfragen pro Sekunde mit Burst-Werten von 100, gezählt nach IP-Adresse oder Benutzer. Die Antworten enthalten X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset; bei Überschreitung des Limits antwortet der Server mit 429 und einem Retry-After-Header in Sekunden. Einige Endpunkte, wie das Anmelden, haben unabhängig von der Einstellung ein eigenes Limit.
Schreiben Sie Skripte, die bei 429 warten und erneut versuchen, und vermeiden Sie Polling: Verwenden Sie stattdessen den WebSocket.
Der WebSocket-Ereignisstrom
Verbinden Sie sich mit wss://chat.example.com/api/v4/websocket. Authentifizieren Sie sich entweder über den Authorization: Bearer-Header in der Verbindungsanfrage oder indem Sie dies als erste Nachricht senden:
{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}
Der Server sendet ein hello-Ereignis, gefolgt von einem Ereignis für alles, was Sie sehen dürfen:
{
"event": "posted",
"data": {"channel_id": "…", "channel_type": "O", "post": "{\"id\":\"…\",\"message\":\"Hello\",…}"},
"broadcast": {"channel_id": "…", "team_id": "", "user_id": "", "omit_users": null},
"seq": 4
}
Beachten Sie, dass data.post der Post als JSON-String ist. Häufige Ereignisse: posted, post_edited, post_deleted, reaction_added, reaction_removed, typing, status_change, user_added, direct_added. Apps senden eigene Ereignisse, benannt als custom_<app id>_<event>.
Sie können auch Aktionen senden, jeweils mit einer steigenden seq: user_typing mit {"channel_id", "parent_id"} oder get_statuses. Stellen Sie die Verbindung wieder her, wenn sie abbricht, und holen Sie sich mit since das nach,, was Sie verpasst haben (siehe Paginierung).
Antimatter fügt diese Ereignisse hinzu: agent_activity_changed und agent_post_stream (siehe Agenten), ai_tools_changed (siehe Agenten), community_rules_updated und community_rules_accepted (siehe Community-Regeln), focus_ended (siehe Fokusmodus), community_attributes_updated, member_timeouts_updated, post_put_on_top, post_removed_from_top, server_categories_updated, channel_overrides_updated und category_overrides_updated. Eine neue Anmeldung bei Ihrem eigenen Konto sendet session_created an Ihre anderen Sitzungen (session_id, create_at, platform, os, browser, mobile; niemals ein Token), und die Bearbeitung der Warnung sendet session_revoked oder session_acknowledged (session_id) an alle diese Sitzungen.
Client-Bibliotheken
- Los:
model.Client4inserver/public/model(Importgithub.com/mattermost/mattermost/server/public/model).model.NewAPIv4Client(url), dannclient.SetToken(token);model.NewWebSocketClient4(wsURL, token)folgt Ereignissen. Die Antimatter-Kopie fügt Methoden für eigene Endpunkte hinzu, wieUpdateMessageRequest,PutPostOnTopundExportChannel. - TypeScript: die
Client4-Klasse von@mattermost/clientinwebapp/platform/client, mit den Typen inwebapp/platform/types. Die Kopie im Antimatter-Repository enthält die Endpunkte von Antimatter; das von Mattermost auf npm veröffentlichte Paket nicht.
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)
}
Was Antimatter zur API hinzufügt
Diese Endpunkte und Felder existieren nicht auf einem Mattermost-Server. Alle erfordern eine Sitzung.
| Endpunkt | Funktion |
|---|---|
GET /teams/{team_id}/user_attributes/fieldsPOST gleicher PfadPATCH, DELETE …/fields/{field_id} | Community-Attribute: die Profilfelder, die die Administratoren einer Community für ihre Mitglieder definieren (maximal 20). Mitglieder können sie lesen; Community-Administratoren erstellen und ändern sie. |
GET /teams/{team_id}/members/{user_id}/user_attributesPATCH gleicher PfadPOST /teams/{team_id}/user_attributes/values/search | Die Attributwerte eines Mitglieds als {field_id: value}. Mitglieder setzen ihre eigenen (außer die von Administratoren verwalteten); Administratoren setzen die von beliebigen Mitgliedern. Die Suche akzeptiert {"user_ids": [...]} (maximal 200). |
GET /teams/{team_id}/timeoutsPUT /teams/{team_id}/members/{user_id}/timeoutGET /teams/{team_id}/members/{user_id}/moderation | Timeouts: {"until": time, "reason": "…"} verhindert, dass jemand in der Community bis zu diesem Zeitpunkt postet, reagiert und hochlädt (maximal 28 Tage); "until": 0 hebt es auf. Die Moderationsansicht zeigt, wann sie beigetreten sind und wie viel sie kürzlich gepostet haben. |
GET /channels/{channel_id}/on_topPUT, DELETE /posts/{post_id}/on_top | Nachrichten, die oben in einem Kanal angeheftet werden (maximal 10). {"duration": ms}, höchstens 30 Tage; 0 behält sie bei, bis sie entfernt werden. Alle, die den Kanal lesen können, sehen die Liste. Um eine Nachricht oben anzuheften oder wieder zu entfernen, benötigt man das Recht, im Kanal zu posten, und – in einem Community-Kanal – die Rolle als Administrator des Kanals oder der Community oder das Recht Nachrichten verwalten (delete_others_posts) dort. In Direktnachrichten oder Gruppennachrichten können dies die Mitglieder. In archivierten Kanälen wird dies abgelehnt. |
GET, PUT /teams/{team_id}/rulesPOST /teams/{team_id}/rules/acceptGET /teams/{team_id}/rules/stats | Community-Regeln: siehe Community-Regeln. |
GET, POST, DELETE /users/me/focusGET /users/me/focus/summary?since=&until=POST /users/me/focus/summary/read | Fokusmodus: siehe Fokusmodus. |
POST /channels/{channel_id}/message_request | Wirkt auf Ihre eigene Nachrichten-Anfrage: {"action": "accept"}, "dismiss" oder "request", um eine Konversation wieder unter den Anfragen zu platzieren. Gibt Ihr Kanalmitglied zurück. |
GET, PUT /channels/{channel_id}/overridesGET /channels/{channel_id}/overrides/effectiveGET, PUT /channels/{channel_id}/role_access | Was eine Rolle oder Person in einem Kanal tun darf und welche Rollen einen rollengesteuerten Kanal sehen. |
GET, PUT /teams/{team_id}/server_categoriesGET, PUT …/server_categories/overrides | Die gemeinsam genutzten Kanal-Kategorien der Community und die Überschreibungen, die auf jeden Kanal in einer Kategorie angewendet werden. |
GET /groups/{group_id}/team_rolePUT …/team_role/permissions | Die Berechtigungen, die eine Community-Rolle gewährt. |
POST /teams/{team_id}/autolinks/preview | Testet die Autolink-Regeln der Community an einem Text. |
POST /channels/{channel_id}/export?format=csv&since=&until= | Lädt die Nachrichten eines Kanals als CSV herunter (max. 50.000), für Personen, die den Kanal lesen dürfen. |
GET /posts/{post_id}/speech | Die vorgelesene Nachricht als Audio, wenn die Text-zu-Sprache-Umsetzung eingerichtet ist. |
POST /posts/{post_id}/move_to_channel | Verschiebt einen Thread in einen anderen Kanal derselben Community: siehe Thread verschieben. |
GET, POST /ai/connectionsGET, PATCH, DELETE /ai/connections/{connection_id}GET /ai/connections/usable | Modellverbindungen, die KI-Anbieter, die die KI-Funktionen und Apps des Servers verwenden: siehe Modellverbindungen. |
GET, POST /ai/agentsGET, PATCH, DELETE /ai/agents/{agent_id}POST /ai/agents/{agent_id}/tasksGET /ai/agents/conversations | KI-Agenten, deren Aktivität sowie die Aufgaben und Unterhaltungen des KI-Chats: siehe Agenten. |
GET /ai/agents/{agent_id}/toolsGET /ai/agents/tools/cataloguePOST /ai/tools/calls/{call_id}/confirm, /declineGET, POST /ai/mcp_serversGET, PATCH, DELETE /ai/mcp_servers/{server_id}POST, DELETE /ai/mcp_servers/{server_id}/oauth | Die Tools eines Agenten, der Katalog der Tools, die er verwenden darf, das Bestätigen oder Ablehnen eines wartenden Tool-Aufrufs sowie die für Agenten verfügbaren MCP-Server: siehe KI. |
GET /channels/{channel_id}/message_actionsPOST /posts/{post_id}/message_actions/{hook_id}GET, POST /hooks/outgoing/{hook_id}/icon | Nachrichtenaktionen: ausgehende Webhooks, die Personen über das Nachrichtenmenü ausführen. Siehe Nachrichtenaktionen. |
POST /users/me/sessions/acknowledge | Verwirft die Warnung vor einer neuen Anmeldung bei einer Ihrer eigenen Sitzungen: {"session_id"}. Dies darf nur von der angemeldeten Person für ihre eigenen Sitzungen aufgerufen werden. |
PUT /channels/{channel_id}/type | Ändert den Preset eines Kanals oder dessen Einstellungen: siehe Kanal-Typen. |
GET /channels/{channel_id}/topicsPATCH /posts/{post_id}/topic | Themen eines Forums sowie das Annehmen einer Antwort oder das Festlegen des Status eines Themas: siehe Kanalarten. |
Neue Felder
- Communities (
TeamundPUT /teams/{team_id}/patch):all_channels_membership(alle sind in jedem Kanal, den sie sehen können),default_channel_id(wo Neueinsteiger landen),welcome_channel_id(wohin die Beitritts- und Austrittsnachrichten gehen, leer für keine),kind(communityoderworkplace, in der Oberfläche als Guild und Workspace angezeigt: eine Guild aktiviert auchall_channels_membership; neue Communities erhalten den ServerwertTeamSettings.DefaultCommunityKind, standardmäßigcommunity/Guild),member_list_view(wie die Mitgliederliste die Mitglieder gruppiert:choice, die Standardeinstellung, lässt jedes Mitglied wählen;rolesoderteamslegt dies fest),hide_role_colors,require_team_badges,name_display(wie die Community Personen anzeigt: leer für die Server-Standardeinstellung),onboardingundautolinks(beide JSON-Zeichenketten). - Der Standardkanal einer neuen Community ist
general(Allgemein), nichttown-square. Das Upgrade auf 0.9.0 benennt dentown-square-Kanal jeder Community ingeneralum, wobei die ID beibehalten wird, sofern die Community nicht bereits einengeneral-Kanal besitzt. Die alten Namen funktionieren weiterhin:GET /teams/{team_id}/channels/name/town-square,GET /teams/name/{team}/channels/name/town-squaresowie daschannel-Feld eines eingehenden Webhooks liefern den Standardkanal der Community, wenn kein Kanal diesen Namen trägt. Verwenden Sie in neuem Codedefault_channel_idoder den Namengeneral. - Kanallinks:
#channel-nameverlinkt einen Kanal, genau wie~channel-name. Diechannel_mentions-Eigenschaft des Beitrags listet die auf diese Weise verlinkten Kanäle auf; ein#word, der keinen Kanal benennt, bleibt ein Hashtag. Die Web-Oberfläche und die Mobile-App von Antimatter schreiben#name. - Archivierte Kanäle können weiterhin neue Mitglieder aufnehmen (
POST /channels/{channel_id}/members), die deren Verlauf lesen können. Niemand kann dort posten, reagieren, anheften, Nachrichten nach oben setzen, den Kanal umbenennen oder die Rollen der Mitglieder ändern. - Inlinen-Antworten: Ein Beitrag mit
"props": {"reply_to": "<post id>"}zitiert diese Nachricht aus demselben Kanal. Fügen Sie"reply_to_mention": falsehinzu, um den Autor nicht zu benachrichtigen. Der Server fülltmetadata.reply_tomit einer kurzen Beschreibung der zitierten Nachricht. - Spoiler:
"props": {"spoiler": true}verbirgt den Text und die Dateien eines Beitrags, bis der Leser entscheidet, sie anzuzeigen. - Ignorieren und Sperren sind Einstellungen: Kategorie
user_block, benannt nach der ID der anderen Person, mit dem Wertignoreoderblock. Ob eine Direktnachricht als Anfrage wartet, steht in dennotify_props.dm_requestIhres Kanalmitglieds (pending,acceptedoderdismissed). - Nachrichtenanhänge können
stagesund einchartenthalten: siehe Cards. - Kanäle (
Channel): Diepropsjedes Community-Kanals enthalten immeram_type(text,voiceoderforum),am_mode,am_root_posts(membersodermoderators) undam_preset(die ID des entsprechenden Presets oder leer bei individuellen Einstellungen) sowie bei Forenam_forum_view(topicsoderimageboard). Ein Payload ohneam_typebedeutet, dass das Feld nicht ausgefüllt wurde, niemals, dass der Kanal ein Textkanal ist. Direkte und Gruppennachrichten enthalten keine dieser Informationen. Siehe Kanalarten.
Kanalarten
Ein Community-Kanal ist text, voice oder forum (seine Art, die bei der Erstellung festgelegt wird), in einem der Modi seiner Art, mit darüber liegenden Einstellungen. Ein Preset ist eine benannte Kombination aus einem Modus und Einstellungen, die ein Client als eine einzige Auswahlmöglichkeit anbietet; Presets werden nicht gespeichert, daher wird das Preset eines Kanals (am_preset) aus seinen Einstellungen abgeleitet und liest "", wenn sie keinem Preset entsprechen („Custom“).
| Preset-ID | Typ | Modus | root_posts | view |
|---|---|---|---|---|
text_chat | text | chat | members | – |
text_announcement | text | chat | moderators | – |
voice_talk | voice | talk | members | – |
voice_stage | voice | stage | members | – |
forum_agora | forum | discussion | members | topics |
forum_qa | forum | qa | members | topics |
forum_ideas | forum | ideas | members | topics |
forum_announcement | forum | discussion | moderators | topics |
forum_imageboard | forum | discussion | members | imageboard |
Erstellen und Ändern der Kanalart
POST /channels liest props.am_preset (wird zuerst expandiert), danach die einzelnen props.am_type, am_mode, am_root_posts und am_forum_view darüber; jedes andere am_-Prop wird verworfen. Das Erstellen eines Sprachkanals, während die Voice Channels-App nicht aktiv ist, wird abgelehnt (400 api.channel.type.voice_unavailable.app_error); das Erstellen einer Direktnachricht oder Gruppennachricht mit Typ-Props wird abgelehnt (api.channel.type.direct.app_error).
curl -X POST https://chat.example.com/api/v4/channels \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"team_id": "'$TEAM_ID'", "name": "help-desk", "display_name": "Help desk", "type": "O",
"props": {"am_preset": "forum_qa"}}'
PUT /channels/{channel_id}/type ändert den Preset oder die Einstellungen eines vorhandenen Kanals: {"preset"?, "mode"?, "root_posts"?, "view"?}, wobei der Preset zuerst wie beim Erstellen expandiert wird. Es werden manage_public_channel_properties oder manage_private_channel_properties im Kanal benötigt (Audit-Ereignis updateChannelType), und es wird der ausgefüllte Kanal zurückgegeben. Ein Body, der einen anderen type nennt, wird abgelehnt (api.channel.type.fixed.app_error): Der Typ selbst ändert sich nie. Weitere Fehler: api.channel.type.invalid.app_error (ein unbekannter Wert, ein Modus, der nicht zum Typ des Kanals gehört, oder eine Ansicht bei einem Nicht-Forum).
Der Massenimport und -export (amctl import bulk) führt dieselben vier Felder in der Zeile eines Kanals mit: am_type, am_mode, am_root_posts, am_forum_view. Eine Kanalzeile ohne diese Felder wird als einfacher Text-Chat-Kanal importiert, wie vor der Einführung von Kanaltypen.
Wer Konversationen startet oder Themen eröffnet
Das Posten einer Root-Nachricht (im Gegensatz zu einer Antwort) erfordert die Berechtigung create_root_post, die im Overrides-Editor als Konversationen starten (Text, Sprache) oder Themen eröffnen (Foren) angezeigt wird. Keine Rolle besitzt diese Berechtigung standardmäßig: Vor den Overrides besitzen sie alle, die posten dürfen, wenn root_posts auf members steht, und nur die Moderatoren des Kanals (Systemadministratoren, Community-Administratoren, Kanaladministratoren und alle, die dort über Nachrichten verwalten verfügen), wenn es auf moderators steht. Ein Rollen- oder Personen-Override für create_root_post wird dann darüber angewendet, wie bei jeder anderen Berechtigung. Eine Antwort (mit gesetzter root_id) benötigt nur das übliche Recht zu posten.
Ein Wurzelbeitrag, der diese Prüfung nicht besteht, führt zu 403: app.post.root_posts.moderators_only.app_error, wenn root_posts auf moderators gesetzt ist und der Verfasser kein Moderator des Kanals ist, oder app.post.root_posts.denied.app_error bei einer expliziten Ablehnung. Diese Prüfung erfolgt für die REST-API, Bots, eingehende und ausgehende Webhooks (basierend auf dem Ersteller des Hooks) sowie für Antworten von Slash-Befehlen; Beiträge von Apps (über die Plugin-API) und Kopien eines verschobenen Threads werden nicht geprüft (hier wird stattdessen die Person geprüft, die den Thread verschiebt). Auch der Massenimport überspringt diese Prüfung.
Foren akzeptieren nur Themen
In einem Forum benötigt ein Wurzelbeitrag props.am_thread_title (den Titel des Themas), ohne führende/abschließende Leerzeichen, mit einer Länge von 1 bis 100 Zeichen, unabhängig von der Quelle; dies gilt auch für Apps und verschobene Threads. Fehlt der Titel, wird 400 app.post.forum.title_required.app_error zurückgegeben; ist er zu lang, app.post.forum.title_too_long.app_error. Antworten benötigen keinen Titel; ein bei einer Antwort übermittelter Titel wird verworfen. Beim Bearbeiten des Wurzelbeitrags eines Themas ohne Titel oder mit einem leeren Titel bleibt der vorhandene Titel erhalten; ein nicht leerer Titel benennt das Thema um. Das Verschieben eines Threads in ein Forum (siehe unten) erfordert ebenfalls einen Titel, entweder aus der Anfrage oder aus dem Thread selbst.
Die akzeptierte Antwort eines Q&A-Themas (am_accepted_answer, die ID einer Antwort) und der Status eines Ideen-Themas (am_topic_status, zusammen mit am_topic_status_by und am_topic_status_at) werden ausschließlich über PATCH /posts/{post_id}/topic geschrieben. Wird einer dieser drei Werte beim Erstellen, Aktualisieren oder Patchen gesendet, sei es durch einen Client oder eine App, wird er verworfen und der gespeicherte Wert beibehalten.
Themen eines Forums auflisten
GET /channels/{channel_id}/topics?sort=votes&per_page=25
Erfordert das Recht, den Kanal zu lesen. Abfrageparameter:
sort:activity(Standard),newest,votes,unanswered(nur Q&A) oderstatus(nur Ideen).answered(true/false, Q&A) undstatus(einer vonopen,planned,in_progress,done,declined, Ideen): Filtern Sie nach diesen Werten. Die Verwendung außerhalb des jeweiligen Modus führt zu400.mine=true: Nur die Themen, die Sie erstellt haben.following=true: Nur die Themen, denen Sie folgen.q: Sucht im Titel oder im Text des ersten Beitrags, bis zu 200 Zeichen.before: dernext_cursorder vorherigen Seite.per_page: Standardwert 25, maximal 100.replies: die 0 bis 5 neuesten Antworten jedes Themas für eine Bildtafel-Ansicht.
Antwort: {"topics": [{"post", "reply_count", "last_reply_at", "participant_ids", "votes", "accepted_answer_id", "status", "on_top", "replies": [post, …]}], "next_cursor"}. Stimmen sind 👍-Reaktionen (+1 und thumbsup werden zusammengezählt), abzüglich der Autor:in des Themas selbst; accepted_answer_id wird nur in Q&A-Foren angegeben, status nur in Ideen-Foren. Themen, die im Kanal oben angeheftet sind, werden zuerst angezeigt.
Eine Antwort akzeptieren oder den Status eines Themas festlegen
curl -X PATCH https://chat.example.com/api/v4/posts/$POST_ID/topic \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"accepted_answer_id": "'$REPLY_ID'"}'
post_id muss der Root-Beitrag eines Forum-Themas sein, andernfalls 400 app.topic.not_a_topic.app_error. accepted_answer_id (die ID einer Antwort oder "", um die Akzeptanz zurückzunehmen) erfordert ein Q&A-Forum; status erfordert ein Ideen-Forum; die falsche Moduszuordnung führt zu 400 app.topic.mode.app_error.
- Akzeptieren einer Antwort: Nur die Fragesteller:in des Themas (solange sie dort noch Beiträge verfassen kann) oder ein:e Kanalmoderator:in darf dies tun; andernfalls
403 app.topic.accept.not_allowed.app_error. Die Antwort muss eine aktive, nicht-systemische Antwort auf dieses Thema sein, andernfalls400 app.topic.accept.not_a_reply.app_error. Wird die akzeptierte Antwort gelöscht, wird die Antwortmarkierung entfernt. - Festlegen eines Status: Nur Kanalmoderator:innen dürfen dies tun, andernfalls
403 app.topic.status.not_allowed.app_error; ein unbekannter Wert führt zu400 app.topic.status.invalid.app_error.
Jede Änderung postet eine Systemantwort im Thema (und informiert dessen Follower) und antwortet mit dem Root-Beitrag des Themas, wie er nun ist. In einem Ideen-Forum führt das Abstimmen für ein Thema auch dazu, dass du ihm folgst.
Thread verschieben
POST /posts/{post_id}/move_to_channel verschiebt einen Thread, seine erste Nachricht und alle Antworten in einen anderen Kanal derselben Community. post_id kann die erste Nachricht oder eine beliebige Antwort sein.
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(Pflichtfeld): Der Kanal, in den der Thread verschoben wird.flatten(Standardfalse):truemacht die Antworten zu Nachrichten des Zielkanals statt zu einem Thread. Fusion nutzt dies für Als Kanal festlegen. Wird abgelehnt, wenn das Ziel ein Forum ist (400 app.post.move_thread.forum_flatten.app_error), da die Antworten sonst zu Themen ohne Titel würden.title: der Titel des Themas, wenn das Ziel ein Forum ist. Ohne diesen wird der eigene Titel des Threads beibehalten, falls vorhanden; fehlt beides, führt dies zu400 app.post.move_thread.forum_title_required.app_error. Wird ignoriert, wenn das Ziel kein Forum ist.
Die Nachrichten behalten ihre Autoren, Zeitstempel, Reaktionen und Dateien. Ihre Kopien tragen die Eigenschaft silent_notification, sodass sie niemanden benachrichtigen. Die ursprünglichen Nachrichten werden gelöscht. Die Antwort ist die verschobene erste Nachricht mit ihrer neuen ID.
Wer einen Thread verschieben darf
- Sie müssen in der Lage sein, den Thread zu lesen und im Zielkanal zu posten.
- Die Administratoren des Kanals, die Administratoren der Community, Personen mit Nachrichten verwalten (
delete_others_posts) im Kanal sowie Systemadministratoren dürfen jeden Thread verschieben. - Der Autor des Threads darf ihn verschieben, wenn beide Kanäle öffentlich sind oder wenn alle Nachrichten des Threads von ihm stammen. Andernfalls lautet die Antwort
403mit der IDapi.post.move_thread.private_needs_moderator.app_error. - Beide Kanäle müssen in derselben Community liegen (keine Direktnachrichten oder Gruppennachrichten), sich unterscheiden und dürfen nicht archiviert sein. Systemnachrichten und Nachrichten, die nach dem Lesen gelöscht werden, können nicht verschoben werden.
- Ein Thread mit mehr als
WranglerSettings.MoveThreadMaxCountNachrichten (Standardmäßig 100; 0 für keine Grenze) wird abgelehnt.
Der Zeiger und die Notiz
Der Vorgang hinterlässt zwei Systemnachrichten vom Typ system_wrangler: einen Zeiger im alten Kanal („Ein Thread mit 13 Nachrichten wurde nach #target verschoben“) und eine Notiz im Zielkanal („Dieser Thread wurde aus #source verschoben“), unter dem verschobenen Thread oder, bei flatten, nach dessen Nachrichten. Neben dem Nachrichtentext ermöglichen deren Eigenschaften, dass ein Client den Kanalnamen als Link darstellt:
- Der Zeiger:
MovedThreadPermalink,NumMessages,MovedThreadChannelId,MovedThreadTeamName,MovedThreadPostIdund, für ein öffentliches Ziel,MovedThreadChannelNameundMovedThreadChannelDisplayName. - Die Notiz:
MovedFromChannelId,MovedFromTeamName,MovedFromPostId(der Zeiger),MovedFromPermalinkund, für eine öffentliche Quelle,MovedFromChannelNameundMovedFromChannelDisplayName.
Beide haben auch eine TranslationID. Der Name eines privaten Kanals wird weggelassen: Leser sehen „ein anderer Kanal“. Der eigene POST /posts/{post_id}/move-Endpunkt von Mattermost ist in Antimatter deaktiviert; verwenden Sie diesen Endpunkt.
Community-Regeln
Administratoren einer Community können festlegen, dass ihre Mitglieder den Regeln zustimmen müssen, bevor sie in deren Kanälen posten. Solange die Regeln aktiviert sind, kann ein Mitglied, das der aktuellen Version nicht zugestimmt hat, nicht posten, antworten, Dateien senden, Nachrichten planen, bearbeiten oder wiederherstellen sowie Befehle ausführen, die in den Kanälen der Community posten: Der Server antwortet mit 403 und der ID api.post.community_rules_not_accepted, und eine für diesen Zeitpunkt geplante Nachricht schlägt mit dem Fehlercode community_rules_not_accepted fehl. Das Lesen, Reaktionen sowie Direktnachrichten und Gruppennachrichten sind nicht betroffen; ebenso wenig Bots, eingehende Webhooks, Systemnachrichten und die Administratoren der Community (manage_team, was auch Systemadministratoren haben).
| Endpunkt | Funktion |
|---|---|
GET /teams/{team_id}/rules | Die Regeln (enabled, text in Markdown, version), zusammen mit der neuesten Version, der Sie zugestimmt haben (accepted_version), und ob Sie zustimmen müssen, bevor Sie posten (must_accept). Für Mitglieder und für alle, die einer offenen Community beitreten können. |
PUT /teams/{team_id}/rules | Speichert sie mit {"enabled", "text", "ask_again"} (manage_team). ask_again erstellt eine neue Version, der alle erneut zustimmen müssen; der erste Speichervorgang erstellt Version 1. Der Text ist erforderlich, um die Regeln zu aktivieren, und darf höchstens 16.000 Zeichen lang sein. |
POST /teams/{team_id}/rules/accept | Stimmt als Mitglied der version zu, die Sie gelesen haben; 409, wenn seitdem eine neuere Version gespeichert wurde, und 0, wenn der aktuellen Version zugestimmt wird. |
GET /teams/{team_id}/rules/stats | Wie viele Mitglieder der Community der aktuellen Version zugestimmt haben (manage_team). |
Das Ereignis community_rules_updated wird an die Community gesendet, wenn ein Administrator die Regeln speichert (team_id, enabled, version), und community_rules_accepted an die Person, die zugestimmt hat, auf allen ihren Sitzungen (team_id, version).
Fokusmodus
Der Fokusmodus ist „Nicht stören“ mit einer Endzeit: Benachrichtigungen werden stummgeschaltet (keine Push-, E-Mail-, Desktop- oder persistenten Benachrichtigungen, einschließlich dringender Nachrichten), der Grund wird zum benutzerdefinierten Status mit dem 🎯-Emoji (dart), der am Ende abläuft, und die Apps von Antimatter blenden die eigenen ungelesenen Abzeichen der Person aus. Nur die Person selbst kann diese Endpunkte verwenden (me oder ihre eigene ID): Niemand anderes, auch keine Systemadministratoren, darf den Fokus oder dessen Zusammenfassung einer anderen Person starten, beenden oder lesen.
| Endpunkt | Funktion |
|---|---|
GET /users/me/focus | Der aktuelle Fokus (active, start_at, end_at, reason), oder der letzte Fokus, nachdem er beendet wurde (ended_at gesetzt), oder alles null. |
POST /users/me/focus | Beginnt den Fokusmodus oder ändert während des Fokusmodus das Ende und den Grund: {"duration": "1h30m", "reason": "…"} oder stattdessen der Dauer {"end_at": ms}, von einer Minute bis zu einer Woche im Voraus. "duration": "tomorrow" endet am nächsten Tag um 09:00 Uhr in der Zeitzone der Person. Das Ende wird auf die volle Minute abgerundet; der Grund darf maximal 100 Zeichen lang sein. Erfordert aktivierte Benutzerstatus (ServiceSettings.EnableUserStatuses); Bots können keinen Fokusmodus aktivieren. |
DELETE /users/me/focus | Beendet den Fokusmodus sofort. |
GET /users/me/focus/summary?since=&until= | Was in diesem Zeitraum versäumt wurde (start_at und ended_at eines Fokusmodus): Kanäle mit ungelesenen Nachrichten von anderen (Direktnachrichten und Gruppennachrichten zuerst, dann solche mit Erwähnungen; stummgeschaltete Kanäle nur bei einer Erwähnung) und bei eingeklappten Antwort-Threads die gefolgten Threads mit neuen Antworten, jeweils mit Anzahl, Erwähnungen und letztem Absender. |
POST /users/me/focus/summary/read | Mit {"since", "until"}: markiert diese Kanäle und Threads nur bis until als gelesen; was danach kam, bleibt ungelesen. |
Während eine Person im Fokusmodus ist, hat ihr Benutzer die Eigenschaft focus_until (Millisekunden), die Clients nutzen, um den Fokusstatus anzuzeigen; sie kann nicht über das Profil geändert werden. Der Fokusmodus endet, wenn die Person ihn beendet, wenn die Zeit erreicht ist (innerhalb einer Minute) oder wenn sie selbst einen Status auswählt, der dann bestehen bleibt. Andernfalls werden der vorherige Status und der vorherige individuelle Status wiederhergestellt. Alle ihre Sitzungen erhalten dann das Ereignis focus_ended mit start_at, end_at und ended_by (user, timer oder status).
Modellverbindungen
Eine Modellverbindung ist die Adresse und der Schlüssel eines KI-Anbieters, die von einem Administrator eingerichtet werden. Die KI-Funktionen des Servers und die Apps, die den KI-Dienst aufrufen, nutzen sie. Systemadministratoren verwalten die serverweiten Verbindungen (manage_ai_connections); die Administratoren einer Community verwalten die eigenen ihrer Community (manage_team_ai_connections). Schlüssel sind nur schreibbar: Keine Antwort enthält einen, nur api_key_set und api_key_last4.
| Endpunkt | Funktion |
|---|---|
GET /ai/connections?scope= | Die Verbindungen, die Sie verwalten. scope ist server oder die ID einer Community; ohne Angabe alle Bereiche, die Sie verwalten. |
POST /ai/connections | Fügt eine Verbindung hinzu (antwortet mit 201). |
POST /ai/connections/test, POST /ai/connections/models | Testet eine Verbindung oder listet deren Modelle auf, bevor sie gespeichert wird. Gleicher Body wie beim Hinzufügen; es wird nichts gespeichert. |
GET, PATCH (oder PUT), DELETE /ai/connections/{connection_id} | Liest, ändert oder löscht eine Verbindung. Ein Patch enthält nur die Felder, die geändert werden sollen; lassen Sie api_key weg, um den Schlüssel beizubehalten. |
POST /ai/connections/{connection_id}/test | Testet eine gespeicherte Verbindung: {"ok", "error", "status_code", "latency_ms", "model_count"}. |
GET /ai/connections/{connection_id}/models | Die vom Anbieter angebotenen Modelle. |
GET /ai/connections/{connection_id}/usage | Anfragen und Token dieses Monats. |
GET /ai/connections/usable?channel_id=&team_id= | Für alle angemeldeten Benutzer: die dort verfügbaren Verbindungen samt deren Modellen und Funktionen – niemals deren Schlüssel oder Adressen. |
Der Inhalt einer neuen Verbindung:
{
"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 ist entweder openai_compatible oder anthropic. scope ist standardmäßig server; die ID einer Community macht daraus eine Verbindung dieser Community. In limits bedeutet 0 kein Limit; Anfragen pro Minute werden auf jedem Server gezählt, Token-Budgets gelten pro Kalendermonat (UTC) für den gesamten Cluster. sharing bestimmt, welche Communities eine serverweite Verbindung nutzen dürfen (für Direktnachrichten und Gruppennachrichten ist all_teams erforderlich), und audience, wer sie nutzen darf; Gäste nur mit allow_guests. Änderungen werden im Audit-Protokoll festgehalten. Die Administrator-Dokumentation erklärt die Einstellungen: siehe KI.
Agenten
Ein Agent ist ein Bot-Konto der Art agent (is_agent bei seinem Benutzer) mit seinen Einstellungen: seinem Geltungsbereich (server oder die ID einer Community), ob er integriert oder external ist, und bei einem integrierten Agenten seine Modellverbindung, das Modell, die System-Prompt und das Reasoning. Systemadministratoren verwalten serverweite Agenten (manage_system), Administratoren einer Community verwalten deren Agenten (manage_team); zusätzlich gibt es manage_own_agent für einen selbst erstellten Agenten und manage_others_agent für andere. Die ID des Agenten in diesen Pfaden ist seine Benutzer-ID. Das Ausführen eines externen Agenten und wie der Status eines integrierten Agenten festgelegt wird, ist unter Bots erklärt; PUT /users/{user_id}/status und die Endpunkte für individuelle Status lehnen die ID eines integrierten Agenten ab, auch für Systemadministratoren (403, api.status.agent.app_error).
| Endpunkt | Funktion |
|---|---|
GET /ai/agents?scope= | Die von dir verwalteten Agenten: scope ist server oder die ID einer Community; ohne diese Angabe werden alle von dir verwalteten Agenten zurückgegeben. |
POST /ai/agents | Erstellt einen Agenten und dessen Konto (Antwort 201). Ein Agent einer Community tritt dieser Community bei. |
GET, PATCH, DELETE /ai/agents/{agent_id}POST …/enable, POST …/disable | Liest, ändert und löscht einen Agenten (dessen Konto wird deaktiviert, dessen Nachrichten bleiben erhalten) und schaltet ihn ein oder aus. |
GET /ai/agents/connections?scope=GET /ai/agents/connections/{connection_id}/models | Die Modellverbindungen, die ein Agent dieses Bereichs verwenden darf, sowie deren Modelle. |
GET, PUT /ai/agents/{agent_id}/activityPOST /ai/agents/activity/ids | Was ein Agent gerade tut; wird von dessen eigenem Token oder dessen Verwaltern festgelegt. Der Stapel verarbeitet bis zu 200 Benutzer-IDs. |
POST /ai/agents/{agent_id}/tasks | Fragt einen integrierten Agenten, den du für eine Aufgabe verwenden darfst: summarize_thread, find_action_items oder find_open_questions (basierend auf der post_id eines Threads oder einer channel_id ab since), summarize_channel, ask_channel (mit einer question) oder summarize_transcription (ein Transkriptionsbeitrag eines Anrufs). Die Anfrage wird als deine Nachricht in deiner Direktnachricht mit dem Agenten in deiner Sprache gesendet und dort beantwortet; die Antwort (201) ist diese Nachricht. Ein Beitrag oder Kanal, den du nicht lesen kannst, wird so behandelt, als existiere er nicht. |
GET /ai/agents/conversations?agent_id=&before=&per_page= | Deine Unterhaltungen mit den Agenten, die du verwenden darfst, beginnend mit der neuesten: die Threads, die du in deinen Direktnachrichten mit ihnen gestartet hast, sowie die Threads an anderen Orten, in denen einer dieser Agenten geantwortet hat und denen du folgst. before (ein Zeitpunkt) gibt die nächste Seite an; per_page beträgt maximal 100. |
Der Inhalt eines neuen Agenten:
{
"username": "researcher",
"display_name": "Researcher",
"description": "Answers with sources",
"scope": "server",
"external": false,
"connection_id": "…",
"model": "",
"system_prompt": "You research questions and answer with sources.",
"reasoning": {"enabled": false, "effort": "", "budget_tokens": 0},
"max_tool_turns": 0,
"access": {"everyone": true, "team_ids": [], "channel_ids": [], "roles": [], "user_ids": [], "allow_guests": false}
}
Ein leeres model verwendet das Chat-Modell der Verbindung. access.channel_ids bezieht sich auf die Mitglieder dieser Kanäle. Ein externer Agent hat keine Verbindung, kein Modell und keinen System-Prompt. GET /agents listet die Agenten auf, mit denen du sprechen kannst, so wie sie von der KI-Chat-App gelesen werden.