API-ul REST
Tot ce fac aplicațiile Antimatter trece prin același API HTTP, deci scripturile dumneavoastră pot face la fel. Această pagină explică cum să vă autentificați, resursele pe care le veți folosi cel mai des, cum arată răspunsurile și erorile și cum să urmăriți în timp real evenimente prin WebSocket.
Bazele
- URL de bază:
https://chat.example.com/api/v4. Toate punctele de acces de mai jos sunt relative la acesta. - Format: JSON la intrare și la ieșere, cu excepția încărcării fișierelor (multipart). Trimiteți
Content-Type: application/json. - ID-uri: fiecare obiect are un
idde 26 de caractere. Timpurile sunt în milisecunde de la epoca Unix (create_at,update_at,delete_at; 0 înseamnă „nu a fost șters”). - Comunitățile sunt echipe: API-ul le numește
teams, cu unteam_id. - tu însuți: oriunde un path acceptă un
user_id,mese referă la utilizatorul autentificat, de exemplu înGET /users/me.
Lista completă de puncte de acces se găsește în codul serverului: rutele sunt declarate în server/channels/api4/*.go, iar tipurile în server/public/model. Descrierea OpenAPI din folderul api/v4/source din depozit acoperă punctele de acces moștenite de la Mattermost, precum și unele adăugiri din Antimatter: mutarea firelor de discuție, conexiunile la modele și acțiunile asupra mesajelor. Celelalte sunt disponibile doar în cod.
Autentificare
Fiecare cerere, cu excepția autentificării și a câtorva puncte de acces publice, necesită un token în antetul Authorization:
curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me
Acolo sunt acceptate trei tipuri de token: tokenuri de acces personale, tokenuri de sesiune și tokenuri de acces OAuth. Authorization: Token … este, de asemenea, acceptat. Tokenurile în șirul de interogare (?access_token=) sunt acceptate doar pentru tokenurile de acces OAuth.
Tokenuri de acces personale (recomandate pentru scripturi)
Un token de acces personal acționează în numele dumneavoastră, nu expiră, cu excepția cazului în care îi stabiliți o dată de expirare și poate fi revocat oricând. Tokenurile de acces personale sunt dezactivate implicit:
- Un administrator de sistem activează Activați jetoanele de acces personal în Consola de sistem › Integrări › Managementul integrării (
ServiceSettings.EnableUserAccessTokens,AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS). - Pentru fiecare persoană care poate crea jetoane, un administrator de sistem deschide Consola de sistem › Gestionarea utilizatorilor › Utilizatori, alege Gestionează rolurile din meniul persoanei și bifează Permite acestui cont să genereze jetoane de acces personal. Administratorii de sistem pot crea jetoane în orice moment.
- Persoana își deschide avatarul din colțul din dreapta sus, apoi Profil & setări › Securitate. În secțiunea Jetoane de acces personale, descrie scopul jetonului și alege Creați un nou jeton. Jetonul este afișat o singură dată: copiați-l.
Prin API: POST /users/{user_id}/tokens cu {"description": "backup script", "expires_at": 0} (expires_at în milisecunde; 0 pentru fără expirare). Câmpul token din răspuns este secretul; id-ul este cel pe care îl folosești pentru a-l revoca (POST /users/tokens/revoke cu {"token_id": "…"}). Din linia de comandă: amctl token generate <user> <description>.
Un administrator de sistem poate limita durata de viață a jetoanelor cu Durata maximă de validitate a tokenului de acces personal (zile) pe aceeași pagină din Consola de sistem.
Tokeni de sesiune
Autentificarea cu o parolă returnează un token de sesiune în antetul de răspuns Token, același tip de sesiune pe care îl folosesc aplicațiile:
curl -i -X POST https://chat.example.com/api/v4/users/login \
-H 'Content-Type: application/json' \
-d '{"login_id": "maya", "password": "…"}'
Adaugă "token": "123456" pentru un cont cu autentificare în mai multe etape. Sesiunile expiră conform setărilor de sesiune ale serverului, iar punctul de autentificare este limitat în rată (5 cereri pe secundă). POST /users/logout încheie sesiunea.
X-CSRF-Token pentru orice operație care nu este GET; un token în antetul Authorization nu necesită un antet CSRF.Aplicații OAuth 2.0
Pentru a permite utilizatorilor să se autentifice în aplicația ta cu contul lor Antimatter, înregistrează o aplicație OAuth 2.0. Antimatter devine apoi furnizorul OAuth:
- Activați furnizorul de servicii OAuth 2.0 trebuie să fie activat (Consola de sistem › Integrări › Managementul integrării,
ServiceSettings.EnableOAuthServiceProvider, activat implicit). - O persoană cu dreptul de a gestiona aplicațiile OAuth (administratorii de sistem, implicit) își deschide avatarul, apoi Integrări › Aplicații OAuth 2.0, și adaugă aplicația cu URL-urile de callback. Primește un client ID și un client secret.
- Aplicația dumneavoastră trimite utilizatorii la
https://chat.example.com/oauth/authorizecuresponse_type=code,client_id,redirect_urișistate. Este suportat PKCE cucode_challenge_method=S256. - Codul este schimbat la
POST https://chat.example.com/oauth/access_token(cugrant_type=authorization_code, apoirefresh_tokenpentru reînnoire), iar apelurile către API se fac cuAuthorization: Bearer <access token>.
Utilizatorii își pot vedea aplicațiile autorizate în Profil & setări › Securitate › Aplicații pe care le-ai autorizat.
Resurse principale
| Ce | Endpoint-uri |
|---|---|
| Dumneavoastră și alți utilizatori | GET /users/me, GET /users/{user_id}, GET /users/username/{username}, POST /users/ids (o listă de ID-uri), POST /users/search, GET /users?in_team=…&in_channel=… |
| Comunități | 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 |
| Canale | GET /users/me/teams/{team_id}/channels, GET /teams/name/{team}/channels/name/{channel}, POST /channels, POST /channels/direct (două ID-uri de utilizator), POST /channels/group, POST /channels/{channel_id}/members |
| Mesaje (postări) | 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 |
| Reacții | POST /reactions cu {"user_id", "post_id", "emoji_name"}, DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name} |
| Fișiere | POST /files (multipart: channel_id și files), apoi introduceți ID-urile returnate în file_ids al postării; GET /files/{file_id} |
| Preferințe | GET /users/me/preferences, PUT /users/me/preferences |
| Integrări | /hooks/incoming, /hooks/outgoing, /commands, /bots, /oauth/apps (a se vedea paginile următoare) |
| Server | GET /system/ping (stare, nu necesită token), GET /config/client?format=old (setările vizibile de către clienți) |
Publicare unui mesaj
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"}'
Mesajele sunt în format Markdown. Adăugați "root_id" (prima postare dintr-un fir de discuție) pentru a răspunde într-un fir de discuție, "file_ids" pentru fișiere și "props" pentru atașamente și alte elemente suplimentare (a se vedea Atașamente).
Găsirea ID-ului unui canal
curl -H "Authorization: Bearer $TOKEN" \
https://chat.example.com/api/v4/teams/name/lumen-labs/channels/name/ops-alerts
Numele sunt cele din linkul canalului: /lumen-labs/channels/ops-alerts.
Paginare
Endpoint-urile de listă acceptă page (de la 0) și per_page (60 implicit, maxim 200). Continuați să solicitați pagina următoare până când o pagină returnată este mai scurtă decât per_page.
Mesajele unui canal (GET /channels/{channel_id}/posts) acceptă și since (o dată: tot ce s-a modificat de atunci), sau before și after (un ID de mesaj). Răspunsul este o listă de mesaje: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.
Erori
Erorile folosesc codurile de stare HTTP uzuale (400 intrare nevalidă, 401 neautentificat, 403 neautorizat, 404 nu a fost găsit, 501 funcție dezactivată) și un corp JSON:
{
"id": "api.context.permissions.app_error",
"message": "You do not have the appropriate permissions.",
"detailed_error": "",
"request_id": "jz8zm5nunpbt8f3gpqsz5dq6so",
"status_code": 403
}
Folosiți id în codul dumneavoastră: message este tradus în limba utilizatorului. detailed_error este gol, cu excepția cazului în care serverul rulează în mod de dezvoltare (ServiceSettings.EnableDeveloper). Citați request_id administratorului serverului: acesta se află în jurnale.
Limite de rată
Limitarea ratei este dezactivată implicit. Când un administrator de sistem o activează (Consola de sistem › Mediu › Evaluați setările de limită), fiecare client primește implicit 10 cereri pe secundă, cu rafale de 100, numărate după adresa IP sau după utilizator. Răspunsurile conțin X-RateLimit-Limit, X-RateLimit-Remaining și X-RateLimit-Reset; dacă se depășește limita, serverul răspunde cu 429 și un antet Retry-After în secunde. Unele endpoint-uri, cum ar fi autentificarea, au propria limită, indiferent de setare.
Scrieți scripturi care așteaptă și reîncearcă la 429, și evitați interogările repetate: folosiți în schimb WebSocket.
Fluxul de evenimente WebSocket
Conectați-vă la wss://chat.example.com/api/v4/websocket. Autentificați-vă fie cu antetul Authorization: Bearer în cererea de conexiune, fie trimițând acest lucru ca prim mesaj:
{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}
Serverul trimite un eveniment hello, apoi un eveniment pentru tot ce aveți voie să vedeți:
{
"event": "posted",
"data": {"channel_id": "…", "channel_type": "O", "post": "{\"id\":\"…\",\"message\":\"Hello\",…}"},
"broadcast": {"channel_id": "…", "team_id": "", "user_id": "", "omit_users": null},
"seq": 4
}
Rețineți că data.post este mesajul ca șir JSON. Evenimente comune: posted, post_edited, post_deleted, reaction_added, reaction_removed, typing, status_change, user_added, direct_added. Aplicațiile trimite propriile evenimente, numite custom_<app id>_<event>.
Puteți trimite și acțiuni, fiecare cu un seq crescător: user_typing cu {"channel_id", "parent_id"}, sau get_statuses. Reconectați-vă când conexiunea se întrerupe și preluați ce ați ratat cu since (a se vedea Paginarea).
Antimatter adaugă aceste evenimente: community_attributes_updated, member_timeouts_updated, post_put_on_top, post_removed_from_top, server_categories_updated, channel_overrides_updated și category_overrides_updated.
Biblioteci client
- Mergi:
model.Client4înserver/public/model(importgithub.com/mattermost/mattermost/server/public/model).model.NewAPIv4Client(url), apoiclient.SetToken(token);model.NewWebSocketClient4(wsURL, token)urmărește evenimentele. Copia Antimatter adaugă metode pentru propriile sale puncte de acces, cum ar fiUpdateMessageRequest,PutPostOnTopșiExportChannel. - TypeScript: clasa
Client4din@mattermost/client, înwebapp/platform/client, cu tipurile sale înwebapp/platform/types. Copia din depozitul Antimatter include punctele de acces ale Antimatter; pachetul publicat pe npm de Mattermost nu le include.
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)
}
Ce adaugă Antimatter la API
Aceste puncte de acces și câmpuri nu există pe un server Mattermost. Toate necesită o sesiune.
| Punct de acces | Ce face |
|---|---|
GET /teams/{team_id}/user_attributes/fieldsPOST aceeași calePATCH, DELETE …/fields/{field_id} | Atributele comunității: câmpurile de profil definite de administratorii unei comunități pentru membrii săi (maxim 20). Membrii le pot citi; administratorii comunității le creează și le modifică. |
GET /teams/{team_id}/members/{user_id}/user_attributesPATCH aceeași calePOST /teams/{team_id}/user_attributes/values/search | Valorile atributelor unui membru, sub forma {field_id: value}. Membrii își setează propriile valori (cu excepția celor administrate de administratori); administratorii pot seta valorile oricui. Căutarea primește {"user_ids": [...]} (maxim 200). |
GET /teams/{team_id}/timeoutsPUT /teams/{team_id}/members/{user_id}/timeoutGET /teams/{team_id}/members/{user_id}/moderation | Timpul de așteptare: {"until": time, "reason": "…"} împiedică o persoană să posteze, să reacționeze și să încarce fișiere în comunitate până la acel moment (maxim 28 de zile); "until": 0 ridică restricția. Vederile de moderare indică când s-a alăturat și cât de mult a postat recent. |
GET /channels/{channel_id}/on_topPUT, DELETE /posts/{post_id}/on_top | Mesajele fixate în partea de sus a unui canal (maximum 10). {"duration": ms}, cel mult 30 de zile; 0 le păstrează până la eliminarea manuală. Oricine poate citi canalul le vede în listă. Fixarea unui mesaj sau eliminarea sa necesită dreptul de a posta în canal și, într-un canal de comunitate, să fii administrator al canalului sau al comunității, sau să ai Gestionează mesajele (delete_others_posts) acolo. Într-un mesaj direct sau de grup, membrii săi pot face acest lucru. Este refuzat în canalele arhivate. |
POST /channels/{channel_id}/message_request | Acționează asupra cererii de mesaj proprii: {"action": "accept"}, "dismiss" sau "request" pentru a readuce o conversație printre cereri. Returnează membrul canalului. |
GET, PUT /channels/{channel_id}/overridesGET /channels/{channel_id}/overrides/effectiveGET, PUT /channels/{channel_id}/role_access | Ce poate face un rol sau o persoană într-un canal, și ce roluri pot vedea un canal restricționat prin rol. |
GET, PUT /teams/{team_id}/server_categoriesGET, PUT …/server_categories/overrides | Categoriile de canale partajate de comunitate, și suprascrierile care se aplică tuturor canalelor dintr-o categorie. |
GET /groups/{group_id}/team_rolePUT …/team_role/permissions | Permisiunile acordate de un rol de comunitate. |
POST /teams/{team_id}/autolinks/preview | Testează regulile de autolink ale comunității pe un text. |
POST /channels/{channel_id}/export?format=csv&since=&until= | Descarcă mesajele unui canal în format CSV (până la 50.000), pentru persoanele care pot citi canalul. |
GET /posts/{post_id}/speech | Mesajul citit cu voce, în format audio, atunci când este configurată conversia text în vorbire. |
POST /posts/{post_id}/move_to_channel | Mută un fir de discuție în alt canal din aceeași comunitate: vezi Mutarea unui fir de discuție. |
GET, POST /ai/connectionsGET, PATCH, DELETE /ai/connections/{connection_id}GET /ai/connections/usable | Conexiunile la modele, furnizorii de inteligență artificială folosiți de funcțiile și aplicațiile AI ale serverului: vezi Conexiuni la modele. |
GET /channels/{channel_id}/message_actionsPOST /posts/{post_id}/message_actions/{hook_id}GET, POST /hooks/outgoing/{hook_id}/icon | Acțiuni asupra mesajelor: webhooks de ieșire pe care utilizatorii le rulează din meniul mesajului. Vezi Acțiuni asupra mesajelor. |
Câmpuri noi
- Comunități (
Team, șiPUT /teams/{team_id}/patch):all_channels_membership(toată lumea este în fiecare canal pe care îl poate vedea),default_channel_id(unde ajung noii veniți; gol înseamnă General),kind(communitysauworkplace: într-un workplace, administratorii canalelor pot arhiva și canalele lor; comunitățile noi primescTeamSettings.DefaultCommunityKindal serverului, implicitcommunity),member_list_view(cum grupează lista de membri membrii:choice, implicit, le permite fiecărui membru să aleagă;rolessauteamsfixează gruparea),hide_role_colors,require_team_badges,onboardingșiautolinks(ambele sunt șiruri JSON). - Canalul implicit al unei comunități noi este
general(General), nutown-square. Actualizarea la versiunea 0.9.0 redenumestetown-squareal fiecărei comunități îngeneral, păstrându-i ID-ul, cu excepția cazului în care comunitatea are deja un canalgeneral. Numele vechi continuă să funcționeze:GET /teams/{team_id}/channels/name/town-square,GET /teams/name/{team}/channels/name/town-squareși câmpulchannelal unui webhook primit returnează canalul implicit al comunității atunci când niciun canal nu are acel nume. Folosițidefault_channel_idsau numelegeneralîn codul nou. - Linkuri de canal:
#channel-nameleagă un canal, la fel cum face~channel-name. Proprietateachannel_mentionsa mesajului listează canalele legate în oricare dintre aceste moduri; un#wordcare nu numește niciun canal rămâne un hashtag. Interfața web și aplicația mobilă Antimatter scriu#name. - Canalele arhivate pot încă primi membri noi (
POST /channels/{channel_id}/members), care își pot citi istoricul. Nimeni nu poate posta, reacționa, fixa, pune un mesaj în evidență, redenumi canalul sau modifica rolurile membrilor acolo. - Răspunsuri inline: un mesaj cu
"props": {"reply_to": "<post id>"}citează acel mesaj din același canal. Adăugați"reply_to_mention": falsepentru a nu notifica autorul. Serverul completeazămetadata.reply_tocu o descriere scurtă a mesajului citat. - Spoilere:
"props": {"spoiler": true}ascunde textul și fișierele unui mesaj până când cititorul alege să le vadă. - Ignorarea și blocarea sunt preferințe: categoria
user_block, numită după ID-ul celeilalte persoane, cu valoareaignoresaublock. Dacă un mesaj direct așteaptă ca cerere, se află înnotify_props.dm_requestal membrului canalului dvs. (pending,acceptedsaudismissed). - Atașamentele mesajelor pot conține
stagesși unchart: consultați Carduri.
Mutarea unui fir de discuție
POST /posts/{post_id}/move_to_channel mută un fir de discuție, mesajul său inițial și toate răspunsurile, într-un alt canal din aceeași comunitate. post_id poate fi mesajul inițial sau oricare dintre răspunsuri.
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(obligatoriu): canalul în care se mută firul de discuție.flatten(implicitfalse):truetransformă răspunsurile în mesaje ale canalului țintă, în loc să rămână un fir de discuție. Opțiunea Make it a channel din Fusion o utilizează.
Mesajele își păstrează autorii, orele, reacțiile și fișierele. Copiile lor au proprietatea silent_notification, deci nu notifică pe nimeni. Mesajele originale sunt șterse. Răspunsul este mesajul inițial mutat, cu noul său ID.
Cine poate muta un fir de discuție
- Trebuie să puteți citi firul de discuție și să puteți posta în canalul țintă.
- Administratorii canalului, administratorii comunității, persoanele cu dreptul Gestionează mesajele (
delete_others_posts) în canal și administratorii de sistem pot muta orice fir de discuție. - Autorul firului de discuție îl poate muta atunci când ambele canale sunt publice, sau atunci când toate mesajele din fir sunt ale acestuia. În caz contrar, răspunsul este
403cu ID-ulapi.post.move_thread.private_needs_moderator.app_error. - Ambele canale trebuie să fie în aceeași comunitate (fără mesaje directe sau de grup), să fie diferite și să nu fie arhivate. Mesajele de sistem și mesajele care se șterg la citire nu pot fi mutate.
- Un fir de discuție cu mai mult de
WranglerSettings.MoveThreadMaxCountmesaje (100 implicit; 0 pentru fără limită) este refuzat.
Indicatorul și nota
Mutarea lasă două mesaje de sistem de tip system_wrangler: un indicator în canalul vechi („Un fir de discuție cu 13 mesaje a fost mutat în #target”) și o notă în canalul de destinație („Acest fir de discuție a fost mutat din #source”), sub firul mutat sau, cu flatten, după mesajele acestuia. Pe lângă textul mesajului, proprietățile lor permit unui client să afișeze numele canalului ca link:
- Indicatorul:
MovedThreadPermalink,NumMessages,MovedThreadChannelId,MovedThreadTeamName,MovedThreadPostIdși, pentru o destinație publică,MovedThreadChannelNameșiMovedThreadChannelDisplayName. - Nota:
MovedFromChannelId,MovedFromTeamName,MovedFromPostId(indicatorul),MovedFromPermalinkși, pentru o sursă publică,MovedFromChannelNameșiMovedFromChannelDisplayName.
Ambele au și un TranslationID. Numele unui canal privat este omis: cititorii văd „alt canal”. Endpoint-ul propriu al Mattermost, POST /posts/{post_id}/move, este dezactivat în Antimatter; folosiți acest endpoint.
Conexiuni la modele
O conexiune la model este adresa și cheia unui furnizor de IA, configurate de un administrator. Funcțiile de IA ale serverului și aplicațiile care apelează serviciul de IA le folosesc. Administratorii de sistem gestionează conexiunile la nivel de server (manage_ai_connections); administratorii unei comunități își gestionează propriile conexiuni (manage_team_ai_connections). Cheile sunt doar de scriere: niciun răspuns nu conține o cheie, doar api_key_set și api_key_last4.
| Punct de acces | Ce face |
|---|---|
GET /ai/connections?scope= | Conexiunile pe care le gestionați. scope este server sau ID-ul unei comunități; fără acesta, toate domeniile pe care le gestionați. |
POST /ai/connections | Adaugă o conexiune (răspunde cu 201). |
POST /ai/connections/test, POST /ai/connections/models | Testează o conexiune sau listează modelele acesteia înainte de a fi salvată. Același corp ca la adăugare; nimic nu este stocat. |
GET, PATCH (sau PUT), DELETE /ai/connections/{connection_id} | Citește, modifică sau șterge o conexiune. Un patch conține doar câmpurile de modificat; lăsați api_key gol pentru a păstra cheia. |
POST /ai/connections/{connection_id}/test | Testează o conexiune salvată: {"ok", "error", "status_code", "latency_ms", "model_count"}. |
GET /ai/connections/{connection_id}/models | Modelele oferite de furnizor. |
GET /ai/connections/{connection_id}/usage | Solicitările și tokenii din acest lună. |
GET /ai/connections/usable?channel_id=&team_id= | Pentru oricine este autentificat: conexiunile pe care le puteți utiliza acolo, cu modelele și capacitățile lor, dar niciodată cheile sau adresele lor. |
Corpul unei noi conexiuni:
{
"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 este openai_compatible sau anthropic. scope are valoarea implicită server; un ID de comunitate îl face o conexiune a acelei comunități. În limits, 0 înseamnă fără limită; solicitările pe minut sunt numărate pe fiecare server, iar bugetele de tokeni pe lună calendaristică (UTC) pentru întregul cluster. sharing indică ce comunități pot utiliza o conexiune la nivel de server (mesajele directe și de grup necesită all_teams), iar audience cine o poate utiliza; oaspeții doar cu allow_guests. Modificările sunt scrise în jurnalul de audit. Ghidul administratorului explică setările: consultați AI.