> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.idenfy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dual Verification Flow

> Run a silent second identity check on documents your user uploads during their first verification — no second UI session required.

<Note>
  **Requirements:**

  * API key pair
  * **Direct Processing** enabled on your contract (contact iDenfy)
  * **Custom Additional Steps** enabled on your account (contact iDenfy)
  * Additional step credits
</Note>

***

## Overview

This pattern lets you verify two different identity documents from the same user while only showing them one verification UI. The user completes the standard flow and uploads the second document as a custom additional step. Your backend then silently runs a second verification on those files via direct processing — no second session for the user.

Both verifications are linked by the same `clientId` and each produces its own webhook result.

<Accordion title="Flow diagram">
  ```mermaid theme={"system"}
  %%{init: {'theme': 'base', 'themeVariables': {'fontFamily': 'Inter, sans-serif', 'fontSize': '11px', 'primaryColor': '#734BFB', 'primaryTextColor': '#ffffff', 'primaryBorderColor': '#5A2FE0', 'lineColor': '#9B7BFC', 'edgeLabelBackground': '#5A2FE0', 'edgeTextColor': '#ffffff'}}}%%
  flowchart TB
      subgraph r1[" "]
          direction LR
          A("`Create Token 1`") --> B("`Send verification link`") --> C("`User completes verification
  & uploads extra document`") --> D("`Webhook received`")
      end
      subgraph r2[" "]
          direction LR
          E{{"`Verification **APPROVED** and additional steps completed?`"}} -->|Yes| F("`Download files
  1-hour window`") --> G("`Create Token 2
  same **clientId**`") --> H("`**POST /api/v2/process**
  auto-detects doc type`") --> I("`Second webhook
  verification complete`")
      end
      D --> E
      E -->|No| Z("`Stop`")

      classDef step fill:#734BFB,stroke:#5A2FE0,color:#ffffff
      classDef user fill:#9B7BFC,stroke:#734BFB,color:#ffffff
      classDef decision fill:#5A2FE0,stroke:#4c1d95,color:#ffffff
      classDef stop fill:#ef4444,stroke:#dc2626,color:#ffffff
      classDef done fill:#22c55e,stroke:#16a34a,color:#ffffff

      class A,B,D,F,G,H step
      class C user
      class E decision
      class Z stop
      class I done

      style r1 fill:none,stroke:none
      style r2 fill:none,stroke:none
  ```
</Accordion>

***

## Step 1 — Create Token 1 (User-Facing)

Token 1 needs a custom additional step that prompts the user to upload the extra document(s). The simplest setup is to have iDenfy support configure this as a **default on your account** — it then applies automatically to every session without any extra parameters in the token request.

If you need per-request control instead (for example, to apply the step only on certain sessions), you can pass the `additionalSteps` object yourself when creating the token. See [Additional Steps](/kyc/additional-steps#managing-custom-additional-steps-per-request) for the full structure and options.

Save the `scanRef` from the response — you'll use it to match the incoming webhook. For all token parameters, see [Create Verification Session](/kyc/generate-token).

***

## Step 2 — Send the User to Verification

Redirect the user using the `authToken` from the Token 1 response. They complete the standard flow and then see the additional upload step(s) at the end.

See [iFrame / Redirect](/kyc/iframe-redirect) for integration options.

***

## Step 3 — Receive Webhook and Download Files

When the user finishes, your configured `callbackUrl` receives a webhook. Before proceeding, confirm two things:

1. **The main verification was approved** — check `status.overall`. Do not trigger the second verification if the primary identity check failed.

2. **The additional step was completed successfully** — check `status.additionalSteps`. This is independent of the main result: a user can pass the identity check but still fail or skip the extra upload. Only proceed if both statuses are positive.

Then download the files:

| Field                    | What it contains                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------- |
| `additionalSteps`        | Map of step name → processing type, confirms which steps were completed                           |
| `status.additionalSteps` | `"Additional step is valid"` / `"Additional step is invalid"` / `"Additional step was not found"` |
| `fileUrls`               | Pre-signed download URLs for image files, keyed by step name                                      |
| `additionalStepPdfUrls`  | Pre-signed download URLs for PDF files, keyed by step name                                        |

For the full webhook payload structure and all status fields, see [KYC Webhooks](/kyc/webhooks).

***

## Step 4 — Create Token 2 (Silent)

Create a second token using the **same `clientId`** to link it to the same person. This token is never shown to the user — it exists only to authorize the direct processing call.

If your account has custom additional steps configured as a default, **disable them explicitly** on Token 2 by passing an empty `additionalSteps` object. The recommended approach here is to have iDenfy support configure the step as your account default and suppress it only for Token 2 this way:

```json theme={"system"}
{
  "clientId": "user-123",
  "tokenType": "DOCUMENT",
  "additionalSteps": {
    "ALL": {
      "ALL": {}
    }
  }
}
```

See [Additional Steps → Verification Without Custom Additional Step](/kyc/additional-steps#verification-without-custom-additional-step) for details on the suppression syntax.

Additional points:

* **No `successUrl` / `errorUrl`** — no one is watching this flow.
* **No questionnaire** — direct processing is incompatible with KYC questionnaires. If your account attaches them by default, set `"questionnaire": null`.

Save the `authToken` and `scanRef` from the response.

***

## Step 5 — Submit via Direct Processing

Convert the files you downloaded in Step 3 to base64 and submit them to the direct processing endpoint using Token 2's `authToken`. Omit `documentType` — the system automatically detects the document type from the `FRONT` image. This means you can fully automate the second verification without knowing in advance what document the user uploaded.

```json theme={"system"}
{
  "token": "<authToken from Token 2>",
  "country": "LT",
  "images": {
    "FRONT": "<base64-encoded front image>",
    "BACK": "<base64-encoded back image>"
  }
}
```

A `200 OK` with no body means the request was accepted. Processing runs asynchronously and the result is delivered via a second webhook to your `callbackUrl`. Use the `scanRef` from Token 2 to identify which webhook belongs to which verification.

For the full endpoint reference, parameters, and error handling, see [Direct Processing](/kyc/direct-processing).

***

## Tips

**Check both statuses before proceeding**
Only trigger the direct processing step after confirming both `status.overall` (main verification approved) and `status.additionalSteps` (document uploaded successfully). A passing identity check does not guarantee the additional step was completed.

**File URLs are valid for 1 hour**
The URLs in `fileUrls` and `additionalStepPdfUrls` are pre-signed and expire after one hour. Download the files as soon as the webhook arrives — do not store the URL and fetch it later.

**Token 2 must not have a questionnaire**
Direct processing rejects tokens with questionnaire answers attached. See the [Direct Processing conditions table](/kyc/direct-processing#conditions--rules) for the full list of token requirements.

**Token 1 cannot be reused**
The first token is deactivated the moment the user completes the flow. Create a fresh token (Token 2) for the direct processing call.
