Webhooks
Um webhook de entrada permite a outro sistema publicar num canal, enviando JSON para uma URL secreta. Um webhook de saída faz o oposto: envia mensagens para a sua URL, as que começam com uma palavra de ativação ou as que as pessoas escolhem no menu de mensagens, e publica aquilo que responder.
Onde gerir webhooks
Abra o seu avatar no canto superior direito e, em seguida, Integrações. As páginas de integrações da comunidade atual listam Webhooks de entrada e Webhooks de saída. Cada webhook pertence a uma única comunidade.
Por omissão, os administradores da comunidade e os administradores do sistema podem criar webhooks. Um administrador do sistema pode conceder esse direito a outros papéis nas definições de permissões do Consola do sistema. Um administrador do sistema também pode desativar cada tipo em Consola do sistema › Integrações › Gestão de integrações: Ativar webhooks de entrada e Ativar webhooks de saída estão ambos ativados por omissão.

Criar um webhook de entrada
- Em Integrações, escolha Webhooks de entrada e, em seguida, Adicionar webhook de entrada.
- Preencha um Título e uma Descrição: estes apenas aparecem nas páginas de integrações.
- Escolha o Canal para onde as mensagens são enviadas por omissão. Para um canal privado, tem de ser membro dele.
- Ative Fixar a este canal se os remetentes não puderem publicar noutros canais.
- Defina, opcionalmente, um Nome de utilizador e uma URL de Imagem do perfil para as suas mensagens (ver Nome e ícone).
- Escolha Guardar. Copie a URL apresentada:
https://chat.example.com/hooks/<key>.
Com a API: POST /api/v4/hooks/incoming com {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"}; o id da resposta é a chave. A partir da linha de comandos: amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI".
Enviar uma mensagem para um webhook de entrada
curl -X POST https://chat.example.com/hooks/xgh5ycrx1jf7mbs9w8z4c8e7ho \
-H 'Content-Type: application/json' \
-d '{"text": "Deploy of **api 2.4.0** finished :white_check_mark:"}'
O servidor responde com 200 e o corpo ok. Também aceita application/x-www-form-urlencoded com o JSON num campo payload, tal como os webhooks do Slack, pelo que as ferramentas feitas para o Slack geralmente funcionam sem alterações.
| Campo | Significado |
|---|---|
text | A mensagem, em Markdown. Obrigatório, a menos que existam attachments. Um texto mais longo que o limite de mensagem do servidor é dividido em várias mensagens. |
channel | Outro canal da comunidade do webhook, pelo nome (ops-alerts ou #ops-alerts), ou @username para uma mensagem direta do proprietário do webhook. Recusado quando o webhook está bloqueado no seu canal. O nome antigo town-square continua a chegar ao canal predefinido da comunidade, agora chamado general. |
username, icon_url, icon_emoji | O nome e a imagem a mostrar, quando o servidor permite substituições. |
attachments | Anexos da mensagem, apresentados como cartões (abaixo). |
props | Propriedades adicionais guardadas na mensagem, para aplicações que as leem. |
type | Um tipo de mensagem personalizado, como custom_poll, para uma aplicação que o apresenta. Os tipos que começam com system_ são recusados. |
root_id | O ID da primeira mensagem de um tópico, para responder nesse tópico. |
priority | Prioridade da mensagem, por exemplo {"priority": "urgent"}. |
silent | true envia a mensagem sem notificações push. |
Toda a mensagem publicada por um webhook tem uma etiqueta BOT ao lado do nome, mesmo quando aparece com o nome do seu criador, para que as pessoas a distinguam de uma mensagem de uma pessoa real. As mensagens de webhook nunca ativam webhooks de saída.
Nome e ícone
Um webhook publica como a pessoa que o criou, a menos que o servidor permita substituições. Duas definições em Consola do sistema › Integrações › Gestão de integrações, ambas desativadas por predefinição, alteram isso:
- Ativar integrações para substituir nomes de utilizador (
ServiceSettings.EnablePostUsernameOverride): o Nome de utilizador do webhook ou ousernameda solicitação são apresentados; na ausência de ambos, o nome éwebhook. - Permitir que as integrações substituam os ícones das fotos de perfil (
ServiceSettings.EnablePostIconOverride): a Imagem do perfil do webhook, ou oicon_urlouicon_emojida solicitação, são apresentados.
Um valor na solicitação tem prioridade sobre o guardado no webhook.
Anexos
Os anexos adicionam conteúdo estruturado abaixo do texto. Seguem o formato de anexos de mensagem do Slack:
{
"text": "Build failed on `main`",
"attachments": [{
"fallback": "main #1902 failed",
"color": "#d24b4e",
"author_name": "GitHub Actions",
"author_icon": "https://chat.example.com/static/ci.png",
"title": "main #1902 failed",
"title_link": "https://ci.example.com/runs/1902",
"text": "Commit `0f4d8e2` by Jonas Weber",
"fields": [
{"title": "Branch", "value": "zephyr-3.7", "short": true},
{"title": "Duration", "value": "3m 40s", "short": true}
],
"footer": "Lumen CI",
"ts": 1760000000
}]
}
| Campo | Significado |
|---|---|
fallback | Texto simples para locais que não podem mostrar o cartão, como notificações. |
color | A barra de cor: uma cor em hexadecimal, ou good, warning, danger. |
pretext | Texto acima do cartão. |
author_name, author_link, author_icon | Uma linha de cabeçalho pequena. |
title, title_link | O título do cartão, opcionalmente um link. |
text | O corpo do cartão, em Markdown. |
fields | Uma lista de {"title", "value", "short"}; os campos short ficam lado a lado. |
image_url, thumb_url | Uma imagem grande abaixo, ou uma pequena ao lado. |
footer, footer_icon, ts | Uma linha de rodapé e um tempo (segundos Unix). |
actions | Botões e menus: ver Mensagens interativas. |
Cartões: etapas e gráficos
O Antimatter adiciona dois campos aos anexos, desenhados pela interface predefinida:
stages: as etapas de um pipeline, apresentadas como pílulas, até 20. Cada uma é{"name", "status"}, com um estado depassed,failed,running,pending,skippedoucanceled.chart: um pequeno gráfico de linha com os valores mais recentes,{"values": [2 to 200 numbers], "threshold": number, "label": "…"}. O limite é representado por uma linha tracejada, que corresponde ao limite de alerta.
{
"attachments": [{
"color": "danger",
"title": "main #1902 failed",
"stages": [
{"name": "build", "status": "failed"},
{"name": "unit", "status": "skipped"},
{"name": "publish", "status": "skipped"}
]
}, {
"color": "warning",
"title": "API latency above 400 ms",
"chart": {"values": [210, 230, 260, 390, 450, 470], "threshold": 400, "label": "p95 latency, ms"}
}]
}
A interface clássica e outros clientes ignoram estes dois campos, por isso coloque também o essencial em text ou fields.
Criar um webhook de saída
Um webhook de saída vigia os canais Público de uma comunidade. Envia uma mensagem para a sua URL quando a primeira palavra da mensagem corresponde a uma das suas palavras de ativação, ou quando alguém o escolhe no menu da mensagem (uma ação de mensagem).
- Em Integrações, escolha Webhooks de saída e, em seguida, Adicionar webhook de saída.
- Preencha o Título e a Descrição.
- Escolha o Tipo de conteúdo da solicitação:
application/x-www-form-urlencodedouapplication/json. - Escolha um Canal, insira Palavras de gatilho (uma por linha) ou ambos. Com um canal e sem palavras de gatilho, todas as mensagens desse canal são enviadas. Com ambos, a mensagem tem de corresponder a ambos.
- Em Gatilhar quando, escolha A primeira palavra corresponde exatamente a uma palavra de ativação, A primeira palavra começa com uma palavra de ativação ou A partir do menu de mensagens. Com A partir do menu de mensagens, as palavras de ativação desaparecem, o Canal é opcional (sem ele, a ação é oferecida em todos os canais públicos da comunidade) e o Título é obrigatório: é o nome da ação no menu.
- Insira as URLs de callback (uma por linha). Cada URL recebe todas as mensagens correspondentes.
- Defina opcionalmente o Nome de utilizador e a Imagem do perfil usados para as respostas. Para uma ação a partir do menu de mensagens, o campo Ícone substitui Imagem do perfil: a URL de uma imagem .png ou .jpg ou, na interface predefinida do Antimatter, uma imagem carregada. O menu mostra-a a cinzento; sem uma, a ação recebe um ícone neutro.
- Escolha Guardar e copie o token apresentado. O seu serviço usa-o para verificar que as solicitações provêm do seu servidor.
Através da API: POST /api/v4/hooks/outgoing com {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"} (trigger_when: 0 para correspondência exata, 1 para "começa com", 2 para "a partir do menu da mensagem"). Um webhook com trigger_when 2 não requer palavras de gatilho e necessita de um display_name. Carregue o respetivo ícone com POST /api/v4/hooks/outgoing/{hook_id}/icon (multipart, campo image: PNG, JPEG ou GIF, armazenado como PNG de 128 px); o respetivo icon_url passa então a apontar para GET /api/v4/hooks/outgoing/{hook_id}/icon.
ServiceSettings.AllowedUntrustedInternalConnections). O servidor não chama endereços privados caso contrário.O pedido de saída
O Antimatter envia um POST com estes campos, como JSON ou codificado em formulário, consoante o tipo de conteúdo:
{
"token": "6kd1ofo5ojr5zgu5ipfipybgnc",
"team_id": "…",
"team_domain": "lumen-labs",
"channel_id": "…",
"channel_name": "ops-alerts",
"timestamp": 1760010000000,
"user_id": "…",
"user_name": "priya",
"post_id": "…",
"text": "deploy api 2.4.0",
"trigger_word": "deploy",
"file_ids": ""
}
Compare token com o token do webhook antes de fazer qualquer coisa. Na versão codificada em formulário, timestamp está em segundos, não em milissegundos. O servidor aguarda a sua resposta pelo tempo que Tempo limite de pedido de integração permitir (30 segundos por omissão, ServiceSettings.OutgoingIntegrationRequestsTimeout).
Responder a um webhook de saída
Para publicar uma resposta, responda com JSON. Para não publicar nada, responda com um corpo vazio.
{
"text": "Deploying **api 2.4.0** to staging…",
"response_type": "comment",
"username": "deploy-bot",
"icon_url": "https://chat.example.com/static/deploy.png"
}
texteattachments: a resposta. Sem nenhum dos dois, nada é publicado.response_type:commentpublica a resposta no tópico da mensagem que a desencadeou; caso contrário, vai para o canal.username,icon_url: mostrados quando o servidor permite substituições; caso contrário, são usados os próprios valores do webhook.props,type,priority: como nos webhooks de entrada.
A resposta é publicada como o criador do webhook, com o nome substituído, quando houver. Para qualquer coisa mais longa do que uma resposta rápida, responda de imediato e publique mais tarde com um webhook de entrada ou com a API.
Ações da mensagem
Uma ação da mensagem é um webhook de saída com Gatilhar quando definido como A partir do menu da mensagem. Nunca é ativada por mensagens publicadas. Em vez disso, as pessoas veem-na no menu de uma mensagem: Ações da mensagem (⋯) › Mais ações, sob o título Integrações, com o respetivo ícone. A interface clássica não mostra ações da mensagem. Ao selecioná-la, essa mensagem é enviada para as URLs de callback, e uma notificação breve indica Enviado para o nome da ação, ou mostra o seu ephemeral_text.
- Onde é mostrada: no canal do webhook ou, na ausência de canal, em todos os canais públicos da respetiva comunidade. Apenas os canais públicos têm ações da mensagem.
- Os Convidados apenas obtêm as ações ligadas a um canal em que estão, e não as de âmbito comunitário.
- Canais arquivados e de apenas leitura: a mensagem ainda pode ser enviada. Arquivar um canal elimina os webhooks ligados a ele, pelo que um canal arquivado mantém apenas as ações de âmbito comunitário. Uma resposta que a pessoa não pôde publicar é-lhe mostrada apenas a ela.
- Limite de taxa: cada pessoa pode executar 10 ações da mensagem por minuto, após um impulso de 5. Acima disso, o servidor responde com
429. - Redes privadas: tal como para outros webhooks de saída, os endereços internos devem ser permitidos em Permitir ligações internas não fiáveis a.
O pedido
O payload é enviado como JSON ou codificado em formulário, conforme o tipo de conteúdo do webhook:
{
"token": "6kd1ofo5ojr5zgu5ipfipybgnc",
"trigger": "message_action",
"team_id": "…",
"team_domain": "lumen-labs",
"channel_id": "…",
"channel_name": "ops-alerts",
"timestamp": 1760010000000,
"user_id": "…",
"user_name": "priya",
"post_id": "…",
"post_root_id": "",
"post_create_at": 1760009000000,
"post_user_id": "…",
"post_user_name": "jonas",
"permalink": "https://chat.example.com/lumen-labs/pl/…",
"text": "The staging database is full again",
"files": [{"id": "…", "name": "df.txt", "link": "https://chat.example.com/api/v4/files/…"}],
"priority": "",
"requested_ack": false,
"burn_on_read": false
}
user_ideuser_namesão a pessoa que selecionou a ação;post_user_idepost_user_namesão o autor da mensagem.- Apenas essa mensagem é enviada, nunca o resto do respetivo tópico.
fileslista os ficheiros da mensagem apenas quando a pessoa que selecionou a ação pode descarregá-los. Descarregar umlinkrequer uma sessão ou um token, tal como qualquer ficheiro da API.- Uma mensagem que se queima após a leitura é enviada sem o seu texto nem ficheiros, com
burn_on_readdefinido comotrue. - Em codificação de formulário, os ficheiros são enviados como campos repetidos
file_id,file_nameefile_link, na mesma ordem.
A resposta
Responder como para qualquer webhook de saída (ver Responder a um webhook de saída): text ou attachments publica uma resposta no canal, e "response_type": "comment" publica-a no tópico da mensagem. Também pode responder com ephemeral_text (limitado a 300 caracteres): é mostrado apenas à pessoa que selecionou a ação, na notificação. Um corpo vazio não publica nada.
{"ephemeral_text": "Ticket OPS-412 created"}
Com a API
GET /api/v4/channels/{channel_id}/message_actions: as ações que pode selecionar num canal, comid,display_name,descriptioneicon_url. Não são devolvidos tokens nem URLs de callback.POST /api/v4/posts/{post_id}/message_actions/{hook_id}: executa uma ação numa mensagem que pode ler. Responde com{"ephemeral_text"}.
Quando um webhook não funciona
- 501 do URL do hook: os webhooks de entrada estão desativados no servidor.
- 400 "Failed to decode the payload…": o JSON é inválido, ou o campo do formulário não se chama
payload. "No text specified." significa que o pedido não tem nemtextnemattachments. - 403: o webhook está bloqueado para outro canal, ou o seu proprietário já não pode ler o canal.
- Um webhook de saída nunca é disparado: o canal é privado, o gatilho não é a primeira palavra, a mensagem veio de um webhook, ou o webhook está definido para ser disparado A partir do menu da mensagem.
- Uma ação de mensagem não está no menu: o canal é privado, a ação está associada a outro canal, a pessoa é um convidado e a ação não tem canal, ou os webhooks de saída estão desativados.
- 404 ao executar uma ação de mensagem: a ação não existe, ou não cobre o canal dessa mensagem para essa pessoa. 429: a pessoa executou mais de 10 ações num minuto. 502: nenhuma das URLs de callback pôde ser alcançada (o registo contém o motivo).
- Registos: com Ativar depuração de webhooks ligado (
LogSettings.EnableWebhookDebugging) e o nível de registo emDEBUG, o servidor regista os payloads dos pedidos de entrada com falha. As chamadas de saída com falha são registadas comoOutgoing Webhook POST failed.