Aller au contenu principal
Technique WhatsApp API• 9 min de lecture

Webhooks WhatsApp : fonctionnement, événements et sécurité (signature HMAC)

Comment fonctionnent les webhooks WhatsApp : événements de messages et de statuts, signature HMAC-SHA256, idempotence, ordre des statuts et bonnes pratiques.

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 :

  1. Vous déclarez une URL de réception (par exemple https://votre-domaine.com/webhooks/whatsapp), accessible publiquement en HTTPS.
  2. Un événement se produit (un client écrit, Meta confirme la livraison d'un message).
  3. La plateforme envoie une requête POST avec un corps JSON décrivant l'événement et un en-tête de signature.
  4. Votre serveur vérifie la signature, enregistre l'événement et répond 200 rapidement.
  5. 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 :

  1. Récupérer le corps brut de la requête, octet pour octet, avant toute transformation JSON.
  2. Calculer HMAC-SHA256(secret, corps_brut).
  3. Comparer le résultat à la signature reçue dans l'en-tête, avec une comparaison à temps constant.
  4. 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.failed avec 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 delivered et read par 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.

#webhook whatsapp#webhooks whatsapp api#hmac sha256#statut message whatsapp#api whatsapp
Arthur Lyonnet
Arthur LyonnetCo-fondateur & CEO

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 gratuit