Webhook

Un webhook in entrata consente a un altro sistema di pubblicare in un canale inviando JSON a un URL segreto. Un webhook in uscita fa l'opposto: invia i messaggi al tuo URL, quelli che iniziano con una parola chiave o che le persone selezionano nel menu del messaggio, e pubblica la tua risposta.

Dove gestire i webhook

Apri il tuo avatar in alto a destra, quindi Integrazioni. Le pagine delle integrazioni della community corrente elencano Webhooks in ingresso e Webhooks in uscita. Ogni webhook appartiene a una sola community.

Di default, gli amministratori della community e gli amministratori di sistema possono creare webhook. Un amministratore di sistema può concedere questo diritto ad altri ruoli nelle impostazioni delle autorizzazioni della Console di Sistema. Un amministratore di sistema può anche disattivare ciascun tipo in Console di Sistema › Integrazioni › Gestione integrazioni: Abilita Webhook in ingresso e Abilita Webhook in uscita sono entrambi attivi di default.

A channel with messages from a CI bot and from GitHub, shown as cards with fields, pipeline stages and a button
Messaggi di integrazione rappresentati come card: campi, fasi del pipeline e un pulsante di azione.

Creare un webhook in entrata

  1. In Integrazioni, scegli Webhooks in ingresso, quindi Aggiungere webhook in ingresso.
  2. Compila un Titolo e una Descrizione: vengono visualizzati solo nelle pagine di integrazione.
  3. Seleziona il Canale di destinazione predefinito per i messaggi. Per un canale privato, devi essere un membro di esso.
  4. Spunta Blocca in questo canale se i mittenti non devono poter pubblicare altrove.
  5. Facoltativamente, imposta un Nome utente e un URL per l'Immagine del profilo dei suoi messaggi (vedi Nome e icona).
  6. Scegli Salva. Copia l'URL visualizzato: https://chat.example.com/hooks/<key>.
L'URL è l'unico segreto: chiunque lo possiede può pubblicare nel canale. Tienilo fuori dai repository pubblici ed elimina il webhook se viene divulgato.

Con l'API: POST /api/v4/hooks/incoming con {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"}; l'id della risposta è la chiave. Dalla riga di comando: amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI".

Inviare un messaggio a un webhook in entrata

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:"}'

Il server risponde con 200 e il corpo ok. Accetta anche application/x-www-form-urlencoded con il JSON in un campo payload, come fanno i webhook di Slack, quindi gli strumenti creati per Slack di solito funzionano senza modifiche.

CampoSignificato
textIl messaggio, in Markdown. Obbligatorio, a meno che non siano presenti attachments. Un testo più lungo del limite di messaggio del server viene suddiviso in più messaggi.
channelUn altro canale della community del webhook, per nome (ops-alerts o #ops-alerts), oppure @username per un messaggio diretto dall'utente che possiede il webhook. Viene rifiutato se il webhook è bloccato sul suo canale. Il vecchio nome town-square raggiunge ancora il canale predefinito della community, ora chiamato general.
username, icon_url, icon_emojiIl nome e l'immagine da mostrare, se il server consente la sovrascrittura.
attachmentsAllegati al messaggio, visualizzati come schede (di seguito).
propsProprietà aggiuntive memorizzate sul messaggio, per le app che le leggono.
typeUn tipo di messaggio personalizzato, ad esempio custom_poll, per un'app che lo visualizza. I tipi che iniziano con system_ vengono rifiutati.
root_idL'ID del primo messaggio di un thread, per rispondere in quel thread.
priorityPriorità del messaggio, ad esempio {"priority": "urgent"}.
silenttrue invia il messaggio senza notifiche push.

Ogni messaggio pubblicato da un webhook reca un tag BOT accanto al nome, anche quando viene visualizzato sotto il nome del suo creatore, in modo da distinguerlo da un messaggio di una persona reale. I messaggi dei webhook non attivano mai webhook in uscita.

Nome e icona

Un webhook pubblica come la persona che lo ha creato, a meno che il server non consenta la sovrascrittura. Due impostazioni in Console di Sistema › Integrazioni › Gestione integrazioni, entrambe disattivate di default, modificano questo comportamento:

  • Abilita integrazioni per l'override dei nome utente (ServiceSettings.EnablePostUsernameOverride): viene visualizzato il Nome utente del webhook o il username della richiesta; in assenza di entrambi, il nome è webhook.
  • Abilita integrazioni per l'override delle immagini profilo (ServiceSettings.EnablePostIconOverride): viene visualizzata l'Immagine del profilo del webhook, oppure il icon_url o il icon_emoji della richiesta.

Un valore presente nella richiesta ha la precedenza su quello salvato sul webhook.

Allegati

Gli allegati aggiungono contenuto strutturato sotto il testo. Seguono il formato di allegato dei messaggi di 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
  }]
}
CampoSignificato
fallbackTesto semplice per i contesti che non possono mostrare la scheda, come le notifiche.
colorLa barra di colore: un colore esadecimale, oppure good, warning, danger.
pretextTesto sopra la scheda.
author_name, author_link, author_iconUna riga di intestazione piccola.
title, title_linkIl titolo della scheda, facoltativamente un link.
textIl corpo della scheda, in Markdown.
fieldsUn elenco di {"title", "value", "short"}; i campi short sono affiancati.
image_url, thumb_urlUn'immagine grande in basso, oppure una piccola sul lato.
footer, footer_icon, tsUna riga di piè di pagina e un'ora (secondi Unix).
actionsPulsanti e menu: vedi Messaggi interattivi.

