Webhooks

Ein eingehender Webhook ermöglicht es einem anderen System, Nachrichten in einen Kanal zu senden, indem es JSON an eine geheime URL sendet. Ein ausgehender Webhook macht das Gegenteil: Er sendet Nachrichten an Ihre URL – entweder solche, die mit einem Auslösewort beginnen, oder solche, die Personen im Nachrichtenmenü dafür auswählen –, und veröffentlicht Ihre Antwort.

Webhooks verwalten

Öffnen Sie das Community-Menü, dann Teameinstellungen, und klicken Sie am Ende der Registerkarten auf Integrationen. Auf den Integrationsseiten der aktuellen Community werden Eingehende Webhooks und Ausgehende Webhooks aufgelistet. Jeder Webhook gehört zu einer Community.

Standardmäßig können Community-Administratoren und Systemadministratoren Webhooks erstellen. Ein Systemadministrator kann dieses Recht in den Berechtigungseinstellungen der Systemkonsole auch anderen Rollen zuweisen. Ein Systemadministrator kann zudem jede Art von Webhook in Systemkonsole › Integrationen › Integrationsverwaltung deaktivieren: Aktiviere eingehende Webhooks und Aktiviere ausgehende Webhooks sind standardmäßig beide aktiviert.

A channel with messages from a CI bot and from GitHub, shown as cards with fields, pipeline stages and a button
Integrationsnachrichten als Karten dargestellt: Felder, Pipeline-Stufen und eine Aktionsbutton.

Einen eingehenden Webhook erstellen

  1. Wählen Sie in Integrationen Eingehende Webhooks und dann Eingehenden Webhook hinzufügen.
  2. Geben Sie einen Titel und eine Beschreibung ein: Diese werden nur auf den Integrationsseiten angezeigt.
  3. Wählen Sie den Kanal, in den die Nachrichten standardmäßig gesendet werden. Für einen privaten Kanal müssen Sie Mitglied davon sein.
  4. Aktivieren Sie Auf diesen Kanal beschränken, wenn Absender nicht in anderen Kanälen posten dürfen.
  5. Setzen Sie optional einen Benutzernamen und eine Profilbild-URL für seine Nachrichten (siehe Name und Icon).
  6. Wählen Sie Speichern. Kopieren Sie die angezeigte URL: https://chat.example.com/hooks/<key>.
Die URL ist das einzige Geheimnis: Jeder, der sie hat, kann in den Kanal posten. Halten Sie sie aus öffentlichen Repositories heraus und löschen Sie den Webhook, wenn er geleakt wird.

Mit der API: POST /api/v4/hooks/incoming mit {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"}; die id in der Antwort ist der Schlüssel. Von der Kommandozeile: amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI".

Eine Nachricht an einen eingehenden Webhook senden

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

Der Server antwortet mit 200 und dem Body ok. Er akzeptiert auch application/x-www-form-urlencoded mit dem JSON in einem payload-Feld, wie bei Webhooks von Slack, sodass Tools, die für Slack erstellt wurden, in der Regel ohne Änderungen funktionieren.

FeldBedeutung
textDie Nachricht in Markdown. Pflichtfeld, sofern keine attachments vorhanden sind. Texte, die das Nachrichtenlimit des Servers überschreiten, werden in mehrere Nachrichten aufgeteilt.
channelEin anderer Kanal der Community des Webhooks, nach Name (ops-alerts oder #ops-alerts), oder @username für eine Direktnachricht vom Besitzer des Webhooks. Abgelehnt, wenn der Webhook an seinen Kanal gebunden ist. Der alte Name town-square erreicht weiterhin den Standardkanal der Community, der jetzt general heißt.
username, icon_url, icon_emojiDer Name und das Bild, die angezeigt werden, wenn der Server Überschreibungen zulässt.
attachmentsAnhänge der Nachricht, dargestellt als Karten (unten).
propsZusätzliche Eigenschaften, die in der Nachricht gespeichert werden, für Apps, die diese lesen. Das Posten in einen Forum-Kanal erfordert props.am_thread_title (1 bis 100 Zeichen): Der Hook wird ohne diesen Wert abgelehnt (siehe Foren akzeptieren nur Themen).
typeEin benutzerdefinierter Nachrichtentyp, z. B. custom_poll, für eine App, die ihn darstellt. Typen, die mit system_ beginnen, werden abgelehnt.
root_idDie ID der ersten Nachricht eines Threads, um in diesem Thread zu antworten.
priorityNachrichtenpriorität, z. B. {"priority": "urgent"}.
silenttrue sendet die Nachricht ohne Push-Benachrichtigungen.

Jede Nachricht, die ein Webhook veröffentlicht, trägt neben ihrem Namen das BOT-Kennzeichen, selbst wenn sie unter dem Namen ihres Erstellers angezeigt wird, damit man sie von einer Nachricht einer echten Person unterscheiden kann. Webhook-Nachrichten lösen niemals ausgehende Webhooks aus.

Name und Symbol

Ein Webhook postet als die Person, die ihn erstellt hat, es sei denn, der Server erlaubt Überschreibungen. Zwei Einstellungen in Systemkonsole › Integrationen › Integrationsverwaltung, beide standardmäßig deaktiviert, ändern das:

  • Erlaube Integrationen den Benutzernamen zu ändern (ServiceSettings.EnablePostUsernameOverride): Der Benutzername des Webhooks oder der username der Anfrage wird angezeigt; ohne beide wird der Name webhook verwendet.
  • Erlaube Integrationen das Profilbild zu ändern (ServiceSettings.EnablePostIconOverride): Das Profilbild des Webhooks oder das icon_url bzw. icon_emoji der Anfrage wird angezeigt.

Ein Wert in der Anfrage hat Vorrang vor dem auf dem Webhook gespeicherten Wert.

Anhänge

Anhänge fügen strukturierte Inhalte unter dem Text hinzu. Sie folgen dem Nachrichtenanhänge-Format von 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
  }]
}
FeldBedeutung
fallbackEinfacher Text für Stellen, die die Karte nicht anzeigen können, z. B. Benachrichtigungen.
colorDie Farbleiste: eine Hex-Farbe oder good, warning, danger.
pretextText über der Karte.
author_name, author_link, author_iconEine kleine Kopfzeile.
title, title_linkDer Titel der Karte, optional ein Link.
textDer Inhalt der Karte, in Markdown.
fieldsEine Liste von {"title", "value", "short"}; short-Felder werden nebeneinander angeordnet.
image_url, thumb_urlEin großes Bild unten oder ein kleines an der Seite.
footer, footer_icon, tsEine Fußzeile und eine Zeit (Unix-Sekunden).
actionsSchaltflächen und Menüs: siehe Interaktive Nachrichten.

Karten: Stufen und Diagramme

Antimatter fügt Anhängen zwei Felder hinzu, die von der Standardoberfläche dargestellt werden:

  • stages: die Schritte einer Pipeline als Pills, bis zu 20. Jeder Schritt ist {"name", "status"} mit einem Status von passed, failed, running, pending, skipped oder canceled.
  • chart: ein kleines Liniendiagramm mit den letzten Werten, {"values": [2 to 200 numbers], "threshold": number, "label": "…"}. Der Schwellenwert wird als gestrichelte Linie dargestellt, für das Limit eines Alerts.
{
  "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"}
  }]
}

Die klassische Oberfläche und andere Clients ignorieren diese beiden Felder. Fügen Sie daher auch die wesentlichen Informationen in text oder fields ein.

Einen ausgehenden Webhook erstellen

Ein ausgehender Webhook überwacht die Öffentlichen Kanäle einer Community. Er sendet eine Nachricht an Ihre URL, entweder wenn das erste Wort der Nachricht einem seiner Auslösewörter entspricht, oder wenn jemand ihn im Menü der Nachricht auswählt (eine Nachrichtenaktion).

  1. Wählen Sie in Integrationen Ausgehende Webhooks und dann Ausgehenden Webhook hinzufügen.
  2. Geben Sie Titel und Beschreibung ein.
  3. Wählen Sie den Inhaltstyp der Anfrage: application/x-www-form-urlencoded oder application/json.
  4. Wählen Sie einen Kanal, geben Sie Auslösewörter (eins pro Zeile) ein oder beides. Bei einem Kanal ohne Auslösewörter wird jede Nachricht dieses Kanals gesendet. Bei beiden muss die Nachricht beide Bedingungen erfüllen.
  5. Unter Auslösen sobald wählen Sie Erstes Wort entspricht exakt einem Auslösewort, Erstes Wort startet mit dem Auslösewort oder Aus dem Nachrichtenmenü. Bei Aus dem Nachrichtenmenü verschwinden die Auslösewörter, der Kanal ist optional (ohne einen wird die Aktion in jedem öffentlichen Kanal der Community angeboten) und der Titel ist erforderlich: Er ist der Name der Aktion im Menü.
  6. Geben Sie die Callback-URLs (eine pro Zeile) ein. Jede URL erhält jede passende Nachricht.
  7. Optional können Sie den Benutzernamen und das Profilbild für Antworten festlegen. Für eine Aktion aus dem Nachrichtenmenü ersetzt das Feld Icon das Profilbild: die URL eines .png- oder .jpg-Bildes oder, in der Standardoberfläche von Antimatter, ein hochgeladenes Bild. Das Menü zeigt es in Grau an; ohne eines erhält die Aktion ein neutrales Icon.
  8. Wählen Sie Speichern und kopieren Sie den angezeigten Token. Ihr Dienst verwendet ihn, um zu überprüfen, ob die Anfragen von Ihrem Server stammen.

