Événements et statut
Mises à jour de statut en temps réel
Messages entrants, statuts de livraison, événements de modèles et de numéros — transmis à votre propre backend, signés et réessayés.
Ce que vous recevez#
- Messages entrants — chaque réponse reçue par vos numéros. Transmise à votre endpoint dès son arrivée ; la plateforme ne conserve pas d'inbox, c'est donc ainsi que vous lisez les réponses.
- Statuts des messages — sent, delivered, read, failed (avec le motif de l'échec).
- Approbations de modèles — approuvé, rejeté (avec motif), désactivé.
- Qualité du numéro — changements de notation de qualité et signalements.
- Déconnexions — lorsque l'intégration d'un numéro est retirée côté Meta.
Comment cela circule#
Meta envoie tous les événements webhook à Genuka. Le dispatcher de Genuka les transmet, sans modification, à la plateforme, qui achemine chaque événement vers le bon compte et le bon numéro, met à jour ce qu'elle reflète (statuts, états des templates, qualité) et met une copie en file pour vos endpoints. Vous n'avez rien à configurer côté Meta — cela fonctionne dès qu'un numéro est connecté.
Idempotent par conception
Les événements sont dédupliqués, de sorte qu'un statut que Meta livre plusieurs fois n'est appliqué qu'une seule fois. Les mises à jour apparaissent généralement en quelques secondes.Transmission vers votre propre backend#
Enregistrez un endpoint dans Webhooksdepuis le tableau de bord pour recevoir une copie signée de ces événements. Un endpoint peut couvrir tous les numéros du compte (général), une seule entreprise connectée, ou un seul numéro — et une entreprise peut être exclue d'un endpoint général.
Le payload#
Chaque livraison est un POST portant un seul événement. data est la valeur Meta brute, intacte ; les champs autour indiquent à quelle entreprise et à quel numéro elle se rapporte.
{
"id": "dlv_2f8c1a...",
"type": "message_status",
"field": "messages",
"created_at": "2026-08-04T09:31:07.412Z",
"partner_id": "cl9x...",
"company_id": "cm31...",
"connection_id": "cn77...",
"waba_id": "102290129340398",
"phone_number_id": "106540352242922",
"data": {
"id": "wamid.HBgLMjM3...",
"status": "delivered",
"timestamp": "1785836801",
"recipient_id": "237699000000"
}
}En-têtes#
X-Genuka-Signature— HMAC du corps — voir ci-dessous.X-Genuka-Event— Type d'événement, ex. message_status.X-Genuka-Event-Field— Le champ webhook Meta sous-jacent.X-Genuka-Delivery— Id de livraison, identique entre les tentatives — utilisez-le pour dédupliquer.X-Genuka-Webhook-Id— L'endpoint visé.X-Genuka-Attempt— Numéro de tentative, à partir de 1.
Vérifier la signature#
Chaque endpoint a sa propre clé (whsec_…), visible sur sa carte dans le tableau de bord. L'en-tête ressemble à t=1785836801,v1=5f3c…, où v1 est le HMAC-SHA256 hexadécimal de `${t}.${rawBody}` calculé avec cette clé.
Calculez-le sur le corps brut de la requête, avant tout parsing JSON — une re-sérialisation change les octets et casse la comparaison. Comparez en temps constant.
import crypto from "node:crypto";
const TOLERANCE_SECONDS = 300;
export function verify(rawBody: string, header: string, secret: string): boolean {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const timestamp = Number(parts.t);
// Reject anything outside the window: this is what makes a captured
// request useless to replay later.
if (Math.abs(Date.now() / 1000 - timestamp) > TOLERANCE_SECONDS) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(parts.v1, "utf8"),
Buffer.from(expected, "utf8"),
);
}Régénérez la clé au moindre doute
La régénération prend effet immédiatement : l'ancienne clé cesse de vérifier dès que vous régénérez, mettez donc votre récepteur à jour dans la foulée.Reprises et échecs#
Une livraison est réussie sur tout 2xx. Tout le reste — y compris un dépassement des 10 secondes — est réessayé 5 fois avec un délai croissant (1 min, 5 min, 30 min, 2 h, 6 h), puis marqué en échec. Chaque tentative est visible dans le journal de livraison du tableau de bord, et une livraison en échec peut être renvoyée à la main une fois votre endpoint rétabli.
Répondez vite, traitez ensuite
Accusez réception avec un 200 dès que l'événement est stocké, et faites le traitement de façon asynchrone. Garder la connexion ouverte rend les reprises plus probables, pas moins.