Webhook qui n'arrive pas : la checklist de debug

Un webhook qui « n'arrive pas » est presque toujours l'un de ces cas : le fournisseur n'envoie pas, la requête ne joint pas votre serveur, ou votre serveur la reçoit mais la rejette. La méthode la plus rapide consiste à couper le problème en deux avec une URL de capture.

1. Coupez le problème en deux

Remplacez temporairement l'URL de votre endpoint par une URL de capture Tracehook, puis déclenchez l'événement. Si la requête apparaît dans l'inspecteur, le fournisseur envoie bien : le problème est de votre côté (réseau, serveur, code). Si rien n'apparaît, le problème est dans la configuration du fournisseur.

Cette seule étape évite des heures de lecture de logs au mauvais endroit. Elle montre aussi la requête exacte, headers et corps bruts, telle que votre code devrait la recevoir.

2. Rien n'arrive : vérifiez le fournisseur

Quand même l'URL de capture ne reçoit rien, regardez du côté de la configuration :

  • Les événements souscrits : l'événement que vous déclenchez fait-il partie de la liste cochée sur l'endpoint ?
  • L'environnement : chez Stripe, les endpoints du mode test et du mode live sont distincts. Un événement de test ne part pas vers un endpoint live.
  • L'état de l'endpoint : certains fournisseurs désactivent un endpoint après une série d'échecs.
  • Le journal de livraison : Stripe liste les tentatives sur la page de l'endpoint, GitHub dans l'onglet « Recent Deliveries » du webhook. Un envoi absent du journal n'a jamais été tenté.

3. La capture reçoit, votre serveur non : le réseau

Le fournisseur appelle votre URL depuis Internet. Elle doit donc être joignable depuis l'extérieur :

  • Pas de localhost ni d'adresse privée : 127.0.0.1, 192.168.x.x ou un nom interne ne sont pas joignables par le fournisseur.
  • DNS : le nom de domaine résout-il vers la bonne machine depuis l'extérieur ?
  • TLS : un certificat expiré, auto-signé ou une chaîne incomplète fait échouer l'appel avant même qu'il atteigne votre code.
  • Pare-feu, WAF ou protection anti-bot : une règle qui bloque les requêtes sans navigateur bloque aussi les webhooks.
Testez la joignabilité depuis une autre machine
curl -i -X POST https://api.example.com/webhooks/stripe \
  -H 'Content-Type: application/json' \
  -d '{"ping":true}'

4. Votre serveur reçoit mais le fournisseur voit un échec

Pour le fournisseur, seule une réponse 2xx rapide compte comme une livraison réussie. GitHub attend une réponse en moins de 10 secondes ; Stripe recommande de répondre 2xx avant tout traitement long. Répondez d'abord, traitez ensuite (file de messages, tâche en arrière-plan).

Méfiez-vous des redirections : une URL en http qui redirige vers https, ou un slash final ajouté par le framework, renvoie un 301 ou un 308 que la plupart des fournisseurs ne suivent pas. Configurez l'URL finale exacte.

5. La requête arrive mais le corps est vide ou illisible

Comparez le header Content-Type reçu dans Tracehook avec ce que votre code attend. GitHub, par exemple, peut envoyer application/json ou application/x-www-form-urlencoded (le JSON est alors dans un champ payload) selon le réglage du webhook.

Vérifiez aussi la taille : un proxy ou un framework qui limite le corps à quelques centaines de kilo-octets tronque ou rejette les gros événements.

6. La requête est rejetée par la vérification de signature

C'est la cause la plus fréquente une fois que tout le reste fonctionne : le corps a été parsé puis re-sérialisé avant le calcul du HMAC, ou le secret n'est pas celui de cet endpoint. Le guide dédié détaille la vérification et ses pièges.

Pour aller plus loin

Les guides et pages liés à ce sujet.

Coupez le problème en deux : créez une URL de capture.

Sans inscription