Skip to main content
Webhooks push a signed copy of every control-layer state change to an endpoint you control. The one you actually need is action.requires_approval paired with approval.resolved: that pair is how an agent waits on a person without polling.
Ledger events are a separate subscription with a different registration endpoint and a different event set. See Ledger: webhooks. The signature scheme is identical, so one verification routine covers both.

Register an endpoint

Endpoints are per workspace and need the manage_policy capability.
201 Created
secret is returned exactly once, at creation. Store it immediately. If you lose it, rotate the endpoint with POST /control/v1/workspaces/{slug}/webhook_endpoints/{id}/rotate, which mints a new one and stops the old one verifying immediately.
An empty enabled_events array subscribes to every event type, not none. Name the types you handle.

Event types

A payment fires both spellings. Anything whose action_type starts with payment. emits the payment.* event and its action.* equivalent, whichever endpoint booked it, so an endpoint subscribed to either name hears about it. An unrecognised name in enabled_events is rejected with a 422 at registration. Never treat approval.resolved as permission on its own. It tells you a decision was made, not what it was, and an approved intent carries no cosignature. Read the outcome, and for anything that moves money verify the cosignature at the point of execution.

Delivery shape

Header: Kordio-Signature: t=<unix>,v1=<hex>, an HMAC-SHA256 over <timestamp>.<raw_body> keyed by the endpoint secret.

Verify the signature

Handler

Respond and retry

A delivery succeeds on any 2xx. Anything else, including a timeout or a connection error, is retried with polynomial backoff for up to eight attempts, after which the delivery is marked failed with its last error recorded. The ledger API retries on a different schedule; if you point both at one handler, do not assume a shared budget. Return 2xx quickly and do heavy work asynchronously. Events carry stable ids, so treat handlers as at-least-once and deduplicate on the event id.

If you would rather poll

Everything a webhook reports is also readable. The audit trail is the durable version of the same story:
Filtering by trace_id pulls one action’s whole history across authorization, approval and outcome. Every role can read it, including member.

Next steps

Holding spend for a person

The flow these events drive.

API reference

Endpoint management and the audit events API.