A API REST
Tudo o que os aplicativos do Antimatter fazem passa pela mesma API HTTP, então seus scripts também podem. Esta página explica como autenticar, os recursos que você mais usará, como as respostas e os erros se parecem e como acompanhar eventos em tempo real via WebSocket.
Fundamentos
- URL base:
https://chat.example.com/api/v4. Todos os endpoints abaixo são relativos a ela. - Formato: JSON na entrada e na saída, exceto para envio de arquivos (multipart). Envie
Content-Type: application/json. - IDs: 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 excluído"). - Comunidades são equipes: a API as chama de
teams, com umteam_id. - Você mesmo: sempre que um caminho aceita um
user_id,mesignifica o usuário conectado, como emGET /users/me.
A lista completa de endpoints está 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, conexões de modelos e ações de mensagem. Os demais estão apenas no código.
Autenticação
Cada solicitação, exceto o login e alguns endpoints públicos, requer um token no cabeçalho Authorization:
curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me
Três tipos de token são aceitos lá: tokens de acesso pessoal, tokens de sessão e tokens de acesso OAuth. Authorization: Token … também é aceito. Tokens na string de consulta (?access_token=) são aceitos apenas para tokens de acesso OAuth.
Tokens de acesso pessoal (recomendados para scripts)
Um token de acesso pessoal age em seu nome, não expira, a menos que você defina uma data de expiração, e pode ser revogado a qualquer momento. Os tokens de acesso pessoal estão desativados por padrão:
- Um administrador do sistema ativa Ativar Tokens de Acesso Individual em Console do Sistema › Integrações › Gerenciamento de Integração (
ServiceSettings.EnableUserAccessTokens,AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS). - Para cada pessoa que pode criar tokens, um administrador do sistema abre Console do Sistema › Gestão de Usuários › Usuários, escolhe Gerenciar funções no menu da pessoa e marca Allow this account to generate personal access tokens. Os administradores do sistema sempre podem criá-los.
- A pessoa abre seu avatar no canto superior direito, depois Perfil & configurações › Segurança. Em Tokens de Acesso Individual, descreve para que o token será usado e escolhe Criar Token. O token é exibido apenas uma vez: copie-o.
Pela 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; seu id é o que você usa para revogá-lo (POST /users/tokens/revoke com {"token_id": "…"}). Da linha de comando: amctl token generate <user> <description>.
Um administrador do sistema pode limitar a duração dos tokens com Tempo de vida máximo do token de acesso pessoal (dias) na mesma página do Console do Sistema.
Tokens de sessão
Fazer login com uma senha retorna um token de sessão no cabeçalho de resposta Token, o mesmo tipo de sessão usado pelos aplicativos:
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 de múltiplos fatores. As sessões expiram conforme as configurações de sessão do servidor, e o endpoint de login tem limite de taxa (5 requisições por segundo). POST /users/logout encerra 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.Aplicativos OAuth 2.0
Para permitir que as pessoas façam login no seu aplicativo com sua conta do Antimatter, registre um aplicativo OAuth 2.0. O Antimatter será então o provedor OAuth:
- Ativar Provedor de Serviço OAuth 2.0 deve estar ativado (Console do Sistema › Integrações › Gerenciamento de Integração,
ServiceSettings.EnableOAuthServiceProvider, ativado por padrão). - Alguém com o direito de gerenciar aplicativos OAuth (administradores do sistema por padrão) abre seu avatar, depois Integrações › Aplicativos OAuth 2.0, e adiciona o aplicativo com suas URLs de callback. Eles recebem um ID de cliente e um segredo de cliente.
- Seu aplicativo envia as pessoas para
https://chat.example.com/oauth/authorizecomresponse_type=code,client_id,redirect_uriestate. O PKCE comcode_challenge_method=S256é suportado. - Ele 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 os aplicativos que autorizaram em Perfil e configurações › Segurança › Aplicativos autorizados.
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 usuário), 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} |
| Arquivos | POST /files (multipart: channel_id e files), depois coloque os IDs retornados em 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 (saúde, não requer token), GET /config/client?format=old (as configuraçõ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 em um tópico, "file_ids" para arquivos 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 aqueles no link do canal: /lumen-labs/channels/ops-alerts.
Paginação
Os endpoints de lista aceitam page (a partir de 0) e per_page (60 por padrão, no máximo 200). Continue pedindo a próxima página até que uma página volte mais curta que per_page.
As mensagens de um canal (GET /channels/{channel_id}/posts) também aceitam since (um horário: tudo que mudou desde então) ou before e after (um ID de publicação). Elas retornam como uma lista de publicações: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.
Erros
Os erros usam os códigos de status HTTP habituais (400 entrada inválida, 401 não autenticado, 403 não permitido, 404 não encontrado, 501 recurso desativado) 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
}
Use id no seu código: message é traduzido para o idioma do usuário. detailed_error fica vazio, a menos que o servidor esteja em modo de desenvolvedor (ServiceSettings.EnableDeveloper). Informe o request_id ao administrador do servidor: ele está nos logs.
Limites de taxa
O limite de velocidade está desativado por padrão. Quando um administrador do sistema o ativa (Console do Sistema › Ambiente › Limite de Velocidade), cada cliente recebe 10 requisições por segundo com picos de 100 por padrão, contado por endereço IP ou por usuário. As respostas incluem X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset; acima do limite, o servidor responde 429 com um cabeçalho Retry-After em segundos. Alguns endpoints, como o de login, têm seu próprio limite independentemente da configuração.
Escreva scripts que aguardam e tentam novamente em caso de 429, e evite consultas repetidas: use o WebSocket em vez disso.
O fluxo de eventos do WebSocket
Conecte-se a wss://chat.example.com/api/v4/websocket. Autentique-se com o cabeçalho Authorization: Bearer na requisição de conexão, ou enviando isto como a primeira mensagem:
{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}
O servidor envia um evento hello, seguido por um evento para tudo que você tem permissão para 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
}
Observe que data.post é a mensagem como uma string JSON. Eventos comuns: posted, post_edited, post_deleted, reaction_added, reaction_removed, typing, status_change, user_added, direct_added. Os aplicativos enviam seus próprios eventos, nomeados custom_<app id>_<event>.
Você 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 conexão cair e recupere o que perdeu com since (veja Paginação).
O Antimatter adiciona os seguintes 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 seus próprios endpoints, comoUpdateMessageRequest,PutPostOnTopeExportChannel. - TypeScript: a classe
Client4do@mattermost/client, emwebapp/platform/client, com 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 em um servidor Mattermost. Todos eles exigem uma sessão.
| Endpoint | O que faz |
|---|---|
GET /teams/{team_id}/user_attributes/fieldsPOST mesmo caminhoPATCH, DELETE …/fields/{field_id} | Atributos da comunidade: os campos de perfil definidos pelos administradores da comunidade para seus membros (até 20). Os membros podem lê-los; os administradores da comunidade os criam e modificam. |
GET /teams/{team_id}/members/{user_id}/user_attributesPATCH mesmo caminhoPOST /teams/{team_id}/user_attributes/values/search | Os valores dos atributos de um membro, como {field_id: value}. Os membros definem os próprios (exceto os gerenciados 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 que alguém publique, reaja ou envie arquivos na comunidade até o horário especificado (no máximo 28 dias); "until": 0 remove a suspensão. A visão de moderação mostra quando o membro entrou e quanto publicou 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 as lista. Colocar uma mensagem no topo ou removê-la exige o direito de publicar no canal e, em um canal de uma comunidade, ser administrador do canal ou da comunidade, ou ter Gerenciar mensagens (delete_others_posts) lá. Em uma mensagem direta ou de grupo, seus membros podem. Recusado em canais arquivados. |
POST /channels/{channel_id}/message_request | Age sobre a solicitação de mensagem própria: {"action": "accept"}, "dismiss" ou "request" para colocar uma conversa novamente entre as solicitações. Retorna 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 em um canal, e quais papéis veem um canal restrito por papel. |
GET, PUT /teams/{team_id}/server_categoriesGET, PUT …/server_categories/overrides | As categorias de canais compartilhadas 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 autolinks da comunidade em um texto. |
POST /channels/{channel_id}/export?format=csv&since=&until= | Baixa 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: veja Mover um tópico. |
GET, POST /ai/connectionsGET, PATCH, DELETE /ai/connections/{connection_id}GET /ai/connections/usable | Conexões de modelos, os provedores de IA usados pelos recursos de IA do servidor e pelos aplicativos: veja Conexõ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. Veja 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 novatos chegam; vazio significa Geral),kind(communityouworkplace: em um workplace, os administradores de canal também podem arquivar seus canais; novas comunidades recebem oTeamSettings.DefaultCommunityKinddo servidor,communitypor padrão),member_list_view(como a lista de membros agrupa os membros:choice, o padrão, permite que cada membro escolha;rolesouteamsfixa isso),hide_role_colors,require_team_badges,onboardingeautolinks(ambos strings JSON). - O Canal padrão 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 seu ID, a menos que a comunidade já tenha um canalgeneral. Os nomes antigos continuam funcionando:GET /teams/{team_id}/channels/name/town-square,GET /teams/name/{team}/channels/name/town-squaree o campochannelde um webhook recebido retornam o canal padrão da comunidade quando nenhum canal tem esse nome. Usedefault_channel_idou o nomegeneralem novo código. - Links de canais:
#channel-namevincula um canal, assim como~channel-name. A propchannel_mentionsda publicação lista os canais vinculados de qualquer forma; um#wordque não nomeia nenhum canal permanece uma hashtag. A interface web e o aplicativo móvel do Antimatter escrevem#name. - Canais Arquivados ainda aceitam novos membros (
POST /channels/{channel_id}/members), que podem ler seu histórico. Ninguém pode publicar, reagir, fixar, colocar uma mensagem no topo, renomear o canal ou alterar as funções de seus membros ali. - Respostas inline: uma publicação com
"props": {"reply_to": "<post id>"}cita aquela mensagem do mesmo canal. Adicione"reply_to_mention": falsepara não notificar seu autor. O servidor preenchemetadata.reply_tocom uma breve descrição da mensagem citada. - Spoilers:
"props": {"spoiler": true}oculta o texto e os arquivos de uma publicação até que o leitor escolha 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 espera como uma solicitação está nonotify_props.dm_requestdo seu membro de canal (pending,acceptedoudismissed). - Anexos de mensagem podem carregar
stagese umchart: veja Cartões.
Mover um tópico
POST /posts/{post_id}/move_to_channel move um tópico, 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 o qual o tópico será movido.flatten(padrãofalse):truefaz com que as respostas se tornem mensagens do canal de destino, em vez de um tópico. O recurso Make it a channel do Fusion usa isso.
As mensagens mantêm seus autores, horários, reações e arquivos. Suas cópias carregam a propriedade silent_notification, de modo que não notificam ninguém. As mensagens originais são excluídas. A resposta é a primeira mensagem movida, com seu novo ID.
Quem pode mover um tópico
- Você deve ser capaz de ler o tópico e de publicar no canal de destino.
- Os administradores do canal, os administradores da comunidade, pessoas com Gerenciar mensagens (
delete_others_posts) no canal e 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 dele. Caso contrário, a resposta é
403com o IDapi.post.move_thread.private_needs_moderator.app_error. - Ambos os canais devem estar na mesma comunidade (sem mensagens diretas ou de grupo), ser diferentes e não estar arquivados. Mensagens do sistema e mensagens que se autodestroem após a leitura não podem ser movidas.
- Um tópico com mais de
WranglerSettings.MoveThreadMaxCountmensagens (100 por padrão; 0 para sem limite) é recusado.
O ponteiro e a nota
A movimentação 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"), abaixo do tópico movido ou, com flatten, após as suas mensagens. Além do texto da mensagem, as propriedades permitem que um cliente desenhe o nome do canal como um link:
- 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 também tê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.
Conexões de modelos
Uma conexão de modelo é o endereço e a chave de um provedor de IA, configurados por um administrador. Os recursos de IA do servidor e os aplicativos que chamam o serviço de IA os utilizam. Os administradores do sistema gerenciam as conexões em nível de servidor (manage_ai_connections); os administradores de uma comunidade gerenciam as conexões da própria comunidade (manage_team_ai_connections). As chaves são somente para gravação: nenhuma resposta as contém, apenas api_key_set e api_key_last4.
| Endpoint | O que faz |
|---|---|
GET /ai/connections?scope= | As conexões que você gerencia. scope é server ou o ID de uma comunidade; sem ele, todos os escopos que você gerencia. |
POST /ai/connections | Adiciona uma conexão (responde 201). |
POST /ai/connections/test, POST /ai/connections/models | Testa uma conexão ou lista seus modelos antes de ela ser salva. Mesmo corpo que para adicionar uma; nada é armazenado. |
GET, PATCH (ou PUT), DELETE /ai/connections/{connection_id} | Lê, altera ou exclui uma conexão. Um patch contém apenas os campos a alterar; omita api_key para manter a chave. |
POST /ai/connections/{connection_id}/test | Testa uma conexão salva: {"ok", "error", "status_code", "latency_ms", "model_count"}. |
GET /ai/connections/{connection_id}/models | Os modelos oferecidos pelo provedor. |
GET /ai/connections/{connection_id}/usage | As solicitações e tokens deste mês. |
GET /ai/connections/usable?channel_id=&team_id= | Para qualquer pessoa conectada: as conexões que você pode usar lá, com seus modelos e capacidades, nunca suas chaves ou endereços. |
O corpo de uma nova conexã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 como padrão server; o ID de uma comunidade torna-a a conexão daquela 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 quais comunidades podem usar uma conexão em nível de servidor (mensagens diretas e de grupo exigem all_teams), e audience quem pode usá-la; convidados apenas com allow_guests. As alterações são gravadas no log de auditoria. O guia do administrador explica as configurações: veja IA.