# Verification links

Verification links are single-use or time-limited URLs through which a user starts verification. You create links through the Tenant API or the admin panel and deliver them to the user (by email, SMS, QR code, or in your customer portal). When the user opens the link, a verification session is automatically created or attached, and the user is redirected to the OneKYC verification page.

## Create a verification link [#create-a-verification-link]

API operations:

- `POST /v1/kyc/verification-links`

### Identity and unresolved review [#identity-and-unresolved-review]

`external_user_id` identifies an applicant within a tenant; it is not a session ID. Multiple historical sessions may belong to one applicant. Journey reuse is scoped by tenant, environment, external user ID, flow, and KYC/KYB entity type.

If that scoped identity already has an unresolved manual review, creating a fresh link returns HTTP `409` with `error.code = "session_review_pending"` and `error.existing_session_id`. Finish the existing review or use its resubmit action. Expiration of a link does not resolve a pending reviewer decision. Link duplication and activation of a previously created fresh link cannot bypass this check.

For a session still in progress, normal link creation continues to reuse that session. A final approved/declined decision permits a later independent verification. `external_reference` only reuses an eligible active link when the supplied `external_user_id` is empty or matches the link; a different external user receives an independent link. It is not a lifetime session-deduplication key. Batch creation reports review conflicts per item.

Correlate webhook outcomes by `session_id` as well as `external_id`. A historical session's later reviewer decision is an outcome for that historical session; it must not silently overwrite the result of another session solely because the external ID matches.

### Legacy compatibility [#legacy-compatibility]

The canonical KYC path is `/tenant/v1/kyc/verification-links`. For existing tenant integrations, OneKYC also intentionally keeps `/tenant/v1/verification-links` and `/tenant/v1/verificationLinks` as KYC aliases. Verification-link create and batch-create request bodies also accept legacy field aliases with different casing or separators, such as `flowId`, `FlowID`, `externalUserId`, `redirectUrl`, and `prefilledData`.

Do not treat these aliases as dead code. They are a supported compatibility contract and may be removed only after a separately versioned Tenant API deprecation and migration window.

## Batch create links [#batch-create-links]

Creates several verification links in a single request.

API operations:

- `POST /v1/kyc/verification-links/batch`

## List links [#list-links]

API operations:

- `GET /v1/kyc/verification-links`

## Get a link by ID [#get-a-link-by-id]

API operations:

- `GET /v1/kyc/verification-links/{id}`

## Revoke a link [#revoke-a-link]

A revoked link becomes invalid and cannot be used to start verification.

API operations:

- `POST /v1/kyc/verification-links/{id}/revoke`

## Get a QR code [#get-a-qr-code]

Returns the QR code for a verification link. Use it for the cross-device flow: the user scans the QR code on a mobile device and continues verification there.

API operations:

- `GET /v1/kyc/verification-links/{id}/qr`

---

## Link lifecycle [#link-lifecycle]

```
[Created] → [Activated] → [Consumed]
    ↓            ↓            ↓
[Expired]   [Expired]   [Completed]
    ↓            ↓
[Revoked]   [Revoked]
```

**Link statuses:**

| Status      | Description                                                            |
| ----------- | ---------------------------------------------------------------------- |
| `active`    | Link created; the user has not opened it yet                           |
| `activated` | The user opened the link; a session was created and verification is in progress |
| `consumed`  | Verification completed (approved, rejected, or routed to review)       |
| `expired`   | The link's TTL (`ttl_seconds`) elapsed; the link is no longer usable   |
| `revoked`   | The link was revoked manually through the API or the admin panel       |

> **Note.** After creating the link, deliver it to the user (by email, SMS, or QR code). Opening the link automatically creates a verification session. For the cross-device flow, use the QR code (`GET /v1/kyc/verification-links/{id}/qr`).

---

## Redirect after verification completes [#redirect-after-verification-completes]

When you create a link, you can pass the **redirect_url** parameter — the URL the user is redirected to once verification completes (for example, a customer portal or an application form).

### How it works [#how-it-works]

1. **When creating the link**, pass `redirect_url` in the request body (`POST /v1/kyc/verification-links` or batch).
2. **On activation**, `redirect_url` is stored in the session and returned in the activation response (the `redirect_url` field).
3. **On the completion screen** (after approval, rejection, or routing to review) the user sees:
   - a **return button** — the user clicks it and is redirected to `redirect_url`; or
   - an **automatic redirect** after a configured delay.

### Configuring behaviour [#configuring-behaviour]

Redirect behaviour is set in the **flow parameters** in the admin panel:

- **Redirect behaviour on completion** — redirect mode: "Show button" or "Auto redirect".
- **Redirect delay (seconds)** — delay before the automatic redirect (applies when "Auto redirect" is selected).

Defaults: button is shown; automatic mode delay is 3 seconds. For details, see [Flows (admin)](/en/admin/flows#redirect-settings).