Schede: fasi e grafici

Antimatter aggiunge due campi agli allegati, visualizzati dall'interfaccia predefinita:

  • stages: i passaggi di una pipeline come pillole, fino a 20. Ciascuno è {"name", "status"}, con uno stato di passed, failed, running, pending, skipped o canceled.
  • chart: un piccolo grafico a linee dei valori recenti, {"values": [2 to 200 numbers], "threshold": number, "label": "…"}. La soglia è rappresentata da una linea tratteggiata, per il limite dell'avviso.
{
  "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"}
  }]
}

L'interfaccia classica e gli altri client ignorano questi due campi, quindi inserisci anche le informazioni essenziali in text o fields.

Creare un webhook in uscita

Un webhook in uscita monitora i canali pubblici di una community. Invia un messaggio al tuo URL quando la prima parola del messaggio corrisponde a una delle sue parole chiave, oppure quando qualcuno lo seleziona nel menu del messaggio (un' azione sul messaggio).

  1. In Integrazioni, scegli Webhooks in uscita, quindi Aggiungi webhook in uscita.
  2. Compila Titolo e Descrizione.
  3. Scegli il Tipo di contenuto della richiesta: application/x-www-form-urlencoded o application/json.
  4. Seleziona un Canale, inserisci le Parole di innesco (una per linea), oppure entrambi. Con un canale e senza parole di innesco, viene inviato ogni messaggio di quel canale. Con entrambi, il messaggio deve corrispondere a entrambi.
  5. Sotto Attiva quando, scegli La prima parola corrisponde esattamente ad una parola chiave, La prima parola inizia con una parola chiave o Dal menu del messaggio. Con Dal menu del messaggio, le parole chiave scompaiono, il Canale è facoltativo (senza di esso, l'azione viene offerta in tutti i canali pubblici della community) e il Titolo è obbligatorio: è il nome dell'azione nel menu.
  6. Inserisci gli URL di callback (una per riga). Ogni URL riceve ogni messaggio corrispondente.
  7. Facoltativamente, imposta il Nome utente e l'Immagine del profilo utilizzati per le risposte. Per un'azione dal menu del messaggio, il campo Icona sostituisce Immagine del profilo: l'URL di un'immagine .png o .jpg o, nell'interfaccia predefinita di Antimatter, un'immagine caricata. Il menu la mostra in grigio; in sua assenza, l'azione riceve un'icona neutra.
  8. Scegli Salva e copia il token visualizzato. Il tuo servizio lo usa per verificare che le richieste provengano dal tuo server.

Con l'API: POST /api/v4/hooks/outgoing con {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"} (trigger_when: 0 per una corrispondenza esatta, 1 per "inizia con", 2 per "dal menu del messaggio"). Un webhook con trigger_when pari a 2 non richiede parole di attivazione e necessita di un display_name. Caricare la sua icona con POST /api/v4/hooks/outgoing/{hook_id}/icon (multipart, campo image: PNG, JPEG o GIF, memorizzata come PNG da 128 px); il suo icon_url punta quindi a GET /api/v4/hooks/outgoing/{hook_id}/icon.

Se il tuo servizio è su una rete privata, un amministratore di sistema deve consentire il suo indirizzo in Consenti connessioni interne non verificate a (ServiceSettings.AllowedUntrustedInternalConnections). Il server non chiama altrimenti gli indirizzi privati.

La richiesta in uscita

Antimatter invia una POST con questi campi, come JSON o form-encoded a seconda del tipo di contenuto:

{
  "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": ""
}

Confronta token con il token del webhook prima di procedere. Nella versione form-encoded, timestamp è espresso in secondi anziché in millisecondi. Il server attende la tua risposta per il tempo consentito da Timeout richiesta integrazione (30 secondi di default, ServiceSettings.OutgoingIntegrationRequestsTimeout).

Rispondi a un webhook in uscita

Per pubblicare una risposta, rispondi con JSON. Per non pubblicare nulla, rispondi con un corpo vuoto.

{
  "text": "Deploying **api 2.4.0** to staging…",
  "response_type": "comment",
  "username": "deploy-bot",
  "icon_url": "https://chat.example.com/static/deploy.png"
}
  • text e attachments: la risposta. Senza nessuno dei due, non viene pubblicato nulla.
  • response_type: comment pubblica la risposta nel thread del messaggio che ha attivato il webhook; altrimenti viene pubblicata nel canale.
  • username, icon_url: visualizzati quando il server consente la sovrascrittura; altrimenti vengono usati i valori propri del webhook.
  • props, type, priority: come per i webhook in ingresso.

La risposta viene pubblicata come creatore del webhook, con il nome sovrascritto se presente. Per risposte più lunghe di una risposta rapida, rispondi subito e pubblica in seguito con un webhook in ingresso o l'API.

Azioni sul messaggio

Un'azione sul messaggio è un webhook in uscita con Attiva quando impostato su Dal menu del messaggio. Non viene mai attivato dai messaggi pubblicati. Al contrario, le persone lo vedono nel menu di un messaggio: Azioni sul messaggio (⋯) › Altre azioni, sotto la voce Integrazioni, con la sua icona. L'interfaccia classica non mostra le azioni sul messaggio. Selezionandolo, quel singolo messaggio viene inviato agli URL di callback e una breve notifica indica Inviato a il nome dell'azione, oppure mostra il tuo ephemeral_text.

  • Dove viene visualizzato: nel canale del webhook o, in assenza di un canale, in tutti i canali pubblici della sua community. Solo i canali pubblici hanno azioni sul messaggio.
  • Gli Ospiti ottengono solo le azioni collegate a un canale in cui sono presenti, non quelle a livello di community.
  • Canali archiviati e di sola lettura: il messaggio può comunque essere inviato. L'archiviazione di un canale elimina i webhook collegati ad esso, quindi un canale archiviato mantiene solo le azioni a livello di community. Una risposta che la persona non può pubblicare lì viene mostrata solo a lei.
  • Limite di frequenza: ogni persona può eseguire 10 azioni sul messaggio al minuto, dopo una burst di 5. Oltre questo limite, il server risponde con 429.
  • Rete privata: come per gli altri webhook in uscita, gli indirizzi interni devono essere consentiti in Consenti connessioni interne non verificate a.

La richiesta

Il payload viene inviato come JSON o form-encoded, come indicato dal tipo di contenuto del 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_id e user_name sono la persona che ha selezionato l'azione; post_user_id e post_user_name sono l'autore del messaggio.
  • Viene inviato solo quel messaggio, mai il resto del suo thread.
  • files elenca i file del messaggio solo se la persona che ha selezionato l'azione può scaricarli. Il download di un link richiede una sessione o un token, come qualsiasi file dell'API.
  • Un messaggio da bruciare alla lettura viene inviato senza testo né file, con burn_on_read impostato su true.
  • In formato form-encoded, i file vengono inviati come campi ripetuti file_id, file_name e file_link, nello stesso ordine.

La risposta

Rispondi come per qualsiasi webhook in uscita (vedi Rispondere a un webhook in uscita): text o attachments pubblica una risposta nel canale, mentre "response_type": "comment" la pubblica nel thread del messaggio. Puoi anche rispondere con ephemeral_text (truncato a 300 caratteri): viene mostrato solo alla persona che ha selezionato l'azione, nella notifica. Un corpo vuoto non pubblica nulla.

{"ephemeral_text": "Ticket OPS-412 created"}

Con l'API

  • GET /api/v4/channels/{channel_id}/message_actions: le azioni selezionabili in un canale, con id, display_name, description e icon_url. Non vengono restituiti né token né URL di callback.
  • POST /api/v4/posts/{post_id}/message_actions/{hook_id}: esegue un'azione su un messaggio che puoi leggere. Risponde con {"ephemeral_text"}.

Quando un webhook non funziona

  • 501 dall'URL del webhook: i webhook in ingresso sono disabilitati sul server.
  • 400 "Failed to decode the payload…": il JSON non è valido, oppure il campo del form non si chiama payload. "No text specified." significa che la richiesta non contiene né text né attachments.
  • 403: il webhook è bloccato su un altro canale, oppure il suo proprietario non può più leggere il canale.
  • Un webhook in uscita non viene mai attivato: il canale è privato, il trigger non è la prima parola, il messaggio proviene da un webhook, oppure il webhook è impostato per attivarsi Dal menu del messaggio.
  • Un'azione del messaggio non è presente nel menu: il canale è privato, l'azione è associata a un altro canale, la persona è un ospite e l'azione non ha un canale, oppure i webhook in uscita sono disattivati.
  • 404 durante l'esecuzione di un'azione del messaggio: l'azione non esiste, oppure non copre il canale di quel messaggio per quella persona. 429: la persona ha eseguito più di 10 azioni in un minuto. 502: nessuno degli URL di callback è raggiungibile (il log contiene il motivo).
  • Log: con Attiva il debug di Webhook attivo (LogSettings.EnableWebhookDebugging) e il livello di log impostato su DEBUG, il server registra i payload delle richieste in entrata non riuscite. Le chiamate in uscita non riuscite vengono registrate come Outgoing Webhook POST failed.