Skip to main content

Challenge.StateChange

Emitted when a parental consent challenge changes state.

Challenges don't expire

A challenge remains pending until a trusted adult either approves or denies it. Only the access methods (OTP, QR code, email link) expire, not the challenge itself. For details, see Challenge expiration and time-based authentication.

Fields

FieldTypeRequiredDescription
eventTypestringyesAlways "Challenge.StateChange"
dataobjectyesChallenge state change data
data.idstring (UUID)yesChallenge ID
data.productIdnumberyesThe productId for the product
data.statusstringyesOne of PASS, FAIL, IN_PROGRESS
data.dobstring (YYYY-MM-DD)noPlayer date of birth; present when available
data.sessionIdstring (UUID)noPresent when status is PASS
data.approverEmailstringnoPresent when status is PASS
data.kuidstringnoThe kuid (k-ID user ID); present when available

Example

{
"eventType": "Challenge.StateChange",
"data": {
"id": "9d6b056e-7d62-4a9e-907a-3d0f6f1d1b9a",
"productId": 11472,
"status": "PASS",
"dob": "2011-07-12",
"sessionId": "b6d1a7c2-8f34-4c83-bf0b-3a6d4a2f9d31",
"approverEmail": "parent@example.com",
"kuid": "7a1f2c3d-4e5f-6789-abcd-ef0123456789"
}
}

Challenge event contract

This section documents the complete contract for challenge state change events, including all possible fields, their presence rules, and how to interpret different statuses.

DOM messages aren't authoritative

Challenge results are also communicated to front-end applications via DOM messages for UI control purposes. However, only webhook events and the GET /challenge/get-status endpoint responses should be considered reliable, authoritative data sources for integration logic. DOM messages are provided solely for front-end application state management and shouldn't be used as the basis for critical business decisions or data persistence.

Data structures

Webhook event structure

Webhook events are wrapped in an event envelope:

{
"eventType": "Challenge.StateChange",
"data": {
"id": "uuid",
"productId": number,
"status": "PASS" | "FAIL" | "IN_PROGRESS",
"dob": "YYYY-MM-DD" | null,
"sessionId": "uuid" | null,
"approverEmail": "string" | null,
"kuid": "string" | null
}
}

API endpoint response structure

The GET /challenge/get-status endpoint returns a direct response:

{
"id": "uuid",
"status": "PASS" | "FAIL" | "PENDING" | "IN_PROGRESS",
"dob": "YYYY-MM-DD" | null,
"sessionId": "uuid" | null,
"approverEmail": "string" | null
}

For complete endpoint documentation, see GET /challenge/get-status.

Key differences between webhook and API endpoint

AspectWebhook EventAPI Endpoint
Status valuesPASS, FAIL, IN_PROGRESSPASS, FAIL, PENDING, IN_PROGRESS
StructureWrapped in { eventType, data }Direct response object
productIdAlways includedNot included
kuidIncluded when availableNot included
When availableOnly when challenge state changesCan be polled at any time

Status types

PASS

The trusted adult approved the consent request. A session has been created or updated with the approved permissions.

Availability:

  • Webhook: ✅ Sent when consent is approved
  • API Endpoint: ✅ Returned when consent has been approved

FAIL

The trusted adult explicitly denied the consent request. This only occurs when a parent actively clicks "Deny" in Family Connect. Challenges don't automatically fail due to timeout or expiration.

Availability:

  • Webhook: ✅ Sent when consent is denied
  • API Endpoint: ✅ Returned when consent has been denied

IN_PROGRESS

The trusted adult has accessed the challenge (clicked the link, scanned the QR code, or entered the OTP) but hasn't yet completed the consent flow.

Availability:

  • Webhook: ✅ Sent when the trusted adult begins the flow
  • API Endpoint: ✅ Returned when the flow is in progress

PENDING

The challenge has been created but no trusted adult has accessed it yet.

Availability:

  • Webhook: ❌ Never sent (no state change has occurred)
  • API Endpoint: ✅ Returned when challenge is awaiting action

Field presence rules by status

Status: PASS

Webhook events

Always included:

  • id (UUID) - Challenge ID
  • productId (number) - Product ID
  • status ("PASS")
  • sessionId (UUID) - The created or updated session ID

Sometimes included:

  • dob (string, YYYY-MM-DD) - Player's confirmed date of birth, if the trusted adult confirmed or corrected it
  • approverEmail (string) - Email of the trusted adult who approved
  • kuid (string) - k-ID user ID, if the player has one

API endpoint

Always included:

  • id (UUID) - Challenge ID
  • status ("PASS")
  • sessionId (UUID) - The created or updated session ID

Sometimes included:

  • dob (string, YYYY-MM-DD) - Player's confirmed date of birth
  • approverEmail (string) - Email of the trusted adult who approved
What you need to know
  • Use the sessionId to fetch the full session with GET /session/get
  • Store the approverEmail for customer support cases
  • The dob might differ from what the player originally entered if the trusted adult corrected it

Status: FAIL

Webhook events

Always included:

  • id (UUID) - Challenge ID
  • productId (number) - Product ID
  • status ("FAIL")

Never included:

  • sessionId - No session is created when consent is denied
  • approverEmail - Not provided for denied requests

API endpoint

Always included:

  • id (UUID) - Challenge ID
  • status ("FAIL")

Never included:

  • sessionId
  • approverEmail
What you need to know
  • A FAIL status means the trusted adult explicitly denied the request
  • Display an appropriate message to the player explaining that their parent declined the request
  • The player can request consent again by creating a new challenge

Status: IN_PROGRESS

Webhook events

Always included:

  • id (UUID) - Challenge ID
  • productId (number) - Product ID
  • status ("IN_PROGRESS")

Never included:

  • sessionId
  • approverEmail
  • dob

API endpoint

Always included:

  • id (UUID) - Challenge ID
  • status ("IN_PROGRESS")
What you need to know
  • This status indicates a trusted adult is actively working through the consent flow
  • Consider updating your UI to show "Parent is reviewing" or similar
  • The next webhook is either PASS or FAIL

Status: PENDING (API only)

API endpoint

Always included:

  • id (UUID) - Challenge ID
  • status ("PENDING")

Never included:

  • All other fields
What you need to know
  • The challenge is waiting for a trusted adult to access it
  • Continue displaying the QR code, OTP, or email option to the player
  • Consider refreshing expired access methods with /challenge/generate-otp

Field presence summary

Webhook events

FieldPASSFAILIN_PROGRESS
idalwaysalwaysalways
productIdalwaysalwaysalways
statusalwaysalwaysalways
sessionIdalwaysnevernever
dobsometimesnevernever
approverEmailsometimesnevernever
kuidsometimesnevernever

API endpoint

FieldPASSFAILPENDINGIN_PROGRESS
idalwaysalwaysalwaysalways
statusalwaysalwaysalwaysalways
sessionIdalwaysnevernevernever
dobsometimesnevernevernever
approverEmailsometimesnevernevernever

Implementation checklist

  • Handle all three webhook statuses: PASS, FAIL, IN_PROGRESS
  • On PASS, extract sessionId and fetch the full session
  • On FAIL, display appropriate messaging to the player
  • On IN_PROGRESS, optionally update UI to show consent is being reviewed
  • Store approverEmail when available for customer support
  • Don't assume optional fields are present; check before accessing
  • Use webhook events for real-time updates, API polling as fallback