Skip to main content
Webhooks push a signed copy of every state-changing ledger event to an endpoint you control. The same payloads are also available to pull from the events tail, so you can choose push, pull, or both.
Kordio Control events are a separate subscription, registered per workspace with a different event set and a different retry schedule. See Kordio Control: webhooks. The signing algorithm is the same, so the routine below verifies either, but read the header name off the request rather than hard-coding one.

Register an endpoint

Ledger endpoints are per tenant and need ledger:write.
201 Created
signing_secret is returned only once, at creation. Store it immediately. If you lose it, rotate the endpoint’s secret to mint a new one.
The field is signing_secret here and secret on the spend control side. The two APIs differ; do not share a parser.

Event types

Ingestion itself emits no per-row events; a 10k-row batch would flood the stream. Use reconciliation.run_completed plus GET /v1/external_transactions?status=open for the break workflow. Additional oauth_client.*, member.*, tenant.* and reserve.* events exist for account-management surfaces. Subscribe only to what you handle. A plain period close emits nothing. Only period.closed_forced fires, so a subscriber cannot use these events to learn that a period closed cleanly; read GET /v1/period_closes for that. transaction.reversal_created is emitted before transaction.reversed on purpose. A subscriber rebuilding state from the tail can apply the new transaction before applying the link from the original to its reversal.

Verify the signature

Each delivery includes a Kordio-Signature header: an HMAC-SHA256 over <timestamp>.<raw_body>, keyed by the endpoint’s signing secret.

Respond and retry

A delivery succeeds on any 2xx. Any non-2xx, timeout, or network error is retried with exponential backoff: After the fifth failed attempt the delivery is marked dead. 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. You can inspect deliveries for an endpoint, count failures, redeliver a specific delivery, or send a test event from the webhook endpoints API.

Events tail and replay

Every state-changing operation also lands in the durable events log, with the same payloads webhooks deliver. If an endpoint was down or you need to backfill, pull from the tail instead of relying on retries.
The events list is cursor-paginated, newest first, and filterable by type and time. since takes an ISO 8601 timestamp or a relative form like 24h, 7d or 30m. Fetch a single event with GET /v1/events/{id}. This is the safe way to rebuild state after an outage, and it is not the audit trail. An event is written just after its transaction commits, so a crash in that window loses the event and keeps the transaction. The postings are what an audit reads.

Next steps

Reconciliation

The workflow reconciliation.run_completed drives.

Pagination

Walking the events tail with cursors.