Webhooks
Les webhooks sont des notifications push temps réel de DZBuild vers votre serveur quand quelque chose se passe sur votre boutique. Utilisez-les au lieu du polling — moins de charge, latence plus basse, et les livraisons webhook ne comptent pas dans votre quota mensuel de requêtes.
Choisissez le bon avant de construire.
| Addon Webhooks marchand | Webhooks API v1 (cette section) | |
|---|---|---|
| Configuration | /dashboard/webhooks — sans code | POST /v1/webhooks — via l'API uniquement |
| Qui peut l'utiliser | Plan Unlimited et au-delà | Toute boutique avec une clé API inscrite au pilote |
| Endpoints par boutique | 1 en Unlimited, 3 en Enterprise | Aucune limite n'est appliquée |
| Signature | X-DZ-Signature: t=<ts>,v1=hex(hmac_sha256(secret, ts + "." + rawBody)) sur le body brut — vous pouvez la vérifier. Envoie aussi un en-tête X-DZ-Token: <secret> pour les outils no-code qui ne savent faire que de l'auth par en-tête. | Signée avec une clé qui ne vous est pas remise — les marchands ne peuvent pas la vérifier aujourd'hui. Voir Signature. |
| Commandes couvertes | order.created depuis toutes les sources (boutique, landing page, création manuelle au dashboard, API) plus 6 événements de statut, dont order.processing | Uniquement les commandes créées ou mises à jour via l'API |
| Livré depuis | Les plages IP Cloudflare | Les adresses de sortie propres à DZBuild — demandez la liste actuelle au support |
| Extras | Interface de journal des livraisons, régénération du secret, validation HTTPS de la cible, désactivation automatique après 10 échecs consécutifs | — |
Si tout ce dont vous avez besoin, ce sont des notifications de commande fiables, l'addon est le meilleur produit. Utilisez les webhooks API v1 quand votre intégration parle déjà à l'API REST.
Pourquoi des webhooks
Comparez :
Polling — votre code appelle GET /v1/orders?since=... chaque minute. 1440 appels/jour, 1440 round-trips, votre quota brûle uniformément, et la latence « commande créée → votre code le sait » est de 60 s.
Webhooks — vous enregistrez https://yourapp/webhooks une fois. Chaque commande créée via POST /v1/orders met une livraison en file, et la file se vide en continu : la latence est donc généralement inférieure à une minute. Zéro polling, zéro gâchis de quota.
order.created se déclenche uniquement pour les commandes créées via POST /v1/orders. Les commandes passées sur la boutique, sur une landing page ou créées manuellement au dashboard ne déclenchent rien ici. Idem pour les changements de statut — voir le Catalogue d'événements.
Le polling n'est meilleur que quand :
- Votre endpoint n'est pas joignable depuis Internet (pollez depuis votre réseau interne).
- Vous n'avez pas de serveur (pollez depuis une lambda planifiée / cron).
Comment fonctionne la livraison
Une écriture API v1 a lieu
│
▼
Une livraison est mise en file pour chaque webhook abonné à cet événement
│
▼
La file se vide en continu — généralement en moins d'une minute
│
▼
Body signé ─────► POST votre URL (5 s connexion, 10 s au total)
│
├─ 2xx → marque livré, fini
├─ 5xx → remis en file, re-tenté chaque minute
├─ 4xx ou 3xx → une tentative, pas de retry
└─ pas de réponse (timeout / DNS / TLS) → une tentative, pas de retry
Comportement des retries
Lisez ceci avant de concevoir quoi que ce soit autour des retries.
- HTTP 5xx — la livraison est re-POSTée une fois par minute, indéfiniment, jusqu'à ce que votre endpoint réponde 2xx ou que vous supprimiez le webhook. L'intervalle n'augmente jamais et la livraison n'est jamais abandonnée : ne concevez rien autour d'une échelle de backoff — il n'y en a pas.
- Timeout, échec DNS, échec TLS — tentés exactement une fois, puis abandonnés. Pas de retry, et la livraison n'est plus jamais reprise.
- HTTP 4xx et 3xx — une tentative, jamais de retry. Les redirections ne sont pas suivies : un
301/302compte comme un échec.
Il n'y a pas de désactivation automatique. Le failure_count du webhook s'incrémente une fois par tentative échouée et retombe à 0 au premier succès ; status reste active.
Conséquences pratiques :
- Répondez 2xx vite. Si vous ne pouvez pas traiter une payload, répondez quand même 2xx et jetez-la — répondre 5xx vous abonne à un POST toutes les 60 secondes, pour toujours.
- Ne comptez pas sur un retry pour couvrir un endpoint lent. Un timeout est une livraison définitivement perdue. Persistez le body dans votre propre file et acquittez immédiatement.
- Réconciliez par polling. Comme les échecs sont abandonnés en silence, lancez un balayage périodique
GET /v1/orders?since=...comme filet de sécurité.
Ce qui compte comme un « succès »
- HTTP 200, 201, 202, 204 (n'importe quel 2xx) — succès.
- HTTP 4xx (400, 401, 403, 404, 422 …) — pas de retry. Corrigez votre endpoint et re-testez via
POST /v1/webhooks/{id}/test. - HTTP 3xx — pas de retry. Nous ne suivons pas les redirections ; pointez le webhook sur l'URL finale.
- Timeout, échec DNS, échec TLS — pas de retry non plus. Les certificats TLS sont vérifiés strictement : un certificat auto-signé échoue ici.
- HTTP 5xx — re-tenté, mais voir l'avertissement sur la boucle ci-dessus.
Modèle de sécurité
Ce qu'on envoie
Content-Type: application/json
User-Agent: dzbuild-webhook/1
X-DZ-Timestamp: <unix seconds>
X-DZ-Signature: <hex hmac-sha256>
X-DZ-Delivery-Id: <numeric delivery id>
Signature
X-DZ-Signature n'est pas dérivée du secret propre au webhook renvoyé par POST /v1/webhooks, et ce secret ne sert jamais à signer — tout code de vérification écrit contre lui rejette donc 100 % des livraisons authentiques.
Traitez X-DZ-Signature comme une valeur opaque en attendant la signature par webhook. S'il vous faut une signature réellement vérifiable, utilisez l'addon Webhooks marchand sur /dashboard/webhooks, qui signe chaque endpoint avec le secret propre à cet endpoint.
Ce que vous devez faire
- Relisez avant d'agir. Puisque la signature n'est pas vérifiable, traitez la payload comme une notification et non comme une donnée authentifiée — récupérez l'enregistrement avec
GET /v1/orders/{id}en utilisant votre clé API avant d'expédier, de facturer ou d'exécuter quoi que ce soit. - Rendez l'URL indevinable. Un long segment de chemin aléatoire, ou un token partagé en query string, est votre authentification pratique aujourd'hui.
- Vérifiez que le timestamp est dans 5 min de l'horloge serveur — protection anti-rejeu à moindre coût.
- Utilisez les bytes raw du body si vous hachez quoi que ce soit — ne re-sérialisez pas le JSON.
- Soyez idempotent — le même événement logique PEUT être livré plusieurs fois (remises en file après un 5xx). Dédupliquez via
delivery_idou les ids de l'événement.
Ce qu'on ne fait pas
- Pas d'auth sortant en mTLS. Si votre endpoint le requiert, mettez un reverse proxy qui strip/ajoute mTLS devant.
- On n'envoie pas les livraisons API v1 depuis les plages IP Cloudflare : n'autoriser que celles-ci bloque donc toutes les livraisons. S'il vous faut une allow-list IP, demandez au support les adresses de sortie actuelles — elles peuvent changer. (L'addon Webhooks marchand, lui, part bien des plages Cloudflare.)
Enveloppe de payload
Chaque body webhook a la même forme externe :
{
"event": "order.confirmed",
"store_id": 13,
"occurred_at": "2026-04-30T21:18:21+00:00",
"data": { "order_id": 6894, "old_status": "pending", "new_status": "confirmed" },
"delivery_id": "9f2c41ab77e05d18"
}
| Champ | Notes |
|---|---|
event | Type d'événement (liste complète dans Catalogue d'événements). |
store_id | Votre store id — utile si vous avez plusieurs webhooks sur le même handler. |
occurred_at | Quand l'événement a eu lieu chez nous, ISO 8601 + TZ. |
data | Payload propre à l'événement. Voir Catalogue pour la forme. |
delivery_id | Chaîne de 16 caractères hex, unique par livraison (un webhook × un événement). Elle est identique octet pour octet à chaque retry — c'est ce qui la rend utilisable pour la déduplication. |
L'en-tête X-DZ-Delivery-Id est une valeur différente : un id numérique de livraison, par exemple 4127. Il est lui aussi stable d'un retry à l'autre, mais il n'est pas égal au delivery_id du body. Dédupliquez sur l'un ou l'autre de façon cohérente — ne mélangez pas.
Quota
Les livraisons webhook ne sont aujourd'hui ni comptabilisées ni plafonnées. Une valeur webhooks_per_month est remontée par GET /v1/usage et GET /v1/quotas, mais rien ne l'incrémente et rien ne l'applique. Les tentatives de livraison ne consomment pas non plus votre quota API requests_per_month.
Ce n'est pas un permis d'être lent — un endpoint qui répond 5xx est re-POSTé toutes les 60 secondes indéfiniment (voir Comportement des retries).
La suite
- Enregistrement —
POST /v1/webhooksavec body, réponse, exemples. - Catalogue d'événements — chaque event avec sample data.
- Vérifier les signatures — code en 4 langages.