Enregistrer un webhook
Vous pouvez enregistrer jusqu'à 10 URLs webhook par boutique. Chacune peut s'abonner à une liste différente d'événements ; choisissez un modèle qui vous convient :
- Un seul endpoint, tous les events — le plus simple pour des petites apps. Branchez sur
eventdans le handler. - Plusieurs endpoints, un event chacun — plus propre en microservices, mais plus d'URLs à gérer.
POST /v1/webhooks — enregistrer
Auth : clé plateforme avec webhooks:write. Nécessite Idempotency-Key.
Corps
| Champ | Type | Requis | Notes |
|---|---|---|---|
url | string (URL https) | ✅ | Doit être http:// ou https://. En prod : toujours https://. Longueur max 500. |
events | string[] | ✅ | Liste de noms d'events. Voir Catalogue d'events. Vide = erreur. |
Requête
curl -X POST 'https://api.dzbuild.app/v1/webhooks' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"url": "https://yourapp.example/webhooks/dzbuild",
"events": ["order.created", "order.confirmed", "order.shipped",
"order.cancelled", "signup.counted"]
}'
Réponse 201
{
"data": {
"id": 17,
"secret": "fc9b5f0b51b4a93c1d6f8e29b6a2e30c7c2c44a4f2a6c8d8e0e1b9d4f6c1a8b3",
"note": "Save the secret now — it is not retrievable after this response."
}
}
Le secret est affiché UNE FOIS. Stockez-le à côté de l'id du webhook dans votre coffre. C'est la valeur que vous utiliserez pour vérifier chaque POST entrant. Si vous le perdez, supprimez le webhook et créez-en un nouveau.
Erreurs
| Code | Cause |
|---|---|
bad_request "url must be a valid http(s) URL" | URL mal formée |
bad_request "events must be a non-empty list" | Tableau vide |
bad_request "unknown event: foo. Allowed: …" | Nom d'event hors catalogue |
GET /v1/webhooks — liste
Auth : clé plateforme avec webhooks:read.
curl https://api.dzbuild.app/v1/webhooks \
-H "Authorization: Bearer $DZ_KEY"
{
"data": {
"items": [
{
"id": 17,
"url": "https://yourapp.example/webhooks/dzbuild",
"events": ["order.created", "order.confirmed"],
"status": "active",
"last_success_at": "2026-04-30 21:18:23",
"last_failure_at": null,
"failure_count": 0,
"created_at": "2026-04-30 19:00:00"
}
],
"allowed_events": [
"order.created", "order.confirmed", "order.shipped", "order.delivered",
"order.cancelled", "order.returned", "payment.received",
"signup.counted", "event.recorded", "product.stock_low"
]
}
}
allowed_events est la liste canonique — utilisez-la pour peupler des dashboards dans vos outils admin.
| Statut | Signification |
|---|---|
active | Reçoit les livraisons |
paused | Ne reçoit pas (pause possible via dashboard) |
dead | Auto-désactivé après 5 DLQ d'affilée. Contactez le support pour réveiller. |
POST /v1/webhooks/{id}/test
Déclenche une livraison webhook.test pour vérifier que votre endpoint reçoit + vérifie correctement les signatures.
Auth : clé plateforme avec webhooks:write. Nécessite Idempotency-Key.
curl -X POST 'https://api.dzbuild.app/v1/webhooks/17/test' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: test-17-$(date +%s)"
{ "data": { "tested": true, "note": "a webhook.test delivery was enqueued; check your endpoint" } }
La livraison de test ressemble à :
{
"event": "webhook.test",
"store_id": 13,
"occurred_at": "2026-04-30T21:24:17+00:00",
"data": { "ts": 1717112657 },
"delivery_id": "..."
}
Elle porte une vraie signature — votre code de vérification peut être testé end-to-end.
DELETE /v1/webhooks/{id}
Auth : clé plateforme avec webhooks:write. Nécessite Idempotency-Key.
curl -X DELETE 'https://api.dzbuild.app/v1/webhooks/17' \
-H "Authorization: Bearer $DZ_KEY" \
-H "Idempotency-Key: del-17"
{ "data": { "deleted": true, "id": 17 } }
Après suppression :
- Plus aucune livraison nouvelle n'est mise en file.
- Les livraisons in-flight (déjà en file) sont tentées une fois.
- Le secret du webhook est désormais inutile — personne ne peut signer avec.
Exigences de l'endpoint
Votre URL webhook doit :
- Répondre en 2xx au succès — tout autre est traité comme erreur (4xx ack, 5xx retry).
- Répondre dans les 10 secondes. Plus lent → timeout → retry.
- Accepter
POSTavecContent-Type: application/json. - Lire le body raw pour vérifier la signature (ne pas re-sérialiser).
- Être idempotent — le même
delivery_idPEUT arriver plusieurs fois.
Piège classique dans certains frameworks : un middleware re-encode le JSON avant que votre handler le voie, et sha256(body) ne match plus. Solutions :
- Express :
express.raw({ type: 'application/json' })pour la route webhook, puisJSON.parse(req.body)dans le handler. - Django :
request.bodyest les bytes raw — c'est ce qu'on veut. - Laravel :
$request->getContent()retourne le body raw. - PHP raw :
file_get_contents('php://input').
Voir Vérifier les signatures pour le code en 4 langages.