Webhooks
When Deliverant delivers an event to your endpoint, it includes standard headers for identification and signature verification. This page covers what your server receives, how to verify signatures, and how the delivery lifecycle works.
Delivery headers
Every webhook delivery includes the following headers alongside the JSON payload.
Content-Typeapplication/jsonX-Webhook-EventEvent type (e.g. order.created)X-Webhook-DeliveryDelivery UUIDX-Webhook-AttemptAttempt number (1-based)X-Webhook-TimestampUnix timestampX-Webhook-Signaturev1=<hmac_sha256> (if endpoint has a secret)Signature verification
If your endpoint has a signing secret configured, Deliverant computes an HMAC-SHA256 signature over the timestamp and request body. Verify this signature to ensure the webhook is authentic and untampered.
signature = HMAC-SHA256(secret, "{timestamp}.{body}")import hmac
import hashlib
def verify_webhook(secret: str, timestamp: str, body: bytes, signature: str) -> bool:
expected = hmac.new(
secret.encode(),
f"{timestamp}.".encode() + body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"v1={expected}", signature)const crypto = require('crypto');
function verifyWebhook(secret, timestamp, body, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${body}`)
.digest('hex');
return signature === `v1=${expected}`;
}Delivery states
Each delivery progresses through a series of states. Terminal states are final — once reached, no further attempts are made.
Retry backoff schedule
Failed deliveries are retried with exponential backoff. Full jitter is applied — the actual delay is random(0, max_delay).
After 12 failed attempts, the delivery transitions to FAILED terminal state.