Delivery & retries

At-least-once delivery, deduplication, the retry ladder, and the dead-letter queue.

At-least-once, so dedupe

Delivery is at-least-once. A delivery that stalls mid-flight is reclaimed and re-sent, so you may occasionally receive the same event twice — dedupe on Drazill-Webhook-Id (idempotent by construction). Record the delivery id the first time you durably accept an event, and ignore a repeat.

Retries and the dead-letter queue

Respond 2xx once you have durably accepted the event. Any non-2xx response or a timeout is a failed attempt. Failed attempts back off on this schedule (seconds), then move to the dead-letter queue:

0 → 30 → 120 → 600 → 3600 → 21600 → 86400 → DEAD_LETTER

That is seven attempts over roughly a day. A payload that fails its own schema is never sent — it fails closed into this same retry/DLQ path rather than delivering unvalidated data.

Inspect and replay

Inspect deliveries and replay one from the API:

$curl -sS https://api.drazill.com/api/v1/webhooks/$ID/deliveries -H "X-API-Key: $KEY"
$curl -sS -X POST https://api.drazill.com/api/v1/webhooks/deliveries/$DELIVERY_ID/replay -H "X-API-Key: $KEY"

Test your integration

  • POST /webhooks/{id}/test — sends a real, signed webhook.test delivery to one endpoint.
  • POST /webhooks/sandbox/events — enqueues any event type with a sample or your own data (validated), for exercising your handler without live activity.

Both go through the exact signing + delivery path production uses, so verifying one proves your verification code. Test and live deliveries are segregated by livemode, so a sandbox event never reaches a live endpoint.

Return 2xx fast and do the real work asynchronously. If you can’t finish within the delivery timeout, accept the event (dedupe on Drazill-Webhook-Id) and process it out of band, rather than holding the connection open.