Über die API: POST /api/v4/hooks/outgoing mit {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"} (trigger_when: 0 für exakte Übereinstimmung, 1 für „beginnt mit“, 2 für „aus dem Nachrichtenmenü“). Ein Webhook mit trigger_when 2 benötigt keine Triggerwörter, aber einen display_name. Sein Icon wird mit POST /api/v4/hooks/outgoing/{hook_id}/icon hochgeladen (multipart, Feld image: PNG, JPEG oder GIF, gespeichert als 128-px-PNG); sein icon_url verweist dann auf GET /api/v4/hooks/outgoing/{hook_id}/icon.

The outgoing webhook form with Trigger When set to From the message menu, and the Icon field below it
Auslöser auf Aus dem Nachrichtenmenü gesetzt, mit dem Feld Symbol.
Wenn Ihr Dienst in einem privaten Netzwerk läuft, muss ein Systemadministrator dessen Adresse in Erlaube ungesicherte interne Verbindungen zu (ServiceSettings.AllowedUntrustedInternalConnections) erlauben. Andernfalls ruft der Server keine privaten Adressen auf.

Die ausgehende Anfrage

Antimatter sendet einen POST mit diesen Feldern, als JSON oder formular-kodiert, je nach Inhaltstyp:

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

Vergleichen Sie token mit dem Token des Webhooks, bevor Sie etwas tun. In der form-kodierten Version ist timestamp in Sekunden statt in Millisekunden angegeben. Der Server wartet auf Ihre Antwort so lange, wie es Zeitüberschreitung der Integrationsanfrage zulässt (standardmäßig 30 Sekunden, ServiceSettings.OutgoingIntegrationRequestsTimeout).

Antwort auf einen ausgehenden Webhook

Um eine Antwort zu senden, antworten Sie mit JSON. Um nichts zu senden, antworten Sie mit einem leeren Body.

{
  "text": "Deploying **api 2.4.0** to staging…",
  "response_type": "comment",
  "username": "deploy-bot",
  "icon_url": "https://chat.example.com/static/deploy.png"
}
  • text und attachments: die Antwort. Ohne eines davon wird nichts gesendet.
  • response_type: comment sendet die Antwort in den Thread der auslösenden Nachricht; andernfalls wird sie in den Kanal gesendet.
  • username, icon_url: werden angezeigt, wenn der Server Überschreibungen zulässt; andernfalls werden die eigenen Werte des Webhooks verwendet.
  • props, type, priority: wie bei eingehenden Webhooks.

Die Antwort wird als Ersteller des Webhooks gesendet, unter dem überschriebenen Namen, falls vorhanden. Für alles, was länger als eine kurze Antwort ist, antworten Sie sofort und senden Sie später mit einem eingehenden Webhook oder der API.

Nachrichtenaktionen

Eine Nachrichten-Aktion ist ein ausgehendes Webhook, bei dem Auslösen sobald auf Aus dem Nachrichtenmenü gesetzt ist. Sie wird nie durch gesendete Nachrichten ausgelöst. Stattdessen sehen sie die Aktion im Menü einer Nachricht: Nachrichten-Aktionen (⋯) › Weitere Aktionen, unter der Überschrift Integrationen, mit ihrem Icon. Die klassische Oberfläche zeigt Nachrichten-Aktionen nicht an. Wenn die Aktion ausgewählt wird, wird genau diese Nachricht an die Callback-URLs gesendet. Eine kurze Benachrichtigung zeigt an, dass die Nachricht an den Namen der Aktion gesendet wurde, oder zeigt den von Ihnen definierten ephemeral_text an.

  • Anzeigeposition: im Kanal des Webhooks oder, ohne Kanal, in jedem öffentlichen Kanal der Community. Nur öffentliche Kanäle haben Nachrichten-Aktionen.
  • Gäste erhalten nur die Aktionen, die an einen Kanal gebunden sind, in dem sie sich befinden, nicht aber die communityweiten Aktionen.
  • Archivierte und schreibgeschützte Kanäle: Die Nachricht kann dennoch gesendet werden. Beim Archivieren eines Kanals werden die daran gebundenen Webhooks gelöscht, sodass ein archivierter Kanal nur noch die communityweiten Aktionen behält. Eine Antwort, die die Person dort nicht posten konnte, wird nur ihr angezeigt.
  • Ratenbegrenzung: Jede Person kann 10 Nachrichten-Aktionen pro Minute ausführen, nach einem Anfangsbudget von 5. Darüber hinaus antwortet der Server mit 429.
  • Private Netzwerke: Wie bei anderen ausgehenden Webhooks müssen interne Adressen unter Erlaube ungesicherte interne Verbindungen zu erlaubt sein.

Die Anfrage

Die Nutzlast wird als JSON oder formularkodiert gesendet, wie es der Inhaltstyp des Webhooks angibt:

{
  "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 und user_name sind die Person, die die Aktion ausgewählt hat; post_user_id und post_user_name der Autor der Nachricht.
  • Nur diese Nachricht wird gesendet, niemals der Rest ihres Threads.
  • files listet die Dateien der Nachricht nur dann, wenn die Person, die die Aktion ausgewählt hat, diese herunterladen darf. Zum Herunterladen eines link-Elements wird eine Sitzung oder ein Token benötigt, wie bei jeder Datei der API.
  • Eine Nachricht, die nach dem Lesen gelöscht wird, wird ohne Text und Dateien gesendet, wobei burn_on_read auf true gesetzt ist.
  • Bei der form-encoded-Übermittlung kommen die Dateien als wiederholte Felder file_id, file_name und file_link in derselben Reihenfolge.

Die Antwort

Die Antwort erfolgt wie bei jedem ausgehenden Webhook (siehe Antwort auf einen ausgehenden Webhook): text oder attachments veröffentlicht eine Antwort im Kanal, und "response_type": "comment" veröffentlicht sie im Thread der Nachricht. Sie können auch mit ephemeral_text antworten (auf 300 Zeichen begrenzt): Dies wird nur der Person angezeigt, die die Aktion ausgewählt hat, in der Benachrichtigung. Ein leerer Body veröffentlicht nichts.

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

Mit der API

  • GET /api/v4/channels/{channel_id}/message_actions: Die Aktionen, die Sie in einem Kanal auswählen können, mit id, display_name, description und icon_url. Weder Tokens noch Callback-URLs werden zurückgegeben.
  • POST /api/v4/posts/{post_id}/message_actions/{hook_id}: Führt eine Aktion auf einer Nachricht aus, die Sie lesen können. Es wird {"ephemeral_text"} als Antwort gesendet.

Wenn ein Webhook nicht funktioniert

  • 501 von der Hook-URL: Eingehende Webhooks sind auf dem Server deaktiviert.
  • 400 "Failed to decode the payload…": Das JSON ist ungültig oder das Formularfeld heißt nicht payload. "No text specified." bedeutet, dass die Anfrage weder text noch attachments enthält.
  • 403: Der Webhook ist an einen anderen Kanal gebunden oder sein Besitzer kann den Kanal nicht mehr lesen.
  • Ein ausgehender Webhook wird nie ausgelöst: Der Kanal ist privat, das Trigger-Wort ist nicht das erste Wort der Nachricht, die Nachricht stammt von einem Webhook oder der Webhook ist so konfiguriert, dass er Aus dem Nachrichtenmenü ausgelöst wird.
  • Eine Nachrichtaktion fehlt im Menü: Der Kanal ist privat, die Aktion ist einem anderen Kanal zugeordnet, die Person ist Gast und die Aktion hat keinen Kanal oder ausgehende Webhooks sind deaktiviert.
  • 404 beim Ausführen einer Nachrichtaktion: Die Aktion existiert nicht oder deckt den Kanal dieser Nachricht für diese Person nicht ab. 429: Die Person hat mehr als 10 Aktionen in einer Minute ausgeführt. 502: Keine der Callback-URLs konnte erreicht werden (der Grund steht im Protokoll).
  • Ein Post in ein Forum wird abgelehnt: Die Nachricht des Hooks benötigt einen Titel (props.am_thread_title); der Fehler nennt den Grund, wie z. B. app.post.forum.title_required.app_error, anstelle eines allgemeinen Fehlers (siehe Kanal-Typen).
  • Protokolle: Wenn Aktiviere Webhook-Debugging aktiviert ist (LogSettings.EnableWebhookDebugging) und das Protokolllevel auf DEBUG steht, protokolliert der Server die Nutzlasten fehlgeschlagener eingehender Anfragen. Fehlgeschlagene ausgehende Aufrufe werden als Outgoing Webhook POST failed protokolliert.