Webhooks natifs de GLPI 11 : comment les configurer et les 3 détails qui bloquent l'intégration

Nous avons testé les webhooks de GLPI 11 sur notre instance de support : une URL avec port est refusée sans avertissement, l'envoi arrive sans Content-Type et dépend du cron. Configuration champ par champ, signature HMAC, tentatives et checklist.

GLPI 11 dispose de webhooks natifs : à chaque ticket créé, modifié ou supprimé, il prévient un autre système par HTTP, avec signature et nouvelles tentatives. Nous l'avons testé sur notre GLPI de support et la première configuration n'a rien livré. La raison n'apparaissait sur aucun écran : GLPI refuse toute URL avec un port, comme :8080 ou le :5678 par défaut de n8n. Ce guide montre comment le configurer, ce que le test a mesuré et les trois détails qui bloquent l'intégration.

Besoin d'aller au-delà du webhook sortant, avec des conditions, plusieurs étapes ou la réception de données externes ? Consultez Automatisations et webhooks dans GLPI avec NexTool.

Ce que fait le webhook natif (et ce qu'il ne fait pas)

Le webhook de GLPI 11 est sortant : lorsqu'un événement survient sur un élément, GLPI construit un message et l'envoie à une URL. Il sert à prévenir un ERP, ouvrir une carte dans Teams, alimenter un tableau de bord ou déclencher un flux dans n8n.

  • Événements : nouveau, mise à jour et suppression.
  • Éléments : les mêmes que la nouvelle API de GLPI 11, comme les tickets, problèmes, changements, actifs et utilisateurs.
  • Message : par défaut, l'élément au format de l'API (statut, demandeur, équipe, entité, dates), modifiable avec des variables.

Il ne reçoit rien. Pour qu'un autre système crée ou modifie des tickets dans GLPI, il faut passer par l'API.

Où le configurer

Dans Configuration > Webhooks > Ajouter :

Champ À quoi il sert
Entité et récursif Ne se déclenche que pour les éléments de cette entité (et de ses entités filles, si récursif)
Type d'élément et événement Ex. : Ticket + Nouveau
URL Destination. Accepte des variables, comme l'ID de l'élément dans le chemin
Méthode HTTP POST, PUT, PATCH ou GET
Nombre de tentatives Combien de fois renvoyer si la destination échoue
Journaliser dans l'historique de l'élément Enregistre chaque envoi dans l'historique du ticket
Enregistrer le corps de la réponse Conserve ce que la destination a répondu (doit être autorisé dans la configuration du serveur)

Et dans les onglets :

  • Critères : filtre les éléments qui déclenchent l'envoi, avec les mêmes critères que la recherche. Ex. : uniquement les tickets de la catégorie « Achats ».
  • Éditeur de charge utile : remplace le message par défaut par votre propre modèle, avec aperçu.
  • Sécurité : secret de la signature, défi de validation de l'URL et authentification OAuth.
  • En-têtes personnalisés : comme Authorization ou Content-Type.

Le test : ce que nous avons mesuré

Nous avons créé deux webhooks dans l'entité de test de notre GLPI de support (entreprise fictive Acme) et ouvert des tickets. L'un pointait vers une destination qui répond 200 ; l'autre, vers une destination qui répond une erreur 500.

Chronologie du test : URL avec port refusée, cible répondant 200 livrée en 8 secondes et cible répondant 500 recevant 3 tentatives, une par minute
Une URL avec port ne sort jamais de GLPI ; l'envoi prend un cycle du cron ; en cas d'erreur, GLPI réessaie chaque minute. Test NexTool, 3 octobre 2026.
Ce que nous avons vérifié Résultat
URL avec port (http://destino:8080/...) Refusée comme « unsafe », rien n'est envoyé
La même URL sans port Acceptée
Délai entre l'ouverture du ticket et la livraison 8 secondes (passage suivant du cron)
Destination en erreur 500 et « Nombre de tentatives » = 2 3 envois, un par minute, puis GLPI abandonne
Signature X-GLPI-signature Conforme : HMAC-SHA256 du corps + X-GLPI-timestamp
En-tête Content-Type Absent
Corps {"event": "new", "item": {...}} de 2,1 Ko pour un ticket simple

Les trois détails qui bloquent l'intégration

1. Une URL avec port est refusée

GLPI 11 n'appelle que les URL qui passent une liste d'autorisation (protection contre l'utilisation abusive du serveur). La règle par défaut accepte le domaine, l'IP et le chemin, mais n'accepte pas de port. L'erreur n'apparaît pas à l'écran : elle reste dans webhook.log, sous la forme « Webhook target URL ... is unsafe ».

Nous avons testé la fonction de GLPI lui-même :

URL Résultat
https://n8n.empresa.com.br/webhook/abc acceptée
https://n8n.empresa.com.br:5678/webhook/abc refusée
http://localhost:5678/webhook/abc refusée
http://localhost/webhook/abc acceptée

Solution : publiez la destination sur le port par défaut (443 ou 80), généralement derrière un proxy inverse. Cela règle aussi la question du HTTPS. Il est possible d'élargir la liste avec la constante GLPI_SERVERSIDE_URL_ALLOWLIST, mais elle s'applique à tout accès du serveur à des URL externes : modifiez-la avec prudence.

2. Sans Content-Type, la destination peut ne pas comprendre le JSON

GLPI envoie le corps en JSON, mais sans l'en-tête Content-Type. Des outils comme n8n et de nombreux frameworks ne lisent le corps comme du JSON que si l'en-tête l'indique.

Solution : dans En-têtes personnalisés, ajoutez Content-Type: application/json.

3. Sans cron, rien ne part

Le webhook n'est pas envoyé immédiatement : il est placé dans une file d'attente, et l'action automatique queuedwebhook l'envoie chaque minute, jusqu'à 50 à la fois. Si le cron de GLPI ne tourne pas, la file ne fait que grossir.

Solution : cron en ligne de commande chaque minute (voir l'étape 6 de comment installer GLPI 11) et, de temps en temps, un coup d'œil à Configuration > Webhooks > File d'attente des webhooks.

Comment valider la signature côté destination

Chaque envoi contient deux en-têtes : X-GLPI-timestamp (moment de l'événement) et X-GLPI-signature. La signature est le HMAC-SHA256 du corps suivi du timestamp, avec le secret du webhook. En Python :

import hmac, hashlib

def assinatura_valida(corpo: bytes, timestamp: str, assinatura: str, segredo: str) -> bool:
    calc = hmac.new(segredo.encode(), corpo + timestamp.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(calc, assinatura)

Deux précautions : - Le timestamp est celui de l'événement, pas de l'envoi. Il se répète lors des nouvelles tentatives. Si vous refusez les messages « anciens », prévoyez une fenêtre qui couvre les tentatives (quelques minutes). - Utilisez le corps brut, tel qu'il est arrivé. Si votre code décode puis réencode le JSON, la signature ne correspondra pas.

Pour ceux qui ont besoin de plus de garanties, l'onglet Sécurité propose le défi de validation : avant d'envoyer, GLPI appelle l'URL avec un crc_token, et la destination doit répondre avec le HMAC de ce jeton. Il existe aussi OAuth (client credentials) : GLPI obtient un jeton auprès du serveur d'autorisation et l'envoie en tant que Bearer.

Quand le webhook natif ne suffit pas

  • Recevoir des données d'un autre système : il faut l'API.
  • Une logique avec plusieurs conditions et étapes, comme « si la catégorie est X et que le demandeur fait partie de la direction, prévenir un canal et ouvrir une tâche » : les Critères filtrent, mais n'enchaînent pas d'actions.
  • Voir sur un seul écran ce qui a échoué et renvoyer en un clic. La file affiche le statut, mais le diagnostic se trouve dans webhook.log.

Dans ces cas, on fait appel à un orchestrateur comme n8n ou au module Automatisations de NexTool.

Checklist avant la mise en production

  1. Destination en HTTPS, sur le port par défaut, sans :porta dans l'URL.
  2. En-tête Content-Type: application/json.
  3. Signature validée côté destination, avec le corps brut et une fenêtre de temps pour les tentatives.
  4. Critères pour ne pas tout déclencher.
  5. « Nombre de tentatives » selon l'importance (3 est un bon début).
  6. Cron de GLPI exécuté chaque minute.
  7. « Journaliser dans l'historique de l'élément » activé, pour que le technicien voie ce qui a été envoyé.
  8. Test avec un ticket fictif avant d'ouvrir à tous.

Test NexTool du 3 octobre 2026, sur le GLPI 11.0.7 de notre support, entité de test avec des données fictives. Les webhooks et tickets de test ont été supprimés ensuite. Comportements également vérifiés dans le code source de GLPI 11.

Questions fréquentes

Oui. Dans Configuration > Webhooks, vous choisissez le type d'élément, l'événement (nouveau, mise à jour ou suppression) et l'URL cible. Les envois sont signés et réessayés.

Les causes les plus fréquentes sont une URL avec port (comme :8080 ou :5678), que GLPI refuse comme « unsafe », et un cron GLPI arrêté, car les webhooks partent par une file traitée chaque minute. La raison est consignée dans webhook.log.

Oui, à condition que n8n soit sur le port standard (en général derrière un reverse proxy HTTPS) et que vous ajoutiez l'en-tête Content-Type: application/json, que GLPI n'envoie pas de lui-même.

Calculez le HMAC-SHA256 du corps brut suivi de l'en-tête X-GLPI-timestamp, avec le secret du webhook, et comparez-le à l'en-tête X-GLPI-signature.

Le champ Nombre de tentatives fixe les répétitions après le premier envoi. Dans notre test, avec 2 tentatives, une cible répondant 500 a reçu 3 envois, un par minute.

Non. Le webhook natif est uniquement sortant. Pour qu'un autre système crée ou modifie des tickets, utilisez l'API de GLPI.

Besoin d'aide ?