Webhooks
Get a signed HTTP callback whenever KaizoCore makes a matching decision.
Setting up a webhook
From the dashboard's Webhooks page, or via the API:
POST /v1/webhooks
{ "url": "https://yourapp.com/webhooks/kaizocore", "event_types": ["BLOCK", "REVIEW"] }The response includes a signing secret — shown in full exactly once. Store it; you'll need it to verify deliveries.
Event types
Webhooks subscribe to the same decision vocabulary used everywhere else:
ALLOW, ALLOW_WATCH, SOFT_CHALLENGE, REVIEW, BLOCK. Most integrations
only want BLOCK and REVIEW — the cases that need a downstream action —
but any combination is valid.
Payload
{
"event": "BLOCK",
"request_id": "a6af22a9-3a6c-42e8-b28f-3e3184093d79",
"decision": "BLOCK",
"score": 91.2,
"reasons": ["tor_ip", "bot_user_agent"],
"timestamp": 1752480000
}Verifying the signature
Every delivery includes:
X-KZ-Webhook-Signature: <hex HMAC-SHA256 of the raw request body>
X-KZ-Webhook-Ts: <unix timestamp>Compute HMAC-SHA256(your_signing_secret, raw_body) and compare it to the
header — the same signing pattern used throughout KaizoCore's own request
authentication (see The /v1/decide API).
Delivery guarantees
- Retries: up to 4 attempts total, with 2s / 4s / 8s backoff between them.
- Unhealthy marking: after 10 consecutive failed deliveries, a webhook is marked unhealthy and stops receiving new deliveries — surfaced clearly in the dashboard rather than retried silently forever. Fix the endpoint and it resumes on the next matching event.
- At-least-once: a delivery that times out on your end but actually
succeeded may be retried — make your endpoint idempotent using
request_id.
Known scope limit
Delivery currently runs in-process per decision rather than through a durable job queue — fine at typical traffic volumes, but a detail worth knowing if your endpoint is occasionally slow to respond: a slow endpoint extends how long that one decision's delivery goroutine stays open, up to the total retry window (~14 seconds), not indefinitely.
Managing webhooks
GET /v1/webhooks # list your webhooks (secrets masked)
DELETE /v1/webhooks/{id}
GET /v1/webhooks/deliveries # recent delivery attempts + status, across all your webhooks