Webhook
Un webhook est un callback HTTP automatisé qui envoie des données en temps réel d’une application vers une autre lorsqu’un événement spécifique se produit, via une requête HTTP POST vers une URL prédéfinie.
L’analogie la plus simple : le polling (l’alternative aux webhooks), c’est vérifier votre boîte aux lettres toutes les 5 minutes. Un webhook, c’est le facteur qui sonne à votre porte quand un courrier arrive. Vous ne demandez rien, l’information vient à vous, instantanément, uniquement quand il y a quelque chose à signaler. C’est le mécanisme push fondamental du web moderne, utilisé par Stripe (paiements), GitHub (code pushes), Zapier (automatisations), et la quasi-totalité des plateformes SaaS.
- Catégorie
- Mécanisme de communication inter-applications
- Principe
- Push (serveur → client), déclenché par un événement
- Protocole
- HTTP POST (HTTPS requis en production)
- Format de données
- JSON (dominant), XML, form-encoded
- Synonymes
- Web callback, HTTP push API, reverse API
- Opposé
- Polling (pull model)
Comment fonctionne un webhook
Le fonctionnement d’un webhook se décompose en cinq étapes :
1. Inscription. Vous fournissez une URL de callback (votre endpoint) à l’application source et vous spécifiez les événements qui vous intéressent (par exemple payment.completed, order.created). Cette configuration se fait soit via une interface web, soit via une API.
2. Événement. Quelque chose se produit dans l’application source : un client paie, un code est poussé, un document est modifié, un modèle ML termine un entraînement.
3. Envoi. L’application source construit une requête HTTP POST contenant les données de l’événement (le payload, généralement en JSON) et l’envoie à votre URL de callback.
4. Réception et traitement. Votre serveur reçoit la requête, vérifie la signature (sécurité), traite les données, et retourne un code HTTP 200 OK pour confirmer la réception.
5. Retry en cas d’échec. Si votre serveur est indisponible ou retourne une erreur, la plupart des fournisseurs de webhooks re-tentent l’envoi selon un backoff exponentiel (après 1 minute, 5 minutes, 30 minutes, etc.).
Exemple concret : quand un paiement Stripe réussit, Stripe envoie un webhook POST à votre serveur avec un payload JSON contenant le type d’événement, le montant, la devise, l’ID client et le statut. Votre serveur met à jour la commande et envoie un email de confirmation, le tout en temps réel.
{
"id": "evt_1234567890",
"type": "payment_intent.succeeded",
"created": 1711000000,
"data": {
"object": {
"id": "pi_abc123",
"amount": 5000,
"currency": "eur",
"status": "succeeded",
"customer": "cus_xyz789"
}
}
}Webhook vs API vs polling
| Aspect | Webhook (push) | API classique (pull) | Polling |
|---|---|---|---|
| Qui initie | Le serveur source | Le client | Le client (de manière répétée) |
| Temps réel | Oui (instantané) | Non (sur demande) | Quasi (dépend de l’intervalle) |
| Efficacité | Élevée (1 requête par événement) | Variable | Faible (requêtes inutiles si pas d’événement) |
| Charge serveur | Faible | Variable | Élevée (requêtes continues) |
| Complexité | Endpoint public HTTPS requis | Le client contrôle les appels | Simple à implémenter |
| Fiabilité | Dépend des retries du fournisseur | Le client gère les erreurs | Le client gère les erreurs |
| Cas d’usage | Notifications d’événements, intégrations | Lecture/écriture de données, CRUD | Quand les webhooks ne sont pas disponibles |
Les webhooks et les API ne sont pas concurrents. Ils se complètent. Une application typique utilise des API pour lire et écrire des données (CRUD), et des webhooks pour être notifiée en temps réel quand quelque chose change. Stripe expose une API pour créer des paiements et des webhooks pour vous notifier du résultat.
Implémenter un endpoint webhook
Recevoir un webhook nécessite un serveur HTTP accessible publiquement via HTTPS. Voici un exemple minimal en Python avec FastAPI :
from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib
app = FastAPI()
WEBHOOK_SECRET = "whsec_votre_secret_ici"
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
"""Vérifie la signature HMAC du webhook"""
expected = hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
@app.post("/webhooks/stripe")
async def handle_stripe_webhook(request: Request):
payload = await request.body()
signature = request.headers.get("Stripe-Signature", "")
# 1. Vérifier la signature (sécurité)
if not verify_signature(payload, signature, WEBHOOK_SECRET):
raise HTTPException(status_code=401, detail="Signature invalide")
# 2. Parser le payload
event = await request.json()
event_type = event.get("type")
# 3. Traiter l'événement
if event_type == "payment_intent.succeeded":
payment = event["data"]["object"]
# Mettre à jour la commande, envoyer l'email...
print(f"Paiement reçu : {payment['amount']} {payment['currency']}")
# 4. Répondre 200 rapidement
return {"status": "received"}Sécurité des webhooks
Un endpoint webhook est une URL publique qui accepte des requêtes POST. Sans sécurité, n’importe qui peut envoyer de fausses requêtes à votre endpoint. Les bonnes pratiques de sécurité :
Vérifiez les signatures HMAC. La plupart des fournisseurs sérieux (Stripe, GitHub, Shopify) incluent une signature HMAC dans les headers de la requête. Cette signature est calculée à partir du payload et d’un secret partagé. Vérifiez-la systématiquement avant de traiter le webhook. C’est la protection la plus importante.
Utilisez uniquement HTTPS. Ne recevez jamais de webhooks sur HTTP en clair. Le payload peut contenir des données sensibles (montants, IDs clients, tokens). HTTPS chiffre le transport et empêche les attaques man-in-the-middle.
Validez le payload. Vérifiez que le payload contient les champs attendus avec les types corrects. Ne faites jamais confiance aveuglément aux données reçues.
Rendez le traitement idempotent. Les webhooks ont une garantie « at-least-once » : le même webhook peut être reçu plusieurs fois (retries). Votre traitement doit produire le même résultat qu’il soit exécuté une fois ou dix fois. Utilisez l’ID de l’événement comme clé de déduplication.
Limitez les IP sources (optionnel). Certains fournisseurs publient les plages IP de leurs serveurs webhook. Filtrer les requêtes par IP source ajoute une couche de sécurité supplémentaire, mais n’est pas toujours pratique (les IP changent).
Cas d’usage courants
Paiements et e-commerce
Stripe, PayPal, Shopify envoient des webhooks pour chaque événement de paiement : succès, échec, remboursement, litige. Votre application met à jour le statut de la commande, envoie les confirmations et déclenche la livraison en temps réel, sans que l’utilisateur ait à rafraîchir la page.
CI/CD et DevOps
GitHub envoie un webhook à chaque push, pull request ou merge. Ce webhook déclenche automatiquement votre pipeline CI/CD (GitHub Actions, Jenkins, GitLab CI) : build, tests, déploiement. C’est le mécanisme fondamental de l’intégration continue. Pas besoin de polling pour savoir si du code a été poussé.
IA et MLOps
Dans le contexte MLOps, les webhooks sont utilisés pour : notifier quand un entraînement de modèle est terminé (depuis une plateforme cloud), déclencher un pipeline de ré-entraînement quand de nouvelles données arrivent, alerter quand un drift est détecté en production, ou intégrer des résultats d’inférence dans des workflows d’automatisation (Zapier, Make).
Messaging et chatbots
Slack, Discord, Telegram envoient des webhooks pour les messages entrants. Votre application reçoit le message, exécute la logique du chatbot (appel LLM, recherche en base), et répond. Le webhook est le point d’entrée de la plupart des chatbots.
CMS headless et sites statiques
Quand du contenu est publié dans un CMS headless (Prismic, Contentful, Strapi), un webhook déclenche le rebuild de votre site statique sur Vercel ou Netlify. Le contenu est mis à jour en production sans intervention manuelle.
Automatisation no-code
Les plateformes d’automatisation comme Zapier et Make utilisent massivement les webhooks. Un webhook sert de trigger pour un « Zap » ou un « Scenario » : quand l’événement se produit (nouveau paiement, nouveau formulaire rempli), le workflow d’automatisation se déclenche automatiquement.
Standards et spécifications
Historiquement, chaque fournisseur implémentait ses webhooks avec son propre format de payload et ses propres mécanismes de sécurité. Des standards émergent pour uniformiser les pratiques :
CloudEvents (spécification CNCF) : définit un format d’enveloppe standard pour les données d’événements, avec des attributs communs (source, type, id, time, data). L’objectif est de rendre les événements portables entre systèmes.
OpenAPI Webhooks (depuis OpenAPI 3.1) : permet de documenter les payloads webhook avec la même rigueur que les endpoints request-response, incluant la validation de schéma, les définitions de sécurité et les exemples de payloads.
AsyncAPI : spécification dédiée aux architectures event-driven, couvrant les patterns de communication asynchrone (AMQP, MQTT, Kafka, WebSocket, HTTP webhooks).
Fiabilité et gestion des erreurs
Les webhooks fonctionnent sur un réseau non fiable par nature. Les requêtes peuvent échouer pour de multiples raisons : serveur indisponible, timeout réseau, erreur applicative. Une implémentation robuste doit gérer ces cas.
Idempotence
C’est le concept le plus important pour la fiabilité des webhooks. Un traitement idempotent produit le même résultat qu’il soit exécuté une ou plusieurs fois. Concrètement : si vous recevez deux fois le webhook payment_intent.succeeded avec le même ID, votre système ne doit créditer le paiement qu’une seule fois.
L’implémentation classique : stockez l’ID de chaque événement traité (dans Redis, en base de données, ou dans un cache). Avant de traiter un webhook, vérifiez si cet ID a déjà été vu. Si oui, ignorez-le silencieusement et retournez 200 OK.
import redis
r = redis.Redis()
async def handle_webhook(event: dict):
event_id = event["id"]
# Vérifier si déjà traité (idempotence)
if r.get(f"webhook:{event_id}"):
return {"status": "already_processed"}
# Marquer comme traité (avec expiration 72h)
r.setex(f"webhook:{event_id}", 259200, "processed")
# Traiter l'événement...
process_event(event)
return {"status": "processed"}File d’attente pour le traitement asynchrone
La bonne pratique pour les webhooks à haut volume : votre endpoint reçoit le webhook, le valide (signature + format), l’enregistre dans une file d’attente (Redis Queue, Celery, AWS SQS, RabbitMQ), et retourne 200 immédiatement. Un worker en arrière-plan consomme la file et traite les événements. Cela découple la réception (rapide) du traitement (potentiellement lent) et assure que vous ne perdez aucun événement même si le traitement est temporairement lent.
Monitoring
Surveillez trois métriques clés pour vos webhooks : le taux de succès (% de webhooks traités avec succès), la latence de traitement (temps entre la réception et la réponse 200), et le taux de duplicatas (indicateur de retries excessifs). Alertez quand le taux de succès chute ou quand les duplicatas augmentent.
La plupart des fournisseurs proposent un dashboard webhook qui montre l’historique des envois, les échecs et les retries. Stripe Dashboard, GitHub Webhook Deliveries et Shopify Webhooks sont des exemples. Consultez-les en premier lieu quand vous debuggez un problème d’intégration.
Développer et tester des webhooks en local
Le défi du développement webhook : votre serveur local (localhost:8000) n’est pas accessible depuis Internet. Deux solutions :
ngrok : crée un tunnel sécurisé qui expose votre serveur local via une URL publique temporaire. Vous configurez cette URL comme endpoint webhook et recevez les requêtes sur votre machine de développement.
# Exposer votre serveur local sur un URL public
ngrok http 8000
# Vous obtenez une URL comme https://abc123.ngrok.io
# Configurez cette URL comme endpoint webhookWebhook.site et outils similaires : des services en ligne qui reçoivent et affichent les webhooks entrants, utiles pour inspecter les payloads avant d’implémenter le traitement.
Replay et simulation : les plateformes comme Stripe Dashboard et GitHub Settings permettent de re-envoyer des webhooks passés pour le debugging, et de simuler des événements de test.
Erreurs courantes
Pas de vérification de signature. Accepter n’importe quel POST sur votre endpoint sans vérifier la signature HMAC expose votre système à des requêtes frauduleuses. C’est l’erreur de sécurité la plus grave et la plus répandue. Toujours vérifier la signature avant tout traitement.
Traitement synchrone trop long. Si votre handler met 30 secondes à traiter (appels API, envois d’email, calculs lourds), le fournisseur considère le webhook comme échoué et le renvoie. Répondez 200 immédiatement, traitez en arrière-plan.
Pas d’idempotence. Le même webhook peut arriver 2 ou 3 fois (retries). Si votre traitement n’est pas idempotent, vous risquez de traiter un paiement en double, d’envoyer un email en double, ou de créer un doublon en base.
Pas de logging. Quand un webhook échoue silencieusement, le debugging est impossible sans logs. Loguez chaque webhook reçu (ID, type, timestamp, résultat du traitement).
Endpoint non HTTPS. HTTP en clair pour recevoir des données sensibles est une faille de sécurité. Tous les fournisseurs sérieux exigent HTTPS.
Questions fréquentes sur les webhooks
Quelle est la différence entre un webhook et une API ?
Avec une API, c’est votre application qui initie la requête pour demander des données (modèle pull). Avec un webhook, c’est le serveur source qui envoie les données à votre application quand un événement se produit (modèle push). Les deux se complètent : vous utilisez une API pour lire/écrire des données, et des webhooks pour être notifié en temps réel des changements. Un webhook utilise le protocole HTTP, tout comme une API, mais l’initiateur de la communication est inversé.
Quelle est la différence entre un webhook et le polling ?
Le polling consiste à appeler régulièrement une API pour vérifier s’il y a du nouveau (par exemple toutes les 30 secondes). Le webhook vous notifie instantanément quand l’événement se produit. Le polling est simple à implémenter mais gaspille des ressources (la plupart des requêtes ne retournent rien de nouveau). Les webhooks sont plus efficaces mais nécessitent un serveur accessible publiquement.
Comment sécuriser un webhook ?
Trois mesures essentielles : (1) vérifiez la signature HMAC fournie par le fournisseur dans les headers de la requête, c’est la protection principale contre les requêtes frauduleuses ; (2) n’acceptez que les connexions HTTPS pour chiffrer les données en transit ; (3) rendez votre traitement idempotent pour gérer les retries (utilisez l’ID de l’événement comme clé de déduplication). Optionnellement, vous pouvez filtrer par IP source si le fournisseur publie ses plages.
Que se passe-t-il si mon serveur est indisponible quand un webhook arrive ?
La plupart des fournisseurs implémentent un mécanisme de retry avec backoff exponentiel : si votre serveur ne répond pas ou retourne une erreur, le webhook est re-envoyé après un délai croissant (1 min, 5 min, 30 min, 1h, etc.). Le nombre de retries varie selon le fournisseur (Stripe re-essaie pendant 72h). Si tous les retries échouent, l’événement est marqué comme échoué et peut être consulté dans le dashboard du fournisseur.
Les webhooks sont-ils utilisés en IA et ML ?
Oui, dans plusieurs contextes MLOps : notification de fin d’entraînement (une plateforme cloud envoie un webhook quand un job d’entraînement se termine), déclenchement de pipelines (un webhook sur un push Git déclenche un pipeline de ré-entraînement via CI/CD), intégration de résultats d’inférence dans des workflows no-code (Zapier, Make), et alertes de monitoring (un webhook notifie Slack quand un drift est détecté ou quand la performance du modèle chute sous un seuil).