A API REST
Tudo o que as aplicações do Antimatter fazem passa pela mesma API HTTP, pelo que os seus scripts também o podem fazer. Esta página explica como autenticar, os recursos que mais vai usar, como são as respostas e os erros, e como seguir eventos em tempo real através do WebSocket.
Fundamentos
- URL base:
https://chat.example.com/api/v4. Todos os pontos de acesso abaixo são relativos a este. - Formato: JSON na entrada e na saída, exceto para carregamentos de ficheiros (multipart). Envie
Content-Type: application/json. - ID: cada objeto tem um
idde 26 caracteres. Os tempos são em milissegundos desde a época Unix (create_at,update_at,delete_at; 0 significa "não eliminado"). - As comunidades são equipas: a API chama-lhes
teams, com umteam_id. - si próprio: sempre que um caminho requer um
user_id,mesignifica o utilizador autenticado, como emGET /users/me.
A lista completa de endpoints encontra-se no código do servidor: as rotas são declaradas em server/channels/api4/*.go e os tipos em server/public/model. A descrição OpenAPI na pasta api/v4/source do repositório cobre os endpoints herdados do Mattermost, bem como algumas das adições do Antimatter: mover tópicos, ligações de modelos e ações de mensagem. Os restantes existem apenas no código.
Autenticação
Cada pedido, exceto o de iniciar sessão e alguns pontos de acesso públicos, necessita de um token no cabeçalho Authorization:
curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me
São aceites três tipos de token: tokens de acesso pessoal, tokens de sessão e tokens de acesso OAuth. Authorization: Token … também é aceite. Tokens na cadeia de consulta (?access_token=) só são aceites para tokens de acesso OAuth.
Tokens de acesso pessoal (recomendados para scripts)
Um token de acesso pessoal atua em seu nome, não expira, a menos que lhe defina uma data de expiração, e pode ser revogado a qualquer momento. Os tokens de acesso pessoal estão desativados por omissão:
- Um administrador do sistema ativa Ativar fichas de acesso pessoal em Consola do sistema › Integrações › Gestão de integrações (
ServiceSettings.EnableUserAccessTokens,AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS). - Para cada pessoa que pode criar fichas, um administrador do sistema abre Consola do sistema › Gestão de utilizadores › Utilizadores, escolhe Gerir funções no menu da pessoa e marca Permitir que esta conta gere fichas de acesso pessoal. Os administradores do sistema podem sempre criá-las.
- A pessoa abre o seu avatar no canto superior direito, depois Perfil & definições › Segurança. Em Tokens de acesso pessoal, descreve para que serve o token e escolhe Criar token. O token é mostrado apenas uma vez: copie-o.
Com a API: POST /users/{user_id}/tokens com {"description": "backup script", "expires_at": 0} (expires_at em milissegundos; 0 para nenhum). O campo token da resposta é o segredo; o seu id é o que usa para o revogar (POST /users/tokens/revoke com {"token_id": "…"}). A partir da linha de comandos: amctl token generate <user> <description>.
Um administrador do sistema pode limitar a duração de validade das fichas com Duração máxima de validade do token de acesso pessoal (dias) na mesma página da Consola do sistema.
Tokens de sessão
Iniciar sessão com uma palavra-passe devolve um token de sessão no cabeçalho de resposta Token, o mesmo tipo de sessão que as aplicações usam:
curl -i -X POST https://chat.example.com/api/v4/users/login \
-H 'Content-Type: application/json' \
-d '{"login_id": "maya", "password": "…"}'
Adicione "token": "123456" para uma conta com autenticação multifator. As sessões expiram conforme as definições de sessão do servidor, e o ponto de entrada de login tem limite de taxa (5 pedidos por segundo). POST /users/logout termina a sessão.
X-CSRF-Token para qualquer coisa que não seja GET; um token no cabeçalho Authorization não precisa de cabeçalho CSRF.Aplicações OAuth 2.0
Para permitir que as pessoas iniciem sessão na sua aplicação com a sua conta Antimatter, registe uma aplicação OAuth 2.0. O Antimatter passa então a ser o provedor OAuth:
- Ativar Provedor de Serviços OAuth 2.0 tem de estar ativado (Consola do sistema › Integrações › Gestão de integrações,
ServiceSettings.EnableOAuthServiceProvider, ativado por omissão). - Alguém com o direito de gerir aplicações OAuth (administradores do sistema por omissão) abre o seu avatar, depois Integrações › Aplicações OAuth 2.0, e adiciona a aplicação com as suas URLs de callback. Recebe um ID de cliente e um segredo de cliente.
- A sua aplicação envia as pessoas para
https://chat.example.com/oauth/authorizecomresponse_type=code,client_id,redirect_uriestate. O PKCE comcode_challenge_method=S256é suportado. - Troca o código em
POST https://chat.example.com/oauth/access_token(grant_type=authorization_code, depoisrefresh_tokenpara renovar) e chama a API comAuthorization: Bearer <access token>.
As pessoas veem as aplicações que autorizaram em Perfil e definições › Segurança › Aplicações autorizadas.
Recursos principais
| O quê | Endpoints |
|---|---|
| Você e outras pessoas | GET /users/me, GET /users/{user_id}, GET /users/username/{username}, POST /users/ids (uma lista de IDs), POST /users/search, GET /users?in_team=…&in_channel=… |
| Comunidades | 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 |
| Canais | GET /users/me/teams/{team_id}/channels, GET /teams/name/{team}/channels/name/{channel}, POST /channels, POST /channels/direct (dois IDs de utilizador), POST /channels/group, POST /channels/{channel_id}/members |
| Mensagens (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 |
| Reações | POST /reactions com {"user_id", "post_id", "emoji_name"}, DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name} |
| Ficheiros | POST /files (multipart: channel_id e files), depois coloque os IDs devolvidos no campo file_ids da mensagem; GET /files/{file_id} |
| Preferências | GET /users/me/preferences, PUT /users/me/preferences |
| Integrações | /hooks/incoming, /hooks/outgoing, /commands, /bots, /oauth/apps (veja as páginas seguintes) |
| Servidor | GET /system/ping (estado, não requer token), GET /config/client?format=old (as definições que os clientes veem) |
Publicar uma mensagem
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"}'
As mensagens são em Markdown. Adicione "root_id" (a primeira mensagem de um tópico) para responder num tópico, "file_ids" para ficheiros e "props" para anexos e outros extras (veja Anexos).
Encontrar o ID de um canal
curl -H "Authorization: Bearer $TOKEN" \
https://chat.example.com/api/v4/teams/name/lumen-labs/channels/name/ops-alerts
Os nomes são os que aparecem no link do canal: /lumen-labs/channels/ops-alerts.
Paginação
Os endpoints de listas aceitam page (a partir de 0) e per_page (60 por omissão, no máximo 200). Continue a pedir a página seguinte até uma página vir mais curta do que per_page.
As mensagens de um canal (GET /channels/{channel_id}/posts) também aceitam since (um tempo: tudo o que foi alterado desde então) ou before e after (um ID de publicação). São devolvidas como uma lista de publicações: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.
Erros
Os erros utilizam os códigos de estado HTTP habituais (400 entrada inválida, 401 não autenticado, 403 não autorizado, 404 não encontrado, 501 funcionalidade desativada) e um corpo JSON:
{
"id": "api.context.permissions.app_error",
"message": "You do not have the appropriate permissions.",
"detailed_error": "",
"request_id": "jz8zm5nunpbt8f3gpqsz5dq6so",
"status_code": 403
}
Utilize id no seu código: message é traduzido para a língua do utilizador. detailed_error fica vazio, exceto se o servidor estiver em modo de desenvolvimento (ServiceSettings.EnableDeveloper). Indique request_id ao administrador do servidor: ele está nos registos.
Limites de taxa
A limitação de taxa está desativada por omissão. Quando um administrador do sistema a ativa (Consola do sistema › Ambiente › Limitação de taxa), cada cliente recebe 10 pedidos por segundo, com rajadas de 100 por omissão, contados por endereço IP ou por utilizador. As respostas incluem X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset; quando o limite é excedido, o servidor responde com 429 e um cabeçalho Retry-After em segundos. Alguns pontos de acesso, como a autenticação, têm o seu próprio limite, independentemente da configuração.
Escreva scripts que esperem e repitam em caso de 429, e evite a consulta periódica: siga o WebSocket em vez disso.
O fluxo de eventos do WebSocket
Ligue-se a wss://chat.example.com/api/v4/websocket. Autentique-se com o cabeçalho Authorization: Bearer no pedido de ligação, ou enviando isto como a primeira mensagem:
{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}
O servidor envia um evento hello, seguido de um evento para tudo o que lhe é permitido ver:
{
"event": "posted",
"data": {"channel_id": "…", "channel_type": "O", "post": "{\"id\":\"…\",\"message\":\"Hello\",…}"},
"broadcast": {"channel_id": "…", "team_id": "", "user_id": "", "omit_users": null},
"seq": 4
}
Note que data.post é a publicação como uma string JSON. Eventos comuns: posted, post_edited, post_deleted, reaction_added, reaction_removed, typing, status_change, user_added, direct_added. As aplicações enviam os seus próprios eventos, nomeados custom_<app id>_<event>.
Também pode enviar ações, cada uma com um seq crescente: user_typing com {"channel_id", "parent_id"}, ou get_statuses. Reconecte-se quando a ligação cair e obtenha o que perdeu com since (ver Paginação).
O Antimatter adiciona estes eventos: community_attributes_updated, member_timeouts_updated, post_put_on_top, post_removed_from_top, server_categories_updated, channel_overrides_updated e category_overrides_updated.
Bibliotecas de cliente
- Ir:
model.Client4emserver/public/model(importargithub.com/mattermost/mattermost/server/public/model).model.NewAPIv4Client(url), depoisclient.SetToken(token);model.NewWebSocketClient4(wsURL, token)segue os eventos. A cópia do Antimatter adiciona métodos para os seus próprios pontos de entrada, comoUpdateMessageRequest,PutPostOnTopeExportChannel. - TypeScript: a classe
Client4de@mattermost/client, emwebapp/platform/client, com os seus tipos emwebapp/platform/types. A cópia no repositório do Antimatter inclui os endpoints do Antimatter; o pacote publicado no npm pela Mattermost não.
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)
}
O que o Antimatter adiciona à API
Estes endpoints e campos não existem num servidor Mattermost. Todos eles exigem uma sessão.
| Endpoint | O que faz |
|---|---|
GET /teams/{team_id}/user_attributes/fieldsPOST no mesmo caminhoPATCH, DELETE …/fields/{field_id} | Atributos da comunidade: os campos de perfil definidos pelos administradores de uma comunidade para os seus membros (até 20). Os membros podem lê-los; os administradores da comunidade criam-nos e modificam-nos. |
GET /teams/{team_id}/members/{user_id}/user_attributesPATCH no mesmo caminhoPOST /teams/{team_id}/user_attributes/values/search | Os valores dos atributos de um membro, como {field_id: value}. Os membros definem os seus próprios (exceto os geridos por administradores); os administradores definem os de qualquer pessoa. A pesquisa aceita {"user_ids": [...]} (até 200). |
GET /teams/{team_id}/timeoutsPUT /teams/{team_id}/members/{user_id}/timeoutGET /teams/{team_id}/members/{user_id}/moderation | Suspensões: {"until": time, "reason": "…"} impede alguém de publicar, reagir e carregar ficheiros na comunidade até à data indicada (no máximo 28 dias); "until": 0 remove a suspensão. A vista de moderação mostra quando entraram e quanto publicaram recentemente. |
GET /channels/{channel_id}/on_topPUT, DELETE /posts/{post_id}/on_top | Mensagens mantidas no topo de um canal (até 10). {"duration": ms}, no máximo 30 dias; 0 mantém até ser removida. Qualquer pessoa que possa ler o canal vê-as. Colocar uma mensagem no topo ou removê-la exige o direito de publicar no canal e, num canal de uma comunidade, ser administrador do canal ou da comunidade, ou ter Gerir mensagens (delete_others_posts) aí. Numa mensagem direta ou de grupo, os seus membros podem fazê-lo. Recusado em canais arquivados. |
POST /channels/{channel_id}/message_request | Age sobre o seu próprio pedido de mensagem: {"action": "accept"}, "dismiss" ou "request" para colocar uma conversa novamente entre os pedidos. Devolve o seu membro do canal. |
GET, PUT /channels/{channel_id}/overridesGET /channels/{channel_id}/overrides/effectiveGET, PUT /channels/{channel_id}/role_access | O que um papel ou uma pessoa pode fazer num canal, e que papéis veem um canal com acesso restrito por papel. |
GET, PUT /teams/{team_id}/server_categoriesGET, PUT …/server_categories/overrides | As categorias de canais partilhadas pela comunidade, e as substituições que se aplicam a todos os canais de uma categoria. |
GET /groups/{group_id}/team_rolePUT …/team_role/permissions | As permissões que um papel da comunidade concede. |
POST /teams/{team_id}/autolinks/preview | Testa as regras de ligações automáticas da comunidade num texto. |
POST /channels/{channel_id}/export?format=csv&since=&until= | Descarrega as mensagens de um canal como CSV (até 50.000), para pessoas que podem ler o canal. |
GET /posts/{post_id}/speech | A mensagem lida em voz alta, como áudio, quando a conversão de texto em fala estiver configurada. |
POST /posts/{post_id}/move_to_channel | Move um tópico para outro canal da mesma comunidade: ver Mover um tópico. |
GET, POST /ai/connectionsGET, PATCH, DELETE /ai/connections/{connection_id}GET /ai/connections/usable | Ligações de modelos, os fornecedores de IA que as funcionalidades de IA do servidor e as aplicações utilizam: ver Ligações de modelos. |
GET /channels/{channel_id}/message_actionsPOST /posts/{post_id}/message_actions/{hook_id}GET, POST /hooks/outgoing/{hook_id}/icon | Ações de mensagem: webhooks de saída que as pessoas executam a partir do menu da mensagem. Ver Ações de mensagem. |
Novos campos
- Comunidades (
Team, ePUT /teams/{team_id}/patch):all_channels_membership(todos estão em todos os canais que podem ver),default_channel_id(onde os novos membros chegam; vazio significa Geral),kind(communityouworkplace: num workplace, os administradores de canal também podem arquivar os seus canais; novas comunidades recebem oTeamSettings.DefaultCommunityKinddo servidor,communitypor omissão),member_list_view(como a lista de membros agrupa os membros:choice, a omissão, permite a cada membro escolher;rolesouteamsfixa-a),hide_role_colors,require_team_badges,onboardingeautolinks(ambas cadeias JSON). - O Canal predefinido de uma nova comunidade é
general(General), nãotown-square. A atualização para a versão 0.9.0 renomeia otown-squarede cada comunidade parageneral, mantendo o respetivo ID, a menos que a comunidade já tenha um canalgeneral. Os nomes antigos continuam a funcionar:GET /teams/{team_id}/channels/name/town-square,GET /teams/name/{team}/channels/name/town-squaree o parâmetrochannelde um webhook recebido devolvem o canal predefinido da comunidade quando não existe nenhum canal com esse nome. Utilizedefault_channel_id, ou o nomegeneral, em novo código. - Links de canais:
#channel-nameliga um canal, tal como~channel-name. A propriedadechannel_mentionsda publicação lista os canais ligados de qualquer forma; um#wordque não nomeia nenhum canal permanece uma etiqueta. A interface web e a aplicação móvel do Antimatter escrevem#name. - Os canais arquivados continuam a aceitar novos membros (
POST /channels/{channel_id}/members), que podem ler o respetivo histórico. Ninguém pode publicar, reagir, fixar, colocar uma mensagem no topo, renomear o canal ou alterar as funções dos seus membros. - Respostas em linha: uma publicação com
"props": {"reply_to": "<post id>"}cita essa mensagem do mesmo canal. Adicione"reply_to_mention": falsepara não notificar o autor. O servidor preenchemetadata.reply_tocom uma breve descrição da mensagem citada. - Alertas de conteúdo:
"props": {"spoiler": true}oculta o texto e os ficheiros de uma publicação até o leitor escolher vê-los. - Ignorar e bloquear são preferências: categoria
user_block, nomeada com o ID da outra pessoa, com o valorignoreoublock. Se uma mensagem direta fica pendente como pedido, isso está nosnotify_props.dm_requestdo seu membro do canal (pending,acceptedoudismissed). - Anexos de mensagem podem ter
stagese umchart: veja Cartões.
Mover um tópico
POST /posts/{post_id}/move_to_channel move um tópico, a sua primeira mensagem e todas as suas respostas, para outro canal da mesma comunidade. post_id pode ser a primeira mensagem ou qualquer resposta.
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(obrigatório): o canal para onde o tópico é movido.flatten(predefiniçãofalse):truefaz com que as respostas se tornem mensagens do canal de destino em vez de um tópico. A opção Tornar num canal do Fusion utiliza-a.
As mensagens mantêm os respetivos autores, horários, reações e ficheiros. As suas cópias transportam a propriedade silent_notification, pelo que não notificam ninguém. As mensagens originais são eliminadas. A resposta é a primeira mensagem movida, com o seu novo ID.
Quem pode mover um tópico
- Tem de ser capaz de ler o tópico e de publicar no canal de destino.
- Os administradores do canal, os administradores da comunidade, pessoas com Gerir mensagens (
delete_others_posts) no canal, e os administradores do sistema podem mover qualquer tópico. - O autor do tópico pode movê-lo quando ambos os canais são públicos, ou quando todas as mensagens do tópico são suas. Caso contrário, a resposta é
403com o IDapi.post.move_thread.private_needs_moderator.app_error. - Ambos os canais devem pertencer à mesma comunidade (sem mensagens diretas ou de grupo), ser diferentes e não estarem arquivados. As mensagens do sistema e as mensagens que se eliminam após a leitura não podem ser movidas.
- Um tópico com mais de
WranglerSettings.MoveThreadMaxCountmensagens (100 por omissão; 0 para sem limite) é recusado.
O ponteiro e a nota
A operação de mover deixa duas mensagens do sistema do tipo system_wrangler: um ponteiro no canal de origem ("Um tópico com 13 mensagens foi movido para #target") e uma nota no canal de destino ("Este tópico foi movido de #source"), por baixo do tópico movido ou, com flatten, após as suas mensagens. Além do texto da mensagem, as suas propriedades permitem a um cliente apresentar o nome do canal como um hiperligação:
- O ponteiro:
MovedThreadPermalink,NumMessages,MovedThreadChannelId,MovedThreadTeamName,MovedThreadPostIde, para um destino público,MovedThreadChannelNameeMovedThreadChannelDisplayName. - A nota:
MovedFromChannelId,MovedFromTeamName,MovedFromPostId(o ponteiro),MovedFromPermalinke, para uma origem pública,MovedFromChannelNameeMovedFromChannelDisplayName.
Ambas têm também um TranslationID. O nome de um canal privado é omitido: os leitores veem "outro canal". O próprio POST /posts/{post_id}/move do Mattermost permanece desativado no Antimatter; use este endpoint.
Ligações de modelos
Uma ligação de modelo é o endereço e a chave de um provedor de IA, configurados por um administrador. As funcionalidades de IA do servidor e as aplicações que chamam o serviço de IA utilizam-nas. Os administradores do sistema gerem as ligações de âmbito global do servidor (manage_ai_connections); os administradores de uma comunidade gerem as ligações da sua própria comunidade (manage_team_ai_connections). As chaves são apenas de gravação: nenhuma resposta as inclui, apenas api_key_set e api_key_last4.
| Endpoint | O que faz |
|---|---|
GET /ai/connections?scope= | As ligações que gerem. scope é server ou o ID de uma comunidade; sem ele, todos os âmbitos que gerem. |
POST /ai/connections | Adiciona uma ligação (responde 201). |
POST /ai/connections/test, POST /ai/connections/models | Testa uma ligação, ou lista os seus modelos, antes de esta ser guardada. O mesmo corpo que para adicionar uma; nada é armazenado. |
GET, PATCH (ou PUT), DELETE /ai/connections/{connection_id} | Lê, altera ou elimina uma ligação. Um patch inclui apenas os campos a alterar; omita api_key para manter a chave. |
POST /ai/connections/{connection_id}/test | Testa uma ligação guardada: {"ok", "error", "status_code", "latency_ms", "model_count"}. |
GET /ai/connections/{connection_id}/models | Os modelos que o prestador de serviços disponibiliza. |
GET /ai/connections/{connection_id}/usage | As solicitações e os tokens deste mês. |
GET /ai/connections/usable?channel_id=&team_id= | Para qualquer pessoa iniciada na sessão: as ligações que pode utilizar, com os respetivos modelos e capacidades, nunca as chaves ou endereços. |
O corpo de uma nova ligação:
{
"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 ou anthropic. scope tem por omissão server; o ID de uma comunidade torna-a a ligação dessa comunidade. Em limits, 0 significa sem limite; as solicitações por minuto são contadas em cada servidor, e os orçamentos de tokens por mês civil (UTC) para todo o cluster. sharing indica que comunidades podem utilizar uma ligação de âmbito de servidor (as mensagens diretas e de grupo necessitam de all_teams), e audience quem a pode utilizar; convidados apenas com allow_guests. As alterações são registadas no registo de auditoria. O guia de administração explica as definições: ver IA.