Un webhook WhatsApp est une requête HTTP POST que la plateforme WhatsApp (Meta ou votre fournisseur) envoie automatiquement à une adresse de votre serveur à chaque événement : message reçu, message envoyé, délivré, lu ou échoué. Il évite d'interroger l'API en boucle pour connaître le statut des messages. Pour être fiable, un récepteur de webhook doit vérifier la signature HMAC-SHA256 de chaque requête, répondre vite avec un code 2xx, traiter les événements en double sans effet secondaire, et tolérer qu'ils arrivent dans le désordre.
Ce guide explique le fonctionnement, les événements courants, la vérification de signature et les erreurs à éviter.
Webhook ou appel API : quelle différence ?
Une API fonctionne à l'initiative de votre application : vous envoyez une requête, vous recevez une réponse. Un webhook fonctionne dans l'autre sens : c'est la plateforme qui vous appelle quand quelque chose se produit.
Sur WhatsApp, les deux sont complémentaires :
- l'API sert à agir : envoyer un message, créer un contact, soumettre un template ;
- le webhook sert à être informé : un client a répondu, votre message a été lu, un envoi a échoué.
Sans webhook, vous ne sauriez pas qu'un client vous a écrit, à moins d'ouvrir l'inbox.
Comment fonctionne un webhook WhatsApp
Le cycle est toujours le même :
- Vous déclarez une URL de réception (par exemple
https://votre-domaine.com/webhooks/whatsapp), accessible publiquement en HTTPS. - Un événement se produit (un client écrit, Meta confirme la livraison d'un message).
- La plateforme envoie une requête POST avec un corps JSON décrivant l'événement et un en-tête de signature.
- Votre serveur vérifie la signature, enregistre l'événement et répond 200 rapidement.
- Si votre serveur ne répond pas ou renvoie une erreur, la plateforme peut retenter l'envoi selon sa politique.
Chez Meta (Cloud API)
Si vous utilisez la Cloud API en direct, Meta impose une étape préalable : la vérification de l'URL. Meta envoie une requête GET avec les paramètres hub.mode, hub.verify_token et hub.challenge. Votre serveur doit vérifier que le jeton correspond à celui que vous avez configuré et renvoyer la valeur de hub.challenge. Ensuite, chaque notification POST porte l'en-tête X-Hub-Signature-256, une signature HMAC-SHA256 du corps calculée avec le secret de votre application Meta.
Le corps d'une notification de statut Meta ressemble, de façon simplifiée, à ceci :
{
"object": "whatsapp_business_account",
"entry": [{
"changes": [{
"field": "messages",
"value": {
"statuses": [{
"id": "wamid.HBg...",
"status": "delivered",
"timestamp": "1760000000",
"recipient_id": "2250700000000"
}]
}
}]
}]
}
Chez un fournisseur
Un fournisseur reçoit les webhooks de Meta, les traite, puis vous renvoie ses propres événements, souvent dans un format simplifié et nommé. Vous n'avez alors pas à gérer la vérification d'URL de Meta, mais vous devez toujours vérifier la signature du fournisseur.
Les événements WhatsApp à connaître
| Événement | Signification | Usage typique |
|---|---|---|
| Message reçu | Un contact vous a écrit (texte, média, clic sur un bouton) | Créer ou mettre à jour le contact dans le CRM, alerter un commercial |
| Envoyé | Meta a accepté le message | Journaliser l'envoi |
| Délivré | Le message est arrivé sur le téléphone du destinataire | Mesurer le taux de livraison |
| Lu | Le destinataire a ouvert le message (si les accusés de lecture sont activés chez lui) | Déclencher une relance ciblée |
| Échoué | Le message n'a pas pu être délivré, avec un code d'erreur | Corriger le numéro, basculer sur un autre canal |
| Alerte sur le numéro | Changement de qualité, restriction, limite atteinte | Suspendre les envois, prévenir l'équipe |
| Formulaire rempli | Un contact a soumis un formulaire WhatsApp | Créer un rendez-vous, un ticket, un lead |
Deux remarques importantes :
- « Lu » n'est pas toujours disponible : un utilisateur qui a désactivé les accusés de lecture n'en enverra pas. Un taux de lecture est donc un minimum.
- « Échoué » est l'événement le plus utile et le plus négligé. Il contient la cause (numéro sans WhatsApp, limite marketing par utilisateur atteinte, template en pause, etc.) et permet d'agir.
Les webhooks de Whakup
Whakup envoie des webhooks sortants signés pour les événements suivants :
message.received: message entrant d'un contact ;message.sent,message.delivered,message.read,message.failed: cycle de vie des messages envoyés ;channel.alert: alerte sur le canal WhatsApp (qualité, restriction) ;form.submitted: réponse à un formulaire WhatsApp.
Chaque requête est signée en HMAC-SHA256 avec un secret partagé. Les webhooks font partie de l'offre Business (450 € HT par mois), avec l'API et le MCP. Ils sont compatibles avec n8n, Make ou Zapier via leurs blocs « webhook » génériques ; il n'existe pas de connecteur officiel.
À noter : la documentation publique ne détaille pas encore la politique de nouvelle tentative. Pour une intégration critique (facturation, stocks), prévoyez une réconciliation périodique de votre côté.
Vérifier la signature HMAC-SHA256
La signature prouve deux choses : la requête vient bien de la plateforme (elle seule connaît le secret) et le corps n'a pas été modifié en chemin.
Le principe :
- Récupérer le corps brut de la requête, octet pour octet, avant toute transformation JSON.
- Calculer
HMAC-SHA256(secret, corps_brut). - Comparer le résultat à la signature reçue dans l'en-tête, avec une comparaison à temps constant.
- Rejeter la requête (401) si elles diffèrent.
Exemple en Node.js avec Express (adaptez le nom de l'en-tête, le préfixe éventuel comme sha256= chez Meta et l'encodage, hexadécimal ou base64, à la documentation de votre fournisseur) :
import crypto from "node:crypto";
import express from "express";
const app = express();
const SECRET = process.env.WEBHOOK_SECRET;
const SIGNATURE_HEADER = "x-signature"; // à remplacer par l'en-tête documenté
app.post(
"/webhooks/whatsapp",
express.raw({ type: "application/json" }), // corps brut obligatoire
(req, res) => {
const received = (req.get(SIGNATURE_HEADER) || "").replace(/^sha256=/, "");
const expected = crypto
.createHmac("sha256", SECRET)
.update(req.body)
.digest("hex");
const a = Buffer.from(received, "hex");
const b = Buffer.from(expected, "hex");
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
queue.push(event); // traitement asynchrone
res.sendStatus(200);
}
);
Les erreurs classiques :
- calculer la signature sur le JSON reparsé : le moindre espace ou ordre de clé différent change le résultat ;
- comparer avec
===: une comparaison classique peut fuiter des informations par le temps de réponse ; - stocker le secret dans le code : utilisez une variable d'environnement.
Bonnes pratiques de réception
Répondre vite, traiter ensuite
Répondez 200 dès que la signature est vérifiée et que l'événement est mis en file d'attente. Un traitement long (appel au CRM, envoi d'e-mail) dans la requête provoque des délais d'attente et des renvois.
Rendre le traitement idempotent
Un même événement peut arriver deux fois, par exemple après une nouvelle tentative. Utilisez l'identifiant du message et le type d'événement comme clé unique : si la paire a déjà été traitée, ignorez-la.
Tolérer le désordre
Les statuts n'arrivent pas toujours dans l'ordre logique : un « lu » peut précéder un « délivré ». Ne faites jamais régresser un statut : si un message est déjà « lu », un « délivré » reçu ensuite ne doit pas l'écraser. L'ordre de priorité habituel est : échoué ou lu, puis délivré, puis envoyé.
Surveiller les échecs de réception
Journalisez les requêtes rejetées (signature invalide) et les erreurs de traitement. Une série de signatures invalides peut indiquer un secret mal configuré après une rotation, ou une tentative d'abus.
Sécuriser l'URL
HTTPS obligatoire, URL non devinable, pas d'informations sensibles dans les journaux. La signature reste la protection principale : une URL secrète ne suffit pas.
Cas d'usage concrets
- Synchronisation CRM : sur
message.received, rattacher le message au contact et créer une tâche pour le commercial. - Repli SMS : sur
message.failedavec une cause « numéro sans WhatsApp », envoyer l'information par SMS ou e-mail. - Alerte d'exploitation : sur
channel.alert, prévenir l'équipe marketing sur sa messagerie interne et suspendre les envois depuis vos outils. - Prise de rendez-vous : sur
form.submitted, créer le rendez-vous dans votre agenda. - Tableau de bord : agréger
deliveredetreadpar campagne dans votre outil d'analyse.
Pour la mise en œuvre sans code serveur, voir notre guide Intégration WhatsApp : site web, CRM, boutique.
FAQ
À quoi sert un webhook WhatsApp ?
Il transmet en temps réel à votre serveur les événements de votre compte WhatsApp : messages reçus, statuts des messages envoyés (envoyé, délivré, lu, échoué), alertes. Il permet de synchroniser un CRM ou de déclencher des actions sans interroger l'API en boucle.
Comment sécuriser un webhook WhatsApp ?
En vérifiant la signature HMAC-SHA256 de chaque requête avec votre secret, sur le corps brut et avec une comparaison à temps constant, en utilisant HTTPS et en rejetant toute requête non signée ou mal signée.
Pourquoi je reçois deux fois le même événement ?
Les plateformes peuvent renvoyer un événement si votre serveur a répondu trop lentement ou avec une erreur. Rendez votre traitement idempotent en utilisant l'identifiant du message et le type d'événement comme clé unique.
Pourquoi le statut « lu » arrive-t-il avant « délivré » ?
Les notifications sont envoyées de façon asynchrone et peuvent arriver dans le désordre. Votre code doit conserver le statut le plus avancé et ignorer un statut antérieur reçu en retard.
Quels webhooks propose Whakup ?
message.received, message.sent, message.delivered, message.read, message.failed, channel.alert et form.submitted, signés en HMAC-SHA256. Ils sont inclus dans l'offre Business avec l'API et le MCP.
Brancher vos webhooks
Consultez la documentation développeur et la page API WhatsApp pour les détails d'intégration, ou créez votre compte Whakup pour découvrir la plateforme : essai gratuit de 15 jours, sans carte bancaire.

Co-fondateur de Whakup, Arthur accompagne les entreprises africaines dans leur transformation digitale via WhatsApp depuis 2022. Passionné par le growth marketing et l'entrepreneuriat en Afrique francophone.
Prêt à passer à l'action ?
Essayez Whakup gratuitement pendant 15 jours. Aucune carte bancaire requise.
Démarrer l'essai gratuitArticles similaires
Templates WhatsApp : soumission, approbation Meta et suivi du statut
Créer un template WhatsApp, le soumettre à Meta et suivre son statut (brouillon, en revue, approuvé, refusé) par interface ou API. Causes de refus et conseils.
Connecter WhatsApp Business à Claude ou Cursor avec le MCP
Guide pour connecter votre compte WhatsApp Business à Claude ou Cursor via le Model Context Protocol (MCP) : principe, configuration, sécurité et usages.
Vérification OTP par WhatsApp : templates d'authentification, coûts, mise en place
Envoyer un code OTP par WhatsApp : règles des templates d'authentification Meta, bouton copier le code, coût au message et deux architectures possibles.