Webhooks
Webhooks deliver compliance results asynchronously when the request usesresponseMode: "async". The webhook URL and a per-job signing secret are supplied with the original request and returned in the 202 response — no upfront endpoint registration is required.
For a full submit → receive → verify walkthrough, see the Async + Webhook Execution guide.
Event types
| Event | Fired on |
|---|---|
compliance.completed | Successful end-to-end run, includes the full classified result |
compliance.failed | Pipeline failure or function timeout |
Delivery guarantees
- At-least-once delivery. Use the top-level
eventIdto deduplicate on your side. - HMAC signature in the
X-ZebraTruth-Signatureheader:sha256=<hex(hmac(secret, body))>. - Replay protection.
X-ZebraTruth-Timestampis an ISO 8601 timestamp; reject deliveries with drift greater than 5 minutes. - Per-attempt timeout. Each HTTP attempt has a 10-second timeout.
- Retry policy. Up to 4 attempts (initial + 3 retries) with delays
1 s, 5 s, 25 s. Total worst-case window: ~31 s. - Dead-letter recording. After exhaustion, the delivery is recorded with status
deadin the internal delivery log.
Webhook payload
callbackId is the opaque tag you supplied on the original request — included so you can correlate the webhook with whatever record triggered it.
Headers on every delivery
| Header | Example | Purpose |
|---|---|---|
Content-Type | application/json | — |
X-ZebraTruth-Event-Id | evt_0971a7addc874ba7 | Idempotency key for dedup |
X-ZebraTruth-Timestamp | 2026-05-01T03:58:52.553Z | Replay protection |
X-ZebraTruth-Signature | sha256=bbb03af377... | HMAC over the raw request body |
Verifying a webhook
secret is the webhookSecret returned in the 202 response when the job was submitted. Store it keyed by jobId. Each async job gets a fresh secret; secrets are not shared across jobs.
Failed delivery and recovery
If your webhook handler returns a non-2xx status (or the request times out), we retry with the schedule above. After all attempts fail, the result is still available via the polling endpoint:When the orchestrator fails
A pipeline error firescompliance.failed:
code | Meaning |
|---|---|
pipeline_error | An agent or sub-agent threw during the run |
vercel_timeout | Set by the stale-job sweeper when a run exceeded the function maxDuration ceiling without reaching a terminal state |