## Overview

Some Age Assurance 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`. The two step-ups resume differently:

- **One-time passcode (OTP)** — resumes when you resubmit the evaluation with the passcode. The result returns synchronously.
- **Active capture (selfie or document)** — resumes asynchronously. After the user completes capture, RiskOS™ delivers the final decision on the `evaluation_completed` webhook.

For when each step-up occurs and the high-level integration, see [Build an Age Assurance Integration](https://help.socure.com/riskos/docs/build-age-assurance-integration#step-up-flows).

## End-to-end async sequence

```
RiskOS™Your backendClient app + SDKRiskOS™Your backendClient app + SDKalt[One-time passcode (OTP)][Active capture (selfie or document)]POST /api/evaluationstatus ON_HOLD (step-up required)Prompt for passcodeSubmit passcodeResubmit evaluation with data.individual.otpFinal decision (synchronous response)Launch DocV capture with docvTransactionTokenComplete captureevaluation_completed webhook (final decision)Allow or block on the final decision
```

## One-time passcode (OTP)

Phone- and email-based methods can send a one-time passcode to confirm the user controls the contact. OTP runs only when RiskOS™ finds an identity.

- **Trigger** — A phone or email method needs to confirm possession.
- **Behavior** — RiskOS™ sends a passcode and pauses the evaluation on the OTP step.
- **Resume** — Collect the passcode from the user, then resubmit the evaluation with the same request `id` and the code under `data.individual.otp`.

JSON

```json
{
  "id": "test-user-phone",
  "workflow": "docv_demo_socure",
  "data": {
    "individual": {
      "otp": {
        "code": "123456",
        "resend": false
      }
    }
  }
}
```

Set `resend` to `true` to send a new passcode instead of verifying one.

The OTP result appears under `computed.otp_step_response`:

```json
{
  "verificationId": "a23ddf16-0a17-4639-9a46-e491ee237bae",
  "status": "approved",
  "attemptCount": 1
}
```

| Field                | Type    | Description                                                                           |
|----------------------|---------|---------------------------------------------------------------------------------------|
| `verificationId`     | String  | Identifier for the OTP verification attempt.                                          |
| `status`             | String  | Verification status, for example `approved` or `reject`.                            |
| `attemptCount`      | Integer | Number of passcode attempts made for this evaluation.                                |

For OTP configuration, see [One-Time Passcode (OTP)](https://help.socure.com/riskos/docs/one-time-passcode-otp).

## Active capture (selfie or document)

When no passive method resolves age, the workflow escalates to an active selfie or document capture. This is an **asynchronous** step-up — the evaluation pauses until the user completes capture.

### Detect the step-up

Check the evaluation response for both conditions:

- `eval_status` is `"evaluation_paused"` or `status` is `"ON_HOLD"`.
- `data_enrichments` includes an object where `enrichment_provider` is `"SocureDocRequest"`.

### Extract the handoff assets

Read these from the `SocureDocRequest` object's `response.data`:

| Field                   | Purpose                                                      |
|-------------------------|-------------------------------------------------------------|
| `docvTransactionToken`  | **Required.** Initialize the Capture App or DocV SDK with this value. |
| `url`                   | Optional. Direct mobile redirect to the Capture App.       |
| `qrCode`                | Optional. Base64 PNG for desktop-to-mobile handoff.       |

JSON

```json
{
  "eval_id": "7e79e169-5021-475b-af98-9362ac690c38",
  "status": "ON_HOLD",
  "eval_status": "evaluation_paused",
  "data_enrichments": [
    {
      "enrichment_provider": "SocureDocRequest",
      "response": {
        "data": {
          "docvTransactionToken": "70c6a4bc-f646-4c6a-94c1-9cd428e356ef",
          "url": "https://verify.socure.com/#/dv/70c6a4bc-f646-4c6a-94c1-9cd428e356ef"
        }
      }
    }
  ]
}
```

### Complete the handoff

1. **Persist** the `eval_id` and `docvTransactionToken` to correlate the webhook result later.
2. **Return** the token to your client.
3. **Launch** the [Predictive DocV SDK](https://help.socure.com/riskos/docs/docv-sdks) Capture App to present the capture UI.

### Receive the final decision

After capture, RiskOS™ resumes the evaluation and delivers the final result through the `evaluation_completed` [webhook event](https://help.socure.com/riskos/docs/webhooks). Correlate it to the original evaluation with `eval_id`.

JSON

```json
{
  "event_type": "evaluation_completed",
  "data": {
    "eval_id": "7e79e169-5021-475b-af98-9362ac690c38",
    "decision": "ACCEPT",
    "status": "CLOSED",
    "eval_status": "evaluation_completed"
  }
}
```

> 📘
> **Note:**
> Register a [webhook endpoint](https://help.socure.com/riskos/docs/webhooks) before you run active capture in Production. Without it, your integration can't receive the asynchronous final decision.

## FAQs

How do I tell an OTP step-up from an active capture step-up?

Both pause the evaluation with `status: ON_HOLD`. An active capture step-up also includes a `data_enrichments` object where `enrichment_provider` is `SocureDocRequest` and carries a `docvTransactionToken`. An OTP step-up has no `SocureDocRequest` handoff — you resume it by resubmitting the evaluation with the passcode.

How do I resend a one-time passcode?

Resubmit the evaluation with the same request `id` and `data.individual.otp.resend` set to `true`. RiskOS™ sends a new passcode instead of verifying one.

What happens if the user abandons a step-up?

The evaluation stays `ON_HOLD` until the user completes the step-up or the workflow's configured timeout is reached. Route the user to your fallback flow if the step-up does not complete.
