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.

Emitted when an attempt finishes with all checks passing. The payload includes the consented claims and the canonical list of selected field keys.

When it fires

After the verify pipeline accepts an attempt: SOD chain verified, all data-group hashes match, active and chip authentication checks pass when applicable, the face matcher accepts the selfie, and the user has consented to share at least all required fields. A session can only have one accepted attempt — once this event fires, the session moves to completed and no further attempts are allowed.

Payload

{
  "type": "verification.attempt.succeeded",
  "metadata": {
    "contract_version": 1,
    "event_id": "evt_...",
    "verification_attempt_id": "va_...",
    "verification_session_id": "vs_..."
  },
  "data": {
    "claims": {
      "date_of_birth": "1995-04-12",
      "family_name": "Curie",
      "given_names": "Marie",
      "kayle_document_id": "kdid_..."
    },
    "selected_field_keys": [
      "date_of_birth",
      "family_name",
      "given_names",
      "kayle_document_id"
    ]
  }
}

Fields

type
string
Always verification.attempt.succeeded.
metadata.contract_version
number
The share-contract version the session was created against. Use to detect changes if your code branches on contract semantics.
metadata.event_id
string
The unique event ID. Idempotency-key candidate — the same event will reuse this ID on retries and replays.
metadata.verification_attempt_id
string
The attempt that succeeded.
metadata.verification_session_id
string
The session this attempt belongs to.
data.claims
object
Map of claim key to value. Only the claims the user consented to share appear here. See Share fields for the catalogue and value formats.
data.selected_field_keys
string[]
The canonical, ordered list of keys present in claims. Iterate this rather than Object.keys(claims) if you need consistent order.

Handler outline

if (event.type === "verification.attempt.succeeded") {
  const { verification_session_id, verification_attempt_id, event_id } = event.metadata;
  if (await alreadyProcessed(event_id)) return;

  await markSessionVerified({
    sessionId: verification_session_id,
    attemptId: verification_attempt_id,
    claims: event.data.claims,
  });
}
The claims object reflects the user’s consent at the moment of acceptance. If you requested an optional field and it’s missing here, the user declined it — handle that without failing the verification.