Skip to main content
A verification session represents one Kayle check you want to run. You create a session via the API, redirect the user to the session’s verification_url, and receive the Kayle result over a webhook when the user finishes, or a verification.session.expired event if they don’t.

The session object

The shape returned by the API:
cancel_token is returned only at creation. The verify URL embeds it as a query parameter so the verify browser and native apps can pass it back when cancelling. If you want to surface a cancel link from somewhere else (a dashboard, an email), store it server-side at creation time.

Lifecycle

A session moves through these statuses: Sessions expire 60 minutes after created_at. A scheduled job sweeps expired sessions and emits verification.session.expired for any that didn’t reach a terminal status first.

Retries

A session has per-check retry budgets — not a single whole-session budget. When a user fails NFC, they don’t have to re-scan MRZ; when they fail liveness, they don’t have to re-tap the chip. Retries happen entirely inside the mobile app — the user does not re-scan the handoff QR code, and your server is not notified per retry. Only the terminal outcome fires a webhook. The verification.session.failed payload’s data.nfc_tries_used and data.liveness_tries_used tell you which check exhausted. document_anti_cloning_attestation_failed is a hard-kill: the session terminates immediately, regardless of retry counters. The session response exposes the live counters on nfc_tries_used and liveness_tries_used so you can render an “attempts remaining” UI without subscribing to webhooks.

Creating a session

share_fields is optional. If you omit it, the session uses Kayle’s default share contract (a minimal set including kayle_document_id). If you include it, every entry needs required and a non-empty reason (200 characters max). See Share fields for the catalogue. redirect_url is also optional, but it must begin with https://. Both fields are reflected back to the user during the consent step, so write reason strings the user will see and trust.

Cancelling

Two cancel paths exist:
  • Authenticated cancelPOST /v1/sessions/:id/cancel with your API key. Idempotent. Use this when you decide server-side that you no longer want the Kayle check to proceed.
  • Public cancelPOST /v1/verify/session/:id/cancel with the one-shot cancel_token in the body. The verify app and native apps use this to abort from the user’s side. The token is consumed on first successful use; subsequent calls return 204 if the session is already terminal, otherwise CANCEL_TOKEN_USED.
A cancelled session emits verification.session.cancelled to subscribed webhooks. The payload carries a reason (cancelled, cancelled_after_failed_check, or one of the privacy_cancelled_after_terminal_* variants when the event replaces a scrubbed succeeded / failed payload) plus the per-check retry counters. See the reference for the full field list.
The verification_url in the create response already contains cancel_token as a query parameter, so you don’t need to surface it yourself unless you’re building a separate cancel UI.

Listing sessions

GET /v1/sessions supports filtering by status, created_from, and created_to, and follows the standard cursor pagination (limit, starting_after, next_cursor). Pass include_attempts=true to attach the attempt array to each session — handy for reporting, but increases payload size.

What you don’t see

The session object never includes raw document data, MRZ fields, the on-chip portrait, selfies, or the face match score. Those are computed and discarded inside the verification pipeline. The consented claims surface only in the verification.session.succeeded webhook payload.