Démarrer
Webhooks
Nodium vous appelle quand quelque chose se passe. Signé, repris, journalisé.
Ce que vous recevez
{ "id": "evt_5f1c0a9e2b7d4c3a8e6f1b2c3d4e5f60", "event": "message.received", "workspace_id": "…", "occurred_at": "2026-09-18T09:12:44.120Z", "data": { "message_id": "…", "conversation_id": "…", "contact_id": "…", "channel_type": "whatsapp", "type": "text", "text": "Hello, is my order ready?" }}idest l'identifiant de l'événement : il reste le même quand une livraison est reprise ou relivrée. Dédoublonnez dessus.- En-têtes :
X-Nodium-Event(le nom de l'événement),X-Nodium-Delivery(cette livraison),X-Nodium-Signature. - Répondez un
2xxen moins de 10 secondes. Faites le travail ensuite.
Les événements
Vérifier la signature
X-Nodium-Signature: t=<secondes>,v1=<hex>. La signature vaut HMAC-SHA256(secret, "<t>.<corps brut>"). Pendant un changement de secret, l'en-tête porte deux v1= — acceptez l'appel si l'une correspond. Refusez un appel de plus de 5 minutes.
import crypto from 'node:crypto'// rawBody: the request body exactly as received, before any JSON parsing.export function verifyNodium(rawBody, header, secret) { const parts = header.split(',') const t = parts.find(p => p.startsWith('t='))?.slice(2) const signatures = parts.filter(p => p.startsWith('v1=')).map(p => p.slice(3)) if (!t || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex') return signatures.some(sig => sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))}import hmac, hashlib, timedef verify_nodium(raw_body: bytes, header: str, secret: str) -> bool: parts = header.split(",") t = next((p[2:] for p in parts if p.startswith("t=")), None) signatures = [p[3:] for p in parts if p.startswith("v1=")] if not t or abs(time.time() - int(t)) > 300: return False expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest() return any(hmac.compare_digest(sig, expected) for sig in signatures)Reprises, journal, relivraison
- Un appel qui échoue ou ne répond pas
2xxest repris après 1 min, 5 min, 30 min, 2 h et 12 h — six essais en tout — puis marquéfailed. GET /webhooks/deliveriesliste chaque livraison avec ce que votre serveur a répondu et l'erreur. C'est ce qui tranche « on n'a rien reçu ».POST /webhooks/deliveries/{id}/redeliverla renvoie, même charge, mêmeid.POST /webhooks/{id}/rotate-secretdonne un nouveau secret ; l'ancien signe encore 24 h, le temps de déployer sans perdre d'appel.POST /webhooks/{id}/testenvoie tout de suite un appel d'essai signé et dit ce qui est revenu.