Skip to content

Create a webhook endpoint

Webhooks notify your service when something happens — a verification completes, an applicant skips a step, a manual review is requested. You register an HTTPS endpoint, pick the events, and the platform POSTs a signed payload.

You need Owner or Admin access. Webhook endpoints are configured per mode — endpoints registered in test mode receive only test-mode events. Switch mode in the sidebar before registering. See Modes and regions.

Open Developers → Webhooks and click New subscription. Enter the receiver URL. The URL must start with https://. Plain HTTP is rejected so your signing secret cannot leak. Pick the events you want.

On submit, we generate a 32-byte signing secret and return it once. Copy it into a secrets manager — it is never retrievable again. If you lose the secret, rotate it (see Verify webhook signatures).

These events are delivered today:

  • kyc.session.completed — verification finished, terminal outcome assigned.
  • kyc.session.cancelled — verification cancelled by the operator.
  • kyc.session.manual_review_requested — the verification was parked for human review.

These event types are reserved and accepted on a subscription, but no delivery is produced for them. Subscribing to them is harmless and forward-compatible; build your receiver to handle them when deliveries begin, without assuming they currently arrive:

  • kyc.session.expired — the applicant did not finish before the link expired.
  • kyc.session.skipped_by_applicant — the applicant skipped a step, ending the verification.

Naming follows kyc.<domain>.<state> so you can pattern-match on the prefix. Your receiver should handle unknown event.type values defensively (log and ignore, do not error) — new event types can ship without a code change on your side.

Every kyc.session.* delivery carries a compact JSON body with reference fields only — no applicant personal data:

{
"sessionId": "vs_01J9X2Y3Z4A5B6C7D8E9F0G1H2",
"status": "completed",
"outcome": "approved",
"occurredAt": "2026-06-16T12:34:56.000Z"
}
  • sessionId — the verification id. Use it to fetch full detail from the REST API.
  • status — the terminal status at emit time.
  • outcome — the assigned verification outcome, or null for a transition that carried no verdict.
  • occurredAt — UTC ISO-8601 timestamp of the transition.

The payload is additive within a version: a new optional field may be added without breaking your receiver, and a breaking change ships as a new event version. Parse defensively and ignore fields you do not recognize. The webhook is an integration trigger, not a data export — fetch authoritative detail by sessionId from the API.

After saving the subscription, send a test request from your client to confirm signature verification. The Verify webhook signatures page shows the exact algorithm, header format, and tolerance window. Real events fire when the underlying state transition happens.

The subscription list at Developers → Webhooks shows each endpoint, the events it receives, and the last successful and unsuccessful delivery times. Open a subscription to see its full delivery history, replay individual deliveries, and rotate the signing secret.

The same delivery log is available over the REST API at GET /v1/webhook-events. It is cursor-paginated and returns one row per delivery attempt, with the status, HTTP code, latency, attempt count, and a bounded error code. Filter by session_id to trace one verification’s deliveries, or by subscription_id to inspect one endpoint. The response never includes the signing secret or the event payload. See the API reference for the full schema.