Webhooks
Un webhook entrant permet à un autre système de publier dans un canal en envoyant du JSON à une URL secrète. Un webhook sortant fait l'inverse : il envoie des messages à votre URL, ceux qui commencent par un mot déclencheur ou que les utilisateurs sélectionnent dans le menu des messages, et publie vos réponses.
Où gérer les webhooks
Ouvrez votre avatar en haut à droite, puis Intégrations. Les pages d'intégrations de la communauté actuelle listent Webhooks entrants et Webhooks sortants. Chaque webhook appartient à une seule communauté.
Par défaut, les administrateurs de la communauté et les administrateurs système peuvent créer des webhooks. Un administrateur système peut accorder ce droit à d'autres rôles dans les paramètres de permissions de la Console système. Il peut également désactiver chaque type de webhook dans Console système › Intégrations › Gestion des intégrations : Activer les webhooks entrants et Activer les webhooks sortants sont tous deux activés par défaut.

Créer un webhook entrant
- Dans Intégrations, sélectionnez Webhooks entrants, puis Ajouter des Webhooks entrants.
- Renseignez un Titre et une Description : ils ne s'affichent que sur les pages d'intégrations.
- Sélectionnez le Canal de destination par défaut des messages. Pour un canal privé, vous devez en être membre.
- Cochez Verrouiller le canal si les expéditeurs ne doivent pas pouvoir publier ailleurs.
- Définissez éventuellement un Nom d'utilisateur et une URL de Photo de profil pour ses messages (voir Nom et icône).
- Choisissez Enregistrer. Copiez l'URL affichée :
https://chat.example.com/hooks/<key>.
Via l'API : POST /api/v4/hooks/incoming avec {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"} ; l'id de la réponse est la clé. Depuis la ligne de commande : amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI".
Envoyer un message à un webhook entrant
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:"}'
Le serveur répond 200 avec le corps ok. Il accepte aussi application/x-www-form-urlencoded avec le JSON dans un champ payload, comme les webhooks de Slack, de sorte que les outils conçus pour Slack fonctionnent généralement sans modification.
| Champ | Signification |
|---|---|
text | Le message, au format Markdown. Obligatoire, sauf s'il y a des attachments. Un texte plus long que la limite de message du serveur est divisé en plusieurs messages. |
channel | Un autre canal de la communauté du webhook, par son nom (ops-alerts ou #ops-alerts), ou @username pour un message personnel de la part du propriétaire du webhook. Refusé lorsque le webhook est verrouillé sur son canal. L'ancien nom town-square atteint toujours le canal par défaut de la communauté, désormais appelé general. |
username, icon_url, icon_emoji | Le nom et l'image à afficher, lorsque le serveur autorise les substitutions. |
attachments | Pièces jointes du message, affichées sous forme de cartes (ci-dessous). |
props | Propriétés supplémentaires stockées sur le message, pour les applications qui les lisent. |
type | Un type de message personnalisé, tel que custom_poll, pour une application qui l'affiche. Les types commençant par system_ sont refusés. |
root_id | L'identifiant du premier message d'un fil de discussion, pour y répondre. |
priority | Priorité du message, par exemple {"priority": "urgent"}. |
silent | true envoie le message sans notifications push. |
Chaque message publié par un webhook porte une étiquette BOT à côté de son nom, même lorsqu'il s'affiche sous le nom de son créateur, afin que les utilisateurs puissent le distinguer d'un message d'une personne réelle. Les messages de webhook ne déclenchent jamais de webhooks sortants.
Nom et icône
Un webhook publie au nom de la personne qui l'a créé, sauf si le serveur autorise les substitutions. Deux paramètres dans Console système › Intégrations › Gestion des intégrations, tous deux désactivés par défaut, modifient ce comportement :
- Permettre aux intégrations de remplacer les noms d'utilisateur (
ServiceSettings.EnablePostUsernameOverride) : le Nom d'utilisateur du webhook ou leusernamede la requête est affiché à la place ; en l'absence des deux, le nom estwebhook. - Permettre aux intégrations de redéfinir les images de profil utilisateur (
ServiceSettings.EnablePostIconOverride) : la Photo de profil du webhook, ou leicon_urlouicon_emojide la requête, est affichée.
Une valeur dans la requête prime sur celle enregistrée sur le webhook.
Pièces jointes
Les pièces jointes ajoutent du contenu structuré sous le texte. Elles suivent le format de pièce jointe de message de 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
}]
}
| Champ | Signification |
|---|---|
fallback | Texte brut pour les endroits qui ne peuvent pas afficher la carte, tels que les notifications. |
color | La barre de couleur : une couleur en hexadécimal, ou good, warning, danger. |
pretext | Texte au-dessus de la carte. |
author_name, author_link, author_icon | Une ligne d'en-tête. |
title, title_link | Le titre de la carte, éventuellement un lien. |
text | Le corps de la carte, au format Markdown. |
fields | Une liste de {"title", "value", "short"} ; les champs short sont côte à côte. |
image_url, thumb_url | Une grande image en dessous, ou une petite à côté. |
footer, footer_icon, ts | Une ligne de pied de page et une heure (secondes Unix). |
actions | Boutons et menus : voir Messages interactifs. |
Cartes : étapes et graphiques
Antimatter ajoute deux champs aux pièces jointes, affichés par l’interface par défaut :
stages: les étapes d’un pipeline sous forme de pastilles, jusqu’à 20. Chaque étape est{"name", "status"}, avec un statut depassed,failed,running,pending,skippedoucanceled.chart: un petit graphique linéaire des valeurs récentes,{"values": [2 to 200 numbers], "threshold": number, "label": "…"}. Le seuil est représenté par une ligne pointillée, correspondant à la limite de l’alerte.
{
"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’interface classique et les autres clients ignorent ces deux champs, il est donc recommandé d’inclure l’essentiel dans text ou fields également.
Créer un webhook sortant
Un webhook sortant surveille les canaux public d'une communauté. Il envoie un message à votre URL lorsque le premier mot du message correspond à l'un de ses mots déclencheurs, ou lorsque quelqu'un le sélectionne dans le menu du message (une action de message).
- Dans Intégrations, sélectionnez Webhooks sortants, puis Ajouter des Webhooks sortants.
- Renseignez le Titre et la Description.
- Choisissez le Type de contenu de la requête :
application/x-www-form-urlencodedouapplication/json. - Choisissez un Canal, saisissez des Mots-clés (Un par ligne), ou les deux. Avec un canal et sans mots-clés, chaque message de ce canal est envoyé. Avec les deux, le message doit correspondre aux deux critères.
- Sous Déclencher lorsque, choisissez Premier mot correspond exactement à un mot déclencheur, Le premier mot commence avec un mot déclencheur, ou Depuis le menu des messages. Avec Depuis le menu des messages, les mots déclencheurs disparaissent, le Canal est facultatif (sans canal, l'action est proposée dans tous les canaux publics de la communauté) et le Titre est obligatoire : c'est le nom de l'action dans le menu.
- Saisissez les URLs de rappel (une par ligne). Chaque URL reçoit chaque message correspondant.
- Définissez facultativement le Nom d'utilisateur et la Photo de profil utilisés pour les réponses. Pour une action depuis le menu des messages, le champ Icône remplace Photo de profil : l'URL d'une image .png ou .jpg ou, dans l'interface par défaut d'Antimatter, une image téléversée. Le menu l'affiche en gris ; sans icône, l'action reçoit une icône neutre.
- Choisissez Enregistrer et copiez le jeton affiché. Votre service l’utilise pour vérifier que les requêtes proviennent de votre serveur.
Via l'API : POST /api/v4/hooks/outgoing avec {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"} (trigger_when : 0 pour une correspondance exacte, 1 pour « commence par », 2 pour « depuis le menu du message »). Un webhook avec trigger_when 2 n'accepte pas de mots déclencheurs et nécessite un display_name. Envoyez son icône avec POST /api/v4/hooks/outgoing/{hook_id}/icon (multipart, champ image : PNG, JPEG ou GIF, stockée en PNG de 128 px) ; son icon_url pointe alors vers GET /api/v4/hooks/outgoing/{hook_id}/icon.
ServiceSettings.AllowedUntrustedInternalConnections). Le serveur n'appelle pas les adresses privées dans le cas contraire.La requête sortante
Antimatter envoie une requête POST avec ces champs, en JSON ou encodé en formulaire selon le type de contenu :
{
"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": ""
}
Comparez token avec le jeton du webhook avant toute action. Dans la version encodée en formulaire, timestamp est exprimé en secondes plutôt qu'en millisecondes. Le serveur attend votre réponse pendant la durée autorisée par Délai d’attente des requêtes d’intégration (30 secondes par défaut, ServiceSettings.OutgoingIntegrationRequestsTimeout).
Répondre à un webhook sortant
Pour publier une réponse, répondez avec du JSON. Pour ne rien publier, répondez avec un corps vide.
{
"text": "Deploying **api 2.4.0** to staging…",
"response_type": "comment",
"username": "deploy-bot",
"icon_url": "https://chat.example.com/static/deploy.png"
}
textetattachments: la réponse. Sans l'un ou l'autre, rien n'est publié.response_type:commentpublie la réponse dans le fil de discussion du message déclencheur ; sinon, elle est publiée dans le canal.username,icon_url: affichés lorsque le serveur autorise les substitutions ; sinon, les valeurs propres au webhook sont utilisées.props,type,priority: comme pour les webhooks entrants.
La réponse est publiée au nom du créateur du webhook, sous le nom substitué s'il y en a un. Pour toute réponse plus longue qu'une réponse rapide, répondez immédiatement et publiez plus tard avec un webhook entrant ou l'API.
Actions de message
Une action de message est un webhook sortant dont Déclencher lorsque est réglé sur Depuis le menu du message. Elle ne se déclenche jamais sur les messages publiés. En revanche, elle apparaît dans le menu d'un message : Actions (⋯) › Plus d'actions, sous l'en-tête Intégrations, avec son icône. L'interface classique n'affiche pas les actions de message. La sélectionner envoie ce message unique aux URL de rappel, et un avis bref indique Envoyé à le nom de l'action, ou affiche votre ephemeral_text.
- Où elle s'affiche : dans le canal du webhook, ou, sans canal, dans tous les canaux publics de sa communauté. Seuls les canaux publics disposent d'actions de message.
- Les Utilisateurs invités n'obtiennent que les actions liées à un canal auquel ils appartiennent, et non celles de toute la communauté.
- Canaux archivés et en lecture seule : le message peut toujours être envoyé. L'archivage d'un canal supprime les webhooks qui y sont liés, de sorte qu'un canal archivé ne conserve que les actions de toute la communauté. Une réponse que la personne ne pouvait pas y publier ne lui est affichée qu'à elle seule.
- Limite de débit : chaque personne peut exécuter 10 actions de message par minute, après une rafale de 5. Au-delà, le serveur répond
429. - Réseaux privés : comme pour les autres webhooks sortants, les adresses internes doivent être autorisées dans Autoriser les connexions internes non approuvées à .
La requête
La charge utile est envoyée en JSON ou encodée en formulaire, selon le type de contenu du 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_idetuser_namesont la personne qui a sélectionné l'action ;post_user_idetpost_user_namesont l'auteur du message.- Seul ce message est envoyé, jamais le reste de son fil de discussion.
filesliste les fichiers du message uniquement si la personne qui a sélectionné l'action peut les télécharger. Le téléchargement d'unlinknécessite une session ou un jeton, comme tout fichier de l'API.- Un message à effacement après lecture est envoyé sans son texte ni ses fichiers, avec
burn_on_readdéfini surtrue. - En encodage de formulaire, les fichiers sont transmis sous forme de champs
file_id,file_nameetfile_linkrépétés, dans le même ordre.
La réponse
Répondez comme pour n'importe quel webhook sortant (voir Réponse à un webhook sortant) : text ou attachments publie une réponse dans le canal, et "response_type": "comment" la publie dans le fil de discussion du message. Vous pouvez également répondre avec ephemeral_text (limité à 300 caractères) : elle n'est visible que par la personne qui a sélectionné l'action, dans la notification. Un corps vide ne publie rien.
{"ephemeral_text": "Ticket OPS-412 created"}
Avec l'API
GET /api/v4/channels/{channel_id}/message_actions: les actions que vous pouvez sélectionner dans un canal, avecid,display_name,descriptioneticon_url. Ni les jetons ni les URL de rappel ne sont retournés.POST /api/v4/posts/{post_id}/message_actions/{hook_id}: exécute une action sur un message que vous pouvez lire. Elle répond{"ephemeral_text"}.
Quand un webhook ne fonctionne pas
- 501 depuis l'URL du hook : les webhooks entrants sont désactivés sur le serveur.
- 400 « Failed to decode the payload… » : le JSON est invalide, ou le champ du formulaire n'est pas nommé
payload. « No text specified. » signifie que la requête ne contient nitextniattachments. - 403 : le webhook est verrouillé sur un autre canal, ou son propriétaire ne peut plus lire le canal.
- Un webhook sortant ne se déclenche jamais : le canal est privé, le déclencheur n'est pas le premier mot, le message provient d'un webhook, ou le webhook est configuré pour se déclencher Depuis le menu du message.
- Une action de message n'apparaît pas dans le menu : le canal est privé, l'action est liée à un autre canal, la personne est un invité et l'action n'a pas de canal, ou les webhooks sortants sont désactivés.
- 404 lors de l'exécution d'une action de message : l'action n'existe pas, ou elle ne couvre pas le canal de ce message pour cette personne. 429 : la personne a exécuté plus de 10 actions en une minute. 502 : aucune des URL de rappel n'a pu être atteinte (la raison figure dans le journal).
- Journal : avec Activer le débogage des webhooks activé (
LogSettings.EnableWebhookDebugging) et le niveau de journalisation réglé surDEBUG, le serveur enregistre les charges des requêtes entrantes en échec. Les appels sortis en échec sont journalisés commeOutgoing Webhook POST failed.