Platform signal details
This page is the implementation-focused companion to Platform age signals. Use it when you need exact field shapes, endpoint behavior, and examples you can map directly into your client or server-side integration.
Choose the right signal shape
| Platform | Native signal type | What to send to k-ID | Verified for age requirements? | Notes |
|---|---|---|---|---|
| Apple iOS | Numeric age range | ageLow, ageHigh, optional declarationType | Yes, for verified declaration types | Don't send category |
| Google Play | Numeric age range | ageLow, ageHigh, optional declarationType | Yes, for verified declaration types | Don't send category |
| Xbox | Category | category | No | k-ID resolves the category using the player's jurisdiction |
| Meta Horizon | Category | category | No | k-ID resolves the category using the player's jurisdiction |
| k-ID | Prior verification | verificationId, plus optional category or range | Yes, if the verification is valid | declarationType is resolved server-side |
If a platform already gives you ageLow and ageHigh, send those values directly. Only use POST /age-gate/get-platform-age-range for category-based platforms.
Platform-specific integration guide
Apple iOS
How to obtain the signal: use the Age Range Service to get the player's age range and declaration type.
What to send to k-ID: name, ageLow, ageHigh, and optionally declarationType.
Verified declaration types: paymentChecked, governmentIDChecked, guardianPaymentChecked, guardianGovernmentIDChecked
{
"name": "apple-ios",
"ageLow": 18,
"ageHigh": 25,
"declarationType": "governmentIDChecked"
}
Google Play
How to obtain the signal: use the Play Age Signals API to get the player's age range and userStatus.
What to send to k-ID: name, ageLow, ageHigh, and optionally declarationType.
Verified declaration types: VERIFIED, SUPERVISED
{
"name": "google-play",
"ageLow": 13,
"ageHigh": 17,
"declarationType": "VERIFIED"
}
Xbox
How to obtain the signal: use XR-014 and XUserGetAgeGroup to get the player's age group.
What to send to k-ID: name and category.
Accepted categories: child, teen, adult
How k-ID interprets them:
child=[0, digitalConsentAge - 1]teen=[digitalConsentAge, civilAge - 1]adult=[civilAge, 100]
Xbox signals aren't considered verified for verified-age permissions.
{
"name": "xbox",
"category": "adult"
}
Meta Horizon
How to obtain the signal: use the Get Age Category API to get CH, TN, or AD.
What to send to k-ID: name and category.
Accepted categories: CH, TN, AD
How k-ID interprets them:
CH=[10, digitalConsentAge - 1]with a minimum age of 10TN=[digitalConsentAge, civilAge - 1]AD=[civilAge, 100]
For a typical Brazil configuration, that results in CH=10-12, TN=13-17, AD=18+.
Meta Horizon signals aren't considered verified for verified-age permissions.
{
"name": "meta-horizon",
"category": "TN"
}
k-ID
How to obtain the signal: use a previously completed k-ID verification and pass its verificationId.
What to send to k-ID: name: "k-id" and verificationId. You can also send category or ageLow and ageHigh if your flow needs them, but whether the signal counts as verified comes from the verification lookup.
Server-side verification checks: the signal is considered verified only when the verification:
- Exists
- Has status
PASS - Belongs to the same organization as the requesting product
Caller-provided declarationType values are ignored for k-id signals.
{
"name": "k-id",
"category": "adult",
"verificationId": "a50f4f73-3c0c-4720-a8b3-ec57ccb0aa34"
}
verificationId is limited to one active session per product within an organization. The same verification can be reused across different products in the same organization, but not by multiple active sessions in the same product.
API reference
The six endpoints below are the most relevant to platform age signal integration. Each entry describes when and why to call it. For the full request and response schema, follow the link to the API reference.
GET /age-gate/get-requirements
Call this before showing the age gate. Pass platform signal fields as query parameters (platformName, platformAgeLow, platformAgeHigh, platformCategory, platformDeclarationType, platformVerificationId) to let k-ID factor the signal in before you even collect input.
Key response fields to act on:
shouldDisplay:falsewhen a verified platform signal proves the player is an adult; skip your age gate UI when this isfalseageAssuranceRequired:falseonly when every verified-age permission is already satisfied by the signalpermissions: lists permissions with averifiedAgeThreshold; useful even when all are already satisfied
GET /age-gate/get-default-permissions
Call this when you want to preview permission states without creating a session. Useful for checking whether a verified signal would immediately satisfy a threshold permission before the full age gate flow runs.
- Permissions with
verifiedAgeThresholddefault toenabled: false - A verified signal with
ageLow >= thresholdsets those permissions toenabled: true - For
k-idsignals, the declaration type is resolved server-side fromplatformVerificationId
GET /session/get
Refresh the session after check, VPC, or an age assurance challenge. The response includes an ageVerification object when a verified platform signal (or completed age assurance) has been recorded on the session. Check ageVerification.platformName and ageVerification.declarationType to understand the verification source.
POST /age-gate/check
Creates or updates the session. Pass a platformAgeSignal in the request body, either on its own or alongside dateOfBirth, age, or kuid. k-ID uses the more conservative of the two ages when both are present.
Possible outcomes relevant to platform signals:
- Verified signal + age meets threshold: session contains
ageVerificationand the permission isenabled: true - Signal present but not verified: session is created without
ageVerification; high-risk permission needs age assurance later - Player age below threshold: permission is
managedBy: PROHIBITED; the age assurance recovery flow applies - Age conflict: returns
400 AGE_CONFLICTwhen age-conflict detection is enabled and the platform signal indicates a younger age category than the player's self-reported age
POST /age-gate/get-platform-age-range
Converts a platform category string into a concrete ageLow/ageHigh pair for a given jurisdiction. Only needed for category-based platforms (Xbox, Meta Horizon, k-ID). If the platform already gives you a numeric range, skip this call and send the values directly.
POST /session/upgrade
Requests additional permissions for a player's existing session. This is the endpoint that determines whether a high-risk permission can be unlocked immediately or needs an age assurance challenge first.
The challenge type returned depends on what's being requested:
| Scenario | challenge.type returned |
|---|---|
Permission is PLAYER-managed | No challenge: permission enabled immediately |
Permission is GUARDIAN-managed | CHALLENGE_SESSION_UPGRADE (trusted adult consent) |
Permission has verifiedAgeThreshold and session has no ageVerification | CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCE (player must verify age) |
Permission has verifiedAgeThreshold and session already has ageVerification meeting the threshold | No challenge: permission enabled immediately |
Key constraint: all permissions in a single upgrade request must be of the same type. Mixing permissions with and without verifiedAgeThreshold in one call returns 400: "Can't mix permissions with and without verifiedAgeThreshold".
Example: request a high-risk permission (triggers age assurance):
POST /api/v1/session/upgrade
Content-Type: application/json
Authorization: Bearer your-api-key
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"requestedPermissions": [
{ "name": "loot-boxes-paid-gameplay-impacting" }
]
}
Example: pass a k-ID signal from a completed age appeal to satisfy the threshold directly, without creating a new challenge:
POST /api/v1/session/upgrade
Content-Type: application/json
Authorization: Bearer your-api-key
{
"sessionId": "b1a6482d-5242-4b4a-aa88-3fa52595a672",
"requestedPermissions": [
{ "name": "loot-boxes-paid-gameplay-impacting" }
],
"platformAgeSignal": {
"name": "k-id",
"verificationId": "a50f4f73-3c0c-4720-a8b3-ec57ccb0aa34"
}
}
When a CHALLENGE_SESSION_UPGRADE_BY_AGE_ASSURANCE challenge is returned, direct the player to the challenge.url to complete age verification through AgeKit+. Once the challenge passes, retrieve the updated session: the permission is now enabled: true with an ageVerification object on the session.
Validation and edge cases
Input validation
| Scenario | Result |
|---|---|
platformAgeSignal with missing name | 400: "Platform name must be provided" |
| Unknown platform name | 400: "Unknown platform name" |
apple-ios or google-play with category | 400: "Platform must have age range specified" |
Both category and ageLow/ageHigh provided | 400: "Provide either category or ageLow and ageHigh, not both" |
Only ageLow without ageHigh (or vice versa) | 400: "ageLow and ageHigh must both be provided" |
ageLow greater than ageHigh | 400: Invalid range |
Mixed threshold and non-threshold permissions in session/upgrade | 400: "Can't mix permissions with and without verifiedAgeThreshold" |
Age conflict matrix
When both a primary age and a platform signal are present:
| Platform age category \ Primary age category | Primary: Minor | Primary: Youth | Primary: Adult |
|---|---|---|---|
| Platform: Minor | No conflict | CONFLICT | CONFLICT |
| Platform: Youth | No conflict | No conflict | CONFLICT |
| Platform: Adult | No conflict | No conflict | No conflict |
A conflict only happens when the platform says the player is younger than the self-reported age category.
k-id signal security rules
declarationTypeis always resolved server-side fromverificationId- Caller-provided
declarationTypeis ignored - The verification must be
PASS - The verification must belong to the same organization as the requesting product
- Without a valid
verificationId, thek-idsignal is treated as unverified
Conservative defaults
- If
shouldDisplayisfalseand you have no platform signal to send, callPOST /age-gate/checkwithage: 1 - If the platform signal and primary age disagree but don't conflict, k-ID uses the lower age
- Verified-age permissions default to
enabled: falseuntil they're actually satisfied