Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kayle.id/llms.txt

Use this file to discover all available pages before exploring further.

A verification session represents one identity verification you want to perform. You create a session via the API, redirect the user to the session’s verification_url, and receive the 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:
{
  "id": "vs_mza7vec...",
  "status": "created",
  "contract_version": 1,
  "share_fields": {
    "date_of_birth":     { "required": true,  "reason": "Verify age",        "source": "rc" },
    "kayle_document_id": { "required": true,  "reason": "Sharing \"Kayle Document ID\"", "source": "default" }
  },
  "redirect_url": "https://yourapp.com/verification/done",
  "verification_url": "https://verify.kayle.id/vs_...?cancel_token=...",
  "cancel_token": "...",
  "expires_at": "2026-05-05T12:00:00Z",
  "completed_at": null,
  "created_at": "2026-05-05T11:00:00Z",
  "updated_at": "2026-05-05T11:00:00Z"
}
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:
StatusMeaning
createdThe session exists. No attempt has been claimed yet.
in_progressA mobile or web client is actively performing the verification.
completedAn attempt succeeded, or the maximum number of attempts was exhausted with no success.
expired60 minutes elapsed since creation without a terminal attempt.
cancelledThe session was cancelled by you or by the user.
Sessions expire 60 minutes after created_at. A scheduled job sweeps expired sessions and emits verification.session.expired for any that didn’t reach completed or cancelled first.

Attempts

Inside a session, each interactive run by the user is an attempt (va_...). An attempt has its own status — in_progress, succeeded, failed, cancelled — and, on failure, a failure_code you can match on. See Document checks for the codes. A session allows up to three attempts. After the third terminal failure, the session moves to completed and no further attempts are accepted. You can fetch attempts attached to a session with ?include_attempts=true on GET /v1/sessions/:id, or list across sessions via GET /v1/sessions/attempts.

Creating a session

curl -X POST https://api.kayle.id/v1/sessions \
  -H "Authorization: Bearer kk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "redirect_url": "https://yourapp.com/verification/done",
    "share_fields": {
      "date_of_birth": { "required": true, "reason": "Verify age eligibility" },
      "family_name":   { "required": true, "reason": "Match account name" }
    }
  }'
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 verification 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 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.
curl "https://api.kayle.id/v1/sessions?status=completed&limit=50" \
  -H "Authorization: Bearer kk_..."

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 only place verified claims surface is in the verification.attempt.succeeded webhook payload.