Core Concepts
Understanding Xident's key concepts will help you build the best verification experience for your users.
Xident ID
A Xident ID is a unique identifier issued to users who complete verification. It enables the "Verify Once, Access Everywhere" model.
How It Works
- User visits Site A and completes full verification
- User receives a Xident ID (stored in their browser)
- User visits Site B (also using Xident)
- Site B detects the Xident ID
- Instant verification — no camera, no documents
- Site B pays the lower Xident ID rate for the returning user
User Control
Users can:
- View their authorized OAuth apps in the Xident portal
- Revoke OAuth consent for specific apps
- Delete their Xident ID entirely
Verification Paths
Xident uses five verification paths, automatically selected based on user context:
User arrives at site
|
v
+------------------+ +------------------+
| Has Xident ID? |--Yes->| Path D: Token | (instant, cheapest)
+--------+---------+ +------------------+
| No
v
+------------------+ +------------------+
| EU Wallet avail? |--Yes->| Path E: Wallet | (mso_mdoc attestation)
+--------+---------+ +------------------+
| No
v
+------------------+ +------------------+
| Restricted |--Yes->| Path C: Document | (always OCR)
| country? | +------------------+
+--------+---------+
| No
v
+------------------+ +------------------+
| ML age check |--Pass>| Path A: ML Fast | (client-side, no images sent)
+--------+---------+ +------------------+
| Fail
v
+------------------+
| Path B: Document | (OCR fallback -> Xident account funnel)
+------------------+
Path A: ML Fast
Client-side verification using machine learning. Face images never leave the browser.
- Liveness Detection: Ensures a real person is present (not a photo/video)
- Age Threshold Classification: Binary ML classifiers determine if the user is above the required age threshold (+12, +15, +18, +21, +25) via ONNX Runtime in WebAssembly
- No face data is sent to the server — only a pass/fail result
Path B: Document Fallback
When ML classification fails (approximately 11% false rejection rate for +18), the user falls back to document verification:
- Document OCR: ID document uploaded and processed server-side
- Face Match: Document photo matched against liveness frame
- This is the registration funnel — after the document pain, users are prompted to create a Xident account so they never need to do this again
Path C: Compliance
For restricted countries where ML false positive rates are insufficient for regulatory requirements:
- Always requires document verification regardless of ML result
- Ensures compliance with local age verification regulations
Path D: Xident Token
For returning users who already have a Xident ID with a verified age bracket:
- Instant verification — no camera, no documents
- Token lookup only, 60-80% cheaper than full verification
- Same trust level as full verification
Path E: EU Wallet
For users with an EU Digital Identity Wallet that supports age attestation:
- Uses the W3C Digital Credentials API and OpenID4VP protocol
- Validates mso_mdoc age attestations against the EU Trusted List
- Supports cross-device flow via QR code (user scans with wallet app on phone)
- No face images, no documents — wallet provides a cryptographic age proof
- See API Reference for the wallet endpoints
Privacy and Compliance
Privacy Architecture
- ML Fast path: Face images never leave the browser
- Document path: Document images deleted immediately after OCR
- Server stores only 512-dimensional face embeddings (not reconstructable to faces)
- No PII retained — only DOB-derived age bracket
- Consumers (site owners) receive only pass/fail, never actual age
ARCOM Compliance (Unlinkability)
French Regulatory Compliance
Xident satisfies the French ARCOM unlinkability requirement: age verification does not link users to the platforms they visit. There is no account_connections table — Xident never records which sites a user has verified on. The portal's "Authorized Apps" page shows only OAuth consent grants (for "Login with Xident"), not verification history.
Verification Types
Full Verification
First-time verification with ML processing:
- Liveness Detection: Ensures a real person is present (not a photo/video)
- Age Threshold Classification: ML model determines if user is above required age threshold (+12, +15, +18, +21, +25)
- Document Verification: OCR extraction from ID documents (fallback)
Token Verification
Returning user verification using Xident ID:
- Instant, no UI required
- 60-80% cheaper than full verification
- Same trust level as full verification
EU Wallet Verification
Age attestation via EU Digital Identity Wallet:
- Cryptographic age proof from government-issued wallet
- No biometrics required
- Cross-device flow supported (QR code scan)
Face 2FA
Per-site facial authentication:
- Users enroll their face for a specific site
- Subsequent logins verified via face match
- Separate from Xident ID (site-specific)
Blacklist Check
Fraud detection via face similarity:
- Check if a face matches any in your blacklist
- Prevent banned users from creating new accounts
- Privacy-preserving (no PII shared)
Tokens
A verification flow involves two different tokens — don't confuse them:
- Init token (
xit_…): created byPOST /verify/v1/initand carried in the verification URL as?t=. One-time use, 10-minute expiry. It bootstraps the widget (it never appears in your callback). - Result token (
xtk_…): returned to your callback URL as?token=after verification. You pass it toGET /verify/v1/result/{token}to read the outcome. Single-use; its expiry is returned asexpires_atin the result response.
Result Token Lifecycle
Verification Complete
|
v
+-------------------+
| Result token | --- xtk_… returned to your callback (see expires_at)
+--------+----------+
|
v
+-------------------+
| Backend Verifies | --- Token consumed
+--------+----------+
|
v
+-------------------+
| Token Invalidated | --- Cannot be reused
+-------------------+
Token Properties
- One-time use: tokens are invalidated after they are consumed
- Short-lived: the init token expires in 10 minutes; the result token's expiry is returned as
expires_at - Tamper-proof: opaque, randomly generated, server-validated
Verification Flow States
| Status | Description |
|---|---|
success | Verification completed successfully |
cancelled | User closed the verification window |
expired | Session timed out |
failed | Verification could not be completed |
API Keys
Xident uses a Stripe-style dual key model. You have two types of API keys:
Secret Key (sk_*) — the one you need
- Used in backend only (Node.js, Python, PHP, Go)
- Never expose in client-side code
- Authenticates the whole flow:
POST /verify/v1/initandGET /verify/v1/result/:token - Starts with
sk_live_(production) orsk_test_(sandbox)
Public Key (pk_*) — optional
- Safe to expose in client-side code; only needed if you embed the widget from the browser yourself instead of redirecting from your backend
- Can call
POST /verify/v1/initand widget-facing endpoints (requirements, liveness, OCR) — but cannot read verification results - Starts with
pk_live_(production) orpk_test_(sandbox) - The standard backend integration does not use it
Auth Header
Both key types use the same header:
X-API-Key: pk_live_... or sk_live_...
Environments
Production
- API Key prefix:
pk_live_,sk_live_ - Real verifications, real billing
- Requires HTTPS callback URLs
Sandbox (Testing)
- API Key prefix:
pk_test_,sk_test_ - No real verification, simulated responses
- Allows localhost callback URLs
- No charges
Webhooks
Receive real-time notifications for verification events:
| Event | Description |
|---|---|
verification.completed | User completed verification |
verification.failed | Verification failed |
token.verified | Token was verified by your backend |
Configure webhooks in your Dashboard.
Rate Limits
| Endpoint | Limit |
|---|---|
| Token verification | 100 req/min |
| SDK initialization | 1000 req/min |
| Wallet endpoints | 60 req/min |
| Webhook delivery | 3 retries over 24h |
Next Steps
- Integration Guide - Detailed SDK usage
- Dashboard Guide - Managing your account
- API Reference - Full API documentation