Build an Age Assurance Integration
Overview
Age Assurance uses the same single RiskOS™ Evaluation API as every other workflow. You submit a POST /api/evaluation request that names your Age Assurance workflow and carries the inputs the workflow needs. RiskOS™ orchestrates the passive and active methods you configured and returns a privacy-preserving threshold decision.
This guide covers the system integration: connecting your backend to the Evaluation API, submitting requests, acting on decisions, and handling step-ups. For method selection, waterfall ordering, and routing, see Configure the Workflow.
System architecture
RiskOS Your Backend Client App + SDK RiskOS Your Backend Client App + SDK
alt[Passive method resolves age][OTP or active capture required]
Collect inputs and consent
POST /api/evaluation
Run passive waterfall (device, email, phone)
ACCEPT or REJECT + Valid Age tag
Allow or block
ON_HOLD with OTP or capture link
Prompt user
Submit OTP or complete capture
Resume evaluation
Final decision
Allow or block
Integration flow
- Collect the inputs your configured methods need. Passive assurance uses a phone number, email, name, or address; device-based assurance uses a Digital Intelligence session token from the Digital Intelligence SDK. Age Assurance does not require date of birth or SSN.
- Submit a
POST /api/evaluationrequest from your backend with the workflow name and collected inputs. - Act on the top-level
decision(ACCEPTorREJECT) andValid Agetag to allow or block the user. - Handle a step-up if the workflow pauses for an OTP or an active selfie or document capture. See Step-up flows.
Required components
- A configured Age Assurance workflow.
- Integration with the Digital Intelligence SDK to collect the
di_session_token— required only for device-based assurance. - Integration with the Predictive DocV SDK if your workflow uses active selfie or document methods.
- A RiskOS™ API key from Developer Workbench > API Keys in the Dashboard.
- A webhook endpoint to receive results from asynchronous active capture flows (selfie or document).
Endpoint
HTTP
POST https://riskos.sandbox.socure.com/api/evaluation
HTTP
POST https://riskos.socure.com/api/evaluation
Include your API key in the Authorization header:
HTTP
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: application/json
Example request
Send the workflow name plus the inputs your waterfall reads. Phone-based assurance uses a phone number; email-based assurance uses an email; device-based assurance uses a Digital Intelligence session token. The workflow's routing conditions decide whether to escalate to an active selfie or document capture; the docv.config object controls that capture experience (language and whether Socure sends the capture link).
JSON
{
"id": "test-user-phone",
"timestamp": "2026-07-07T12:44:22.059Z",
"workflow": "docv_demo_socure",
"data": {
"event_type": "identity_verification",
"individual": {
"given_name": "Alex",
"family_name": "Doe",
"phone_number": "19843359615",
"email": "user@example.com",
"address": {
"country": "US"
},
"docv": {
"config": {
"language": "en",
"send_message": false
}
}
},
"channel": "web"
}
}
curl --request POST \
--url https://riskos.sandbox.socure.com/api/evaluation \
--header "Authorization: Bearer YOUR_API_KEY" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data '{
"id": "test-user-phone",
"timestamp": "2026-07-07T12:44:22.059Z",
"workflow": "docv_demo_socure",
"data": {
"event_type": "identity_verification",
"individual": {
"given_name": "Alex",
"family_name": "Doe",
"phone_number": "19843359615",
"email": "user@example.com",
"address": {
"country": "US"
},
"docv": {
"config": {
"language": "en",
"send_message": false
}
}
},
"channel": "web"
}
}'
Request fields
Top-level fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
id |
String | Required | Customer-defined unique identifier for the request. Reusing an ID causes RiskOS™ to treat the request as a re-run. | "test-user-phone" |
timestamp |
String | Required | RFC 3339 timestamp for when your system initiated the request. | "2026-07-07T12:44:22.059Z" |
workflow |
String | Required | Your environment-specific Age Assurance workflow identifier. | "docv_demo_socure" |
data.event_type |
String | Optional | The event category for the evaluation. | "identity_verification" |
data.channel |
String | Optional | The channel the request originates from. | "web" |
Individual fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
given_name |
String | Optional | First name. Improves passive identity resolution. | "Alex" |
family_name |
String | Optional | Last name. Improves passive identity resolution. | "Doe" |
phone_number |
String | Conditional | Required for phone-based assurance. | "19843359615" |
email |
String | Conditional | Required for email-based assurance. | "user@example.com" |
address.country |
String | Optional | Country in ISO 3166-1 alpha-2 format. | "US" |
Device fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
di_session_token |
String | Conditional | Device session token captured by the Digital Intelligence SDK and passed in the request. Required for device-based assurance. | "eyJraWQiOi_di_token" |
DocV configuration fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
send_message |
Boolean | Optional | When true, RiskOS™ sends the capture link to the user for the active step. When false, your app opens the capture flow directly. |
false |
language |
String | Optional | Capture-app language. | "en" |
Handling responses
The evaluation response reports the age result at two levels: a top-level decision your application acts on, and per-method threshold flags under computed for finer-grained logic.
Decision routing
| Decision | Action |
|---|---|
ACCEPT |
Allow the user through. A Valid Age tag confirms the age check passed. |
REJECT |
Block the user or route to a fallback flow. |
Use the top-level decision and Valid Age tag as your primary control signal. Do not use status, sub_status, or eval_status for business decisions — those describe evaluation lifecycle state only.
Example response
Example response (trimmed)
{
"id": "test-user-phone",
"workflow": "docv_demo_socure",
"eval_id": "7e79e169-5021-475b-af98-9362ac690c38",
"decision": "ACCEPT",
"status": "CLOSED",
"sub_status": "Accept",
"tags": ["Valid Age"],
"computed": {
"socure_age_assurance_response": {
"age18Plus": true,
"age21Plus": true,
"age25Plus": false,
"entityKind": "phone",
"isSuccess": true,
"refId": "789a83ce-8b28-4239-8a7c-20e1a8ba0b5a",
"uniqueCnt": 96
}
},
"eval_status": "evaluation_completed"
}
Key response fields
| Area | Fields | Purpose |
|---|---|---|
| Decision and routing | decision, tags, review_queues, score |
Primary signals for application logic and secondary routing |
| Threshold flags | computed.socure_age_assurance_response |
Per-method Boolean age-threshold results (age18Plus/21/25) |
| Traceability | id, eval_id |
Persist for correlation across API calls, logs, webhooks, and support |
| Lifecycle | eval_status, status, sub_status |
Monitoring and async flow tracking only |
Threshold flag fields
A passive method returns its result under computed.socure_age_assurance_response:
| Field | Type | Description |
|---|---|---|
age18Plus |
Boolean | true if the user meets the 18+ threshold, false if not. |
age21Plus |
Boolean | true if the user meets the 21+ threshold, false if not. |
age25Plus |
Boolean | true if the user meets the 25+ threshold, false if not. |
entityKind |
String | The method that produced the result: globalDeviceId, email, phone, selfie, or document. |
isSuccess |
Boolean | true when the method returned a usable result. |
refId |
String | Enrichment-level reference identifier. |
uniqueCnt |
Integer | Identity-graph match count (cardinality) for the lookup. |
Active methods (selfie or document) wrap the same threshold flags in an ageAssurance object under computed.socure_selfie_age_assurance_response, and add a decision of accept, reject, or resubmit.
Step-up flows
Some workflows escalate to an interactive step-up when a passive method can't resolve age on its own. When a step-up starts, the evaluation pauses with status: ON_HOLD.
- One-time passcode (OTP)
If a phone- or email-based method needs to confirm contact ownership, the evaluation pauses for OTP verification. Resume the evaluation by resubmitting the passcode with the original request id.
- Active capture (selfie or document)
If passive methods cannot resolve age, the evaluation pauses for selfie or document capture. Launch the Capture App or DocV SDK and wait for the final decision on the evaluation_completed webhook.
For implementation details, including request payloads, capture handoff assets, and webhook handling, see Handle Age Assurance Step-Up Flows.
Billing behavior
Age Assurance bills only when a method returns a usable result.
| Method category | Billable when... |
|---|---|
| Passive (device / phone / email) | Age is successfully returned. A no-hit lookup is not billable. |
| Phone / email OTP | Billed as part of the age-lookup SKU (not a separate charge). Runs only when an identity exists. |
This "no hit, no charge" model on passive methods lets you place low-cost lookups early in a waterfall without paying for misses.
Privacy and data handling
Age Assurance minimizes the age-related data your application ever receives or that Socure retains.
Not returned to your application:
- Date of birth
- Exact age or age range
- Raw PII
- Images (selfie or document)
- Confidence scores
Deleted immediately after processing:
- Input phone number and email
- Captured images (selfie, document)
- Age-range and confidence response data
- OTP-related data is deleted or anonymized
Retained for billing and audit only:
- Transaction ID and timestamp
- Methods (modules) called
- Method used for billing
- Final decision
Socure does not store raw PII, images, or confidence scores in the audit record.
Integration testing
A passive hit sets isSuccess: true and returns the threshold flags.
The waterfall falls through to the next method when a step returns no hit or has no input.
Active methods return the correct decision for accept, reject, and resubmit.
Routing conditions send each input (device, email, phone) to the intended branch.
Your application acts on the top-level decision and Valid Age tag.
id and eval_id are persisted for traceability.
Before going live
Production workflow is published and active.
Production API key is provisioned and securely stored.
Webhook endpoint is registered in the Production Dashboard.
Required SDKs (Digital Intelligence, Predictive DocV) are integrated where your workflow uses them.
Required scenarios are tested in Sandbox (passive hit, no-hit fallthrough, and any active capture).
Logging and monitoring are configured for decision distribution and latency.
Sensitive inputs (phone, email, session tokens) are redacted from logs.
For a comprehensive go-live process, see the Go-Live Checklist.
FAQs
What is the primary field to act on?
Use the top-level decision (ACCEPT or REJECT) and the Valid Age tag as your primary signal. The per-method threshold flags (age18Plus, age21Plus, age25Plus) under computed are available for finer-grained logic.
How do I switch a workflow from selfie to document capture?
Configure the routing conditions in the RiskOS™ Dashboard. Conditions branch on request inputs (for example, whether a phone, email, or device signal is present) and can also read custom fields you pass in the request. Because routing is configured in the workflow, you can change the active method without a code change once the workflow is integrated.