Webhooks
Event envelope, signature verification, and delivery semantics.
Webhooks are the authoritative way to receive verification results. Polling
/v1/verifications/:id works, but webhooks are instant and cheaper.
Event envelope
This mirrors Stripe's event shape. id is globally unique; type identifies
the event; data.object is the full resource at the time the event fired.
Headers
Every delivery includes:
Content-Type: application/jsonKYC-Signature: t=<unix_ts>,v1=<hex_hmac_sha256>KYC-Event-Id: evt_...(idempotency key for your receiver)User-Agent: KYC-Webhooks/1.0
Verifying the signature
- Read the
KYC-Signatureheader and parse outtandv1. - Compute
HMAC-SHA256(secret, t + "." + raw_body). - Compare the hex digest against
v1using a constant-time comparison. - Reject if
|now - t| > 300seconds.
Delivery guarantees
- At-least-once. Expect occasional duplicates; dedupe on
KYC-Event-Id. - Retries. Exponential backoff up to 24 hours.
- Expected response.
2xxwithin 10 seconds. Anything else is a retry.
Event types (MVP)
| Type | Fires when |
|---|---|
verification.created | POST /v1/sessions succeeds. |
verification.updated | Any status transition. |
verification.completed | Terminal success. |
verification.failed | Terminal failure. |
verification.review_required | Manual review needed. |
billing.subscription.updated | Plan or state change (fiat). |
billing.wallet.updated | Prepaid wallet debit/credit. |