Signature
Each delivery includes anX-Zeam-Signature header of the form
sha256=<hex>, where <hex> is an HMAC-SHA256 of the exact raw request body.
The HMAC key is the X-Webhook-Id header value — the UUID that uniquely
identifies this delivery.
To verify, recompute the HMAC over the raw body bytes and compare it to the
header using a constant-time comparison. Use the raw bytes before any JSON
parsing or re-serialisation.
Replay protection
Each delivery includes anX-Webhook-Ts header containing the delivery
timestamp as Unix milliseconds (UTC). Use it to reject stale deliveries and
narrow the window in which a captured request could be replayed:
X-Webhook-Id deduplication: persist each
processed X-Webhook-Id and ignore any delivery whose ID you have already seen,
regardless of timestamp.
Build an idempotent consumer
- Persist a processed-event key (the
X-Webhook-Id, orintentIdplus event type) and ignore duplicates. - Return a
2xxfor an event you have already processed. - Separate acknowledgement from processing: acknowledge fast, then process on a background worker.
- Log deliveries safely. Never log the raw signature key, tokens, or full personal data.
- Reconcile webhook state with the Transactions API rather than trusting the event in isolation.