Webhooks
/v1/orgs/{org_id}/webhooksCreate Webhook
Authentication
Requires a CI- or admin-level token. Runtime tokens are rejected for mutations.
SDK install
pip install znyx-sdknpm install @znyx/sdkPath parameters
| Name | Type | Required | Description |
|---|---|---|---|
| org_id#path | string | required | — |
Header parameters
| Name | Type | Required | Description |
|---|---|---|---|
| X-API-Key#header | string | null | optional | — |
| authorization#header | string | null | optional | — |
Request bodyrequired
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | required | — |
| events | string[] | required | — |
| generate_secret | boolean | optional | — |
Responses
| Status | Description |
|---|---|
| 201 | Successful Response |
| 422 | Validation Error |
Response schema
Errors & what triggers them
| Code | Trigger | Fix |
|---|---|---|
| 400 | Webhook URL resolves to a private / loopback / reserved IP, or hostname is unresolvable. | Use a public HTTPS URL. Local testing requires a tunnel (ngrok, Cloudflare Tunnel). |
| 403 | Caller is not an org admin. | — |
| 422 | events list is empty or contains an unknown event name. | — |
Notes & examples
Event taxonomy
Webhooks subscribe to a list of event names. Available events:
- Bundle lifecycle —
bundle.published,bundle.activated,bundle.promoted - Evaluation —
evaluation.blocked(fires every time a runtime evaluation returns BLOCK) - Policy —
policy.updated,sso.configured - Team —
team.member_added,team.member_removed - Alerts —
alert.triggered(for paid-tier alert rules)
Signature verification
Every webhook POST to your URL includes an X-Webhook-Signature header of the form sha256=<hex>. Verify it by HMAC-SHA256'ing the raw request body with the shared secret you stored on creation:
import hmac, hashlib
def verify(raw_body: bytes, secret: str, header: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={expected}", header)SSRF protection
The control plane validates your webhook URL on creation. It refuses private / loopback / reserved / AWS-metadata IPs — no localhost, no 10.*, no 169.254.169.254. If you need to test locally, use a tunnel like ngrok.
Reliability
Failed deliveries retry with exponential backoff (5 attempts over ~2h). After that the event is dropped — we don't queue indefinitely. For durable delivery, use webhooks as a nudge and reconcile via the REST API.
Related
POST /v1/orgs/{org_id}/webhooks/{id}/test— send a synthetic event to check your endpoint responds.POST /v1/orgs/{org_id}/webhooks/{id}/rotate-secret— rotate the HMAC secret.
Request
curl -X POST 'https://api.znyx.ai/v1/orgs/00000000-0000-0000-0000-000000000000/webhooks' \
-H 'Authorization: Bearer $ZNYX_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"url": "string",
"events": [
"string"
],
"generate_secret": true
}'Response
Successful Response
{
"id": "string",
"org_id": "string",
"url": "string",
"events": [
"string"
],
"is_active": false,
"created_at": "string",
"has_secret": false
}Schema: object