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

# IDV Module

> Complete reference for the IDV (Identity Verification) module

## Overview

The IDV (Identity Verification) module provides an integrated document capture and biometric verification flow through third-party provider integrations. It manages the complete identity verification process with minimal configuration required.

## Consent Requirement

<Warning>
  **Consent must be collected before mounting the IDV flow.** Without consent, verification submission will fail. Use the [Form Module](/docs/sdk-reference/form-module) CONSENT screen to collect consent from the user before calling `idv.mount()`. See the [IDV Flow guide](/docs/embedded-flows/idv) for a complete example.
</Warning>

## Accessing the Module

The IDV module is accessed through the SDK's flow factory:

```javascript theme={null}
const sdk = await OneSdk({
  mode: 'production',
  session: { token: 'your-token' }
});

// Create IDV flow instance
const idvFlow = sdk.flow('idv', options);
```

## Supported Providers

The IDV module supports multiple identity verification providers:

| Provider | Value      | Learn More                       |
| -------- | ---------- | -------------------------------- |
| Onfido   | `'onfido'` | [onfido.com](https://onfido.com) |
| Sumsub   | `'sumsub'` | [sumsub.com](https://sumsub.com) |
| Incode   | `'incode'` | [incode.com](https://incode.com) |
| Truuth   | `'truuth'` | [truuth.id](https://truuth.id)   |
| Daon     | `'daon'`   | [daon.com](https://www.daon.com) |

<Note>
  Each provider has different capabilities, UI/UX, supported documents, and geographic coverage. Visit the provider's website to understand their specific features and limitations.
</Note>

***

## Configuration Options

### Basic Configuration

```javascript theme={null}
const idvFlow = sdk.flow('idv', {
  provider: {
    name: 'onfido'
  }
});
```

### Common Options

In addition to provider-specific settings, you can configure:

| Option                | Type     | Description                                                                |
| --------------------- | -------- | -------------------------------------------------------------------------- |
| `documents`           | `array`  | Array of document configurations specifying types and countries (optional) |
| `checkProcessingPool` | `object` | Configure check processing polling behavior (optional)                     |

**Documents Array:**

```javascript theme={null}
documents: [
  {
    type: 'DRIVERS_LICENCE',     // Document type
    countries: ['AUS', 'NZL']    // ISO country codes (optional)
  }
]
```

<Callout icon="bell" color="#FFCA16" iconType="regular">
  **Daon provider:** The `documents` parameter and document selection are not required when using the Daon provider — Daon provides its own document type selection screen. To use custom document selection instead of Daon's built-in screen, contact your FrankieOne account team.
</Callout>

**Check Processing Pool:**

```javascript theme={null}
checkProcessingPool: {
  enabled: true,      // Enable polling for check results
  wait_time: 5,       // Wait time between polls (seconds)
  max_attempts: 1     // Maximum polling attempts
}
```

### Provider-Specific Options

#### Onfido Provider

```javascript theme={null}
const idvFlow = sdk.flow('idv', {
  provider: {
    name: 'onfido',
    sdkVersion: '13.0.0',          // Onfido SDK version
    theme: 'light',                 // 'light' or 'dark'
    language: 'en_GB',              // UI language (optional)
    translations: {                 // Custom translation strings (optional)
      // See Onfido documentation for translation keys
    },
    maxDocumentCount: 3,            // Maximum documents to capture
    product: 'idv',                 // Product type
    biometricsVariant: 'standard',  // 'standard', 'video', or 'motion'
    useOneStep: false,              // Enable one-step capture
    showExitButton: true,           // Show exit button in UI
    fallback: 'standard',           // Fallback method: 'standard' or 'video'
    crossDevicePolicy: 'disable',   // Cross-device flow: 'force' or 'disable'
    customUI: {                     // Custom UI configuration
      // See Onfido documentation for customUI options
    }
  }
});
```

**Onfido Options:**

| Option              | Type                    | Description                                                                                                                                                                                                                                                                                                                     |
| ------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sdkVersion`        | `string`                | Version of the Onfido SDK to use. Default: `'12'`. Refer to the [Onfido documentation](https://documentation.onfido.com/sdk/changelog/) for available versions.                                                                                                                                                                 |
| `theme`             | `'light' \| 'dark'`     | UI theme                                                                                                                                                                                                                                                                                                                        |
| `language`          | `string`                | Language code for the Onfido UI. Requires `sdkVersion` 14 or later. When `useOneStep` is `false`, this is forwarded to both the OCR and Biometrics sub-components. See supported values below.                                                                                                                                  |
| `translations`      | `object`                | Custom translation strings to override default Onfido copy. Keys must match Onfido's translation key schema — see the [Onfido language customisation docs](https://documentation.onfido.com/sdk/web/#language-customisation). Requires `sdkVersion` 14 or later. Also forwarded to sub-components when `useOneStep` is `false`. |
| `maxDocumentCount`  | `number`                | Maximum number of documents to capture                                                                                                                                                                                                                                                                                          |
| `product`           | `'idv'`                 | Product type (always `'idv'` for IDV module)                                                                                                                                                                                                                                                                                    |
| `biometricsVariant` | `string`                | Biometric capture variant: `'standard'`, `'video'`, or `'motion'`                                                                                                                                                                                                                                                               |
| `useOneStep`        | `boolean`               | Enable one-step capture workflow                                                                                                                                                                                                                                                                                                |
| `showExitButton`    | `boolean`               | Display exit button in the UI                                                                                                                                                                                                                                                                                                   |
| `fallback`          | `'standard' \| 'video'` | Fallback biometric method                                                                                                                                                                                                                                                                                                       |
| `crossDevicePolicy` | `'force' \| 'disable'`  | Enable/disable cross-device flow                                                                                                                                                                                                                                                                                                |
| `customUI`          | `object`                | Custom UI configuration object                                                                                                                                                                                                                                                                                                  |

**Supported `language` values:**

`ar`, `bg`, `cs`, `da`, `de`, `el`, `en_GB`, `en_US`, `es`, `es_419`, `es_DO`, `et`, `fa`, `fi`, `fr`, `fr_CA`, `he`, `hi`, `hr`, `hu`, `hy`, `id`, `it`, `ja`, `ko`, `lt`, `lv`, `ms`, `nl`, `no`, `pl`, `pt`, `pt_BR`, `ro`, `ru`, `sk`, `sl`, `sr`, `sv`, `th`, `tr`, `uk`, `vi`, `zh_CN`, `zh_TW`

***

#### Incode Provider

```javascript theme={null}
const idvFlow = sdk.flow('idv', {
  provider: {
    name: 'incode',
    product: 'idv',
    lang: 'en'  // Language code
  }
});
```

**Incode Options:**

| Option    | Type     | Description                                                          |
| --------- | -------- | -------------------------------------------------------------------- |
| `product` | `'idv'`  | Product type (required)                                              |
| `lang`    | `string` | Language code (e.g., `'en'`, `'es'`, `'fr'`, `'de'`, `'pt'`, `'zh'`) |

**Supported Languages:**
`'bn'`, `'ca'`, `'zh'`, `'hr'`, `'nl'`, `'en'`, `'en-BZ'`, `'en-DG'`, `'fr'`, `'de'`, `'ht'`, `'hi'`, `'hmn'`, `'hu'`, `'id'`, `'it'`, `'ms'`, `'pl'`, `'pt'`, `'pt-BR'`, `'pt-PT'`, `'ro'`, `'sr'`, `'sr-LATN'`, `'so'`, `'es'`, `'es-ES'`, `'tl-PH'`, `'tr'`, `'vi'`

***

#### Sumsub Provider

```javascript theme={null}
const idvFlow = sdk.flow('idv', {
  provider: {
    name: 'sumsub',
    product: 'idv',  // or 'poa' for proof of address
    config: {
      theme: 'light',  // 'light' or 'dark'
      lang: 'en',      // Language code (optional)
      email: 'user@example.com',  // Pre-fill email (optional)
      phone: '+1234567890'        // Pre-fill phone (optional)
    },
    options: {
      addViewportTag: true,      // Add viewport meta tag
      adaptIframeHeight: true    // Auto-adjust iframe height
    }
  }
});
```

**Sumsub Options:**

| Option    | Type             | Description                                                                     |
| --------- | ---------------- | ------------------------------------------------------------------------------- |
| `product` | `'idv' \| 'poa'` | Product type: `'idv'` for identity verification or `'poa'` for proof of address |
| `config`  | `object`         | Sumsub configuration object (see Config table below)                            |
| `options` | `object`         | Sumsub SDK options (see Options table below)                                    |

**Sumsub Config Object:**

| Property | Type                | Required | Description                                  |
| -------- | ------------------- | -------- | -------------------------------------------- |
| `theme`  | `'dark' \| 'light'` | Yes      | UI theme                                     |
| `lang`   | `string`            | No       | Language code (e.g., `'en'`, `'es'`, `'fr'`) |
| `email`  | `string`            | No       | Pre-fill user's email address                |
| `phone`  | `string`            | No       | Pre-fill user's phone number                 |

**Sumsub Options Object:**

| Property            | Type      | Required | Description                                   |
| ------------------- | --------- | -------- | --------------------------------------------- |
| `addViewportTag`    | `boolean` | Yes      | Whether to add viewport meta tag to page      |
| `adaptIframeHeight` | `boolean` | Yes      | Whether to automatically adjust iframe height |

***

#### Truuth Provider

```javascript theme={null}
const idvFlow = sdk.flow('idv', {
  provider: {
    name: 'truuth',
    sdkVersion: '1.0.0'  // Optional SDK version
  }
});
```

**Truuth Options:**

| Option       | Type     | Description                                                                                               |
| ------------ | -------- | --------------------------------------------------------------------------------------------------------- |
| `sdkVersion` | `string` | Version of the Truuth SDK to use. Default: `'1.0'`. Refer to Truuth documentation for available versions. |

***

#### Daon Provider

```javascript theme={null}
const idvFlow = sdk.flow('idv', {
  provider: {
    name: 'daon',
    products: ['IdentityX', 'VeriFLY'],  // Daon products to use
    processInstanceParameters: [
      {
        name: 'param1',
        mandatory: true,
        default: 'value'
      }
    ]
  }
});
```

***

## Methods

### `mount()`

Mounts the IDV component to a DOM element and starts the verification flow.

**Signature:**

```typescript theme={null}
mount(domElementOrSelector: string | HTMLElement): void
```

**Parameters:**

| Parameter              | Type                    | Required | Description                                                                                              |
| ---------------------- | ----------------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `domElementOrSelector` | `string \| HTMLElement` | Yes      | CSS selector string (e.g., `'#idv-container'`) or HTMLElement object where the component will be mounted |

**Description:**
Mounts the IDV Smart UI to the specified DOM element and initiates the identity verification flow. The provider's interface will be displayed within this element.

**Example:**

```javascript theme={null}
// Mount to element by ID
idvFlow.mount('#idv-container');

// Mount to element reference
const container = document.getElementById('idv-container');
idvFlow.mount(container);
```

***

### `unmount()`

Unmounts the IDV component from the DOM.

**Signature:**

```typescript theme={null}
unmount(): void
```

**Description:**
Removes the IDV component from the DOM and cleans up resources. Call this when the user navigates away or the verification flow is complete.

**Example:**

```javascript theme={null}
idvFlow.unmount();
```

***

### `isPreloaded()`

Checks if IDV data has been previously captured for this entity.

**Signature:**

```typescript theme={null}
isPreloaded(): boolean
```

**Returns:** `boolean` - `true` if IDV verification data exists for this entity, `false` otherwise

**Description:**
Returns `true` if the entity has existing IDV verification data (indicated by an attestation document). This allows you to skip the verification flow for returning users who have already completed identity verification.

The method checks:

1. Whether the individual module has preloaded data
2. Whether the entity has an attestation document (indicating completed IDV verification)

**Example:**

```javascript theme={null}
const idvFlow = sdk.flow('idv', {
  provider: { name: 'onfido' }
});

if (idvFlow.isPreloaded()) {
  console.log('User has completed IDV verification');
  // Skip verification, proceed to next step
  proceedToNextStep();
} else {
  console.log('User needs to complete IDV verification');
  // Mount and start verification
  idvFlow.mount('#idv-container');
}
```

**Use Cases:**

* Skip verification UI for returning users with completed IDV
* Show different messaging for users with existing verification
* Conditionally render verification components based on verification status

<Warning>
  This method checks for the presence of verification data, not the verification result. A user may have completed verification but failed checks. Always verify the actual verification status through your backend before granting access.
</Warning>

***

### `access()`

Accesses reactive data accessors for the IDV component state.

**Signature:**

```typescript theme={null}
access(fieldName: string): Accessor
```

**Returns:** Currently returns `void` (not implemented)

**Note:** This method is present for API consistency but is not yet implemented for the IDV module.

***

### `statuses`

Object containing all possible IDV status constants.

**Type:** `Readonly<typeof IDVStatus>`

**Description:**
Provides access to IDV status enum values for comparison in event handlers and status checks.

**Available Statuses:**

<Note>
  **Provider-Specific:** Not all statuses are used by all providers. The specific statuses emitted depend on your chosen verification provider's workflow and capabilities.
</Note>

| Status                  | Value                                     | Description                                           |
| ----------------------- | ----------------------------------------- | ----------------------------------------------------- |
| `CHECK_NOT_STARTED`     | `'CHECK_NOT_STARTED'`                     | Verification check has not been initiated             |
| `CHECK_PROCESSING`      | `'CHECK_PROCESSING'`                      | Verification check is currently processing            |
| `COMPLETE`              | `'COMPLETE'`                              | Verification completed successfully                   |
| `FAILED`                | `'FAILED'`                                | Verification failed                                   |
| `INCOMPLETE`            | `'INCOMPLETE'`                            | Verification incomplete (missing data or steps)       |
| `DOCUMENTS_INVALID`     | `'AWAITING_DOCUMENT_UPLOAD_INVALID_TYPE'` | Provided documents are invalid                        |
| `PROVIDER_OFFLINE`      | `'PROVIDER_OFFLINE'`                      | Verification provider is offline/unavailable          |
| `AWAITING_CONSENT`      | `'AWAITING_CONSENT'`                      | Waiting for user consent                              |
| `WAITING_SELFIE_UPLOAD` | `'WAITING_SELFIE_UPLOAD'`                 | Waiting for selfie/biometric upload                   |
| `WAITING_DOC_UPLOAD`    | `'WAITING_DOC_UPLOAD'`                    | Waiting for document upload                           |
| `INTERRUPTED`           | `'INTERRUPTED'`                           | Verification flow was interrupted (provider-specific) |

**Status-to-Event Mapping:**

The `results` event only fires for terminal statuses. Non-terminal statuses surface through other events. The exact mapping varies by provider.

<Tabs>
  <Tab title="Default">
    Used by **Sumsub**, **Incode**, **Daon**, **Mastercard**, and **OcrLabs**. These providers call the backend `initProcess` endpoint after the vendor flow completes and map the returned status to events using the common mapping.

    | Status                  | Event            |
    | ----------------------- | ---------------- |
    | `COMPLETE`              | `results`        |
    | `FAILED`                | `results`        |
    | `INCOMPLETE`            | `input_required` |
    | `DOCUMENTS_INVALID`     | `input_required` |
    | `WAITING_SELFIE_UPLOAD` | `input_required` |
    | `WAITING_DOC_UPLOAD`    | `input_required` |
    | `INTERRUPTED`           | `input_required` |
    | `PROVIDER_OFFLINE`      | `error`          |
    | `AWAITING_CONSENT`      | `error`          |
    | `CHECK_PROCESSING`      | `processing`     |

    <Note>
      **Daon** enables check processing polling by default. If the initial status is not `COMPLETE` or `FAILED`, the SDK polls the backend until a terminal status is reached, then emits `results`.
    </Note>
  </Tab>

  <Tab title="Onfido">
    Onfido does **not** use the common status mapping. Instead, it delegates to internal OCR and Biometrics sub-modules, which emit events directly.

    **Two-step mode (default):** The IDV module creates separate OCR and Biometrics components. Events from each sub-component (`results`, `input_required`, `error`, `detection_complete`, `detection_failed`) are forwarded to the IDV event hub. The status values in these events come from the sub-modules' own processing.

    **One-step mode** (`useOneStep: true`)**:** The Onfido SDK handles both document and face capture in a single flow. On completion, the biometrics `initProcess` is called. Its mapping differs from the default:

    | Status                  | Event        |
    | ----------------------- | ------------ |
    | `COMPLETE`              | `results`    |
    | `FAILED`                | `results`    |
    | `DOCUMENTS_INVALID`     | `error`      |
    | `WAITING_DOC_UPLOAD`    | `error`      |
    | `WAITING_SELFIE_UPLOAD` | `error`      |
    | `PROVIDER_OFFLINE`      | `error`      |
    | `AWAITING_CONSENT`      | `error`      |
    | `CHECK_PROCESSING`      | `processing` |

    In one-step mode, if the user exits, `input_required` is emitted with `INTERRUPTED` status, along with `detection_failed` and `session_interrupted`.

    <Note>
      **Secondary error on SDK failure (one-step mode):** If the Onfido SDK itself reports an error (its `onError` callback), OneSDK emits an `error` event for that SDK failure, then automatically re-triggers the biometrics `initProcess` call to attempt to resolve the check. If that retry also fails, a **second** `error` event is emitted for the `initProcess` failure. Listeners should not assume a single `error` event per failed attempt in one-step mode — up to two `error` events can fire in sequence for the same user action.
    </Note>
  </Tab>

  <Tab title="Truuth">
    Truuth has its own status interpretation based on the provider's `userBehaviourChecks` response. It emits `input_required` directly for non-complete statuses **before** calling the backend, treating them as recoverable conditions.

    | Status                  | Event                                              |
    | ----------------------- | -------------------------------------------------- |
    | `COMPLETE`              | `results` (via common mapping after `initProcess`) |
    | `FAILED`                | `results` (via common mapping after `initProcess`) |
    | `INCOMPLETE`            | `input_required`                                   |
    | `AWAITING_CONSENT`      | `input_required`                                   |
    | `WAITING_DOC_UPLOAD`    | `input_required`                                   |
    | `WAITING_SELFIE_UPLOAD` | `input_required`                                   |
    | `INTERRUPTED`           | `input_required`                                   |
    | `CHECK_PROCESSING`      | `processing` (via polling)                         |

    <Note>
      Unlike other providers, Truuth maps `AWAITING_CONSENT` to `input_required` rather than `error`, treating consent rejection as a recoverable user action. Truuth also enables check processing polling when the vendor reports processing has started.
    </Note>
  </Tab>
</Tabs>

**Example:**

```javascript theme={null}
const idvFlow = sdk.flow('idv', { provider: { name: 'onfido' } });

idvFlow.on('input_required', (info, status) => {
  if (status === idvFlow.statuses.WAITING_DOC_UPLOAD) {
    console.log('Waiting for document upload');
  } else if (status === idvFlow.statuses.WAITING_SELFIE_UPLOAD) {
    console.log('Waiting for selfie upload');
  }
});

idvFlow.on('results', (results) => {
  if (results.checkStatus === idvFlow.statuses.COMPLETE) {
    console.log('Verification completed successfully');
  } else if (results.checkStatus === idvFlow.statuses.FAILED) {
    console.log('Verification failed');
  }
});
```

***

## Events

The IDV module emits events throughout the verification lifecycle.

<Warning>
  **Provider-Specific Behavior:** Events and statuses vary by provider. Not all providers emit all events, and some events are provider-specific. Always test with your chosen provider to understand which events are emitted and when.
</Warning>

### `session_data_generated`

Emitted when session data for the vendor is generated.

**Arguments:**

```typescript theme={null}
{
  session: {
    entityId: string | null;
    vendorParameters: object;
  }
}
```

**Example:**

```javascript theme={null}
idvFlow.on('session_data_generated', ({ session }) => {
  console.log('Session created for entity:', session.entityId);
  console.log('Vendor parameters:', session.vendorParameters);
});
```

***

### `detection_complete`

Emitted when initial detection/capture is complete.

**Arguments:** None

**Example:**

```javascript theme={null}
idvFlow.on('detection_complete', () => {
  console.log('Document and biometric capture complete');
  showProcessingMessage();
});
```

***

### `detection_failed`

Emitted when detection/capture fails.

**Arguments:**

```typescript theme={null}
{
  message: string;
  payload?: Record<string, unknown>;
}
```

**Example:**

```javascript theme={null}
idvFlow.on('detection_failed', ({ message, payload }) => {
  console.error('Detection failed:', message);
  console.error('Details:', payload);
  showErrorMessage(message);
});
```

***

### `input_required`

Emitted when a non-positive flow has occurred but is likely recoverable by retrying.

**Arguments:**

```typescript theme={null}
(
  info: { entityId: string | null },
  status: IDVStatus
)
```

**Description:**
Emitted when the check could not be completed due to user input — not because of a system failure. For example, the user uploaded the wrong document type, or the user closed the session before completing it. Retrying the step will always help resolve `input_required`.

Common scenarios:

* Waiting for document or selfie upload
* Awaiting user consent
* User closed or interrupted the verification session (remounting the module allows them to resume)

<Note>
  There is no way to differentiate between user abandonment and session timeout within the SDK. Both surface as `input_required` with `INTERRUPTED` status. Whether to limit retry attempts depends on your business process.
</Note>

**Example:**

```javascript theme={null}
idvFlow.on('input_required', ({ entityId }, status) => {
  console.log('Input required. Status:', status);
  console.log('User can retry to continue verification');

  if (status === idvFlow.statuses.WAITING_DOC_UPLOAD) {
    showMessage('Please upload your document to continue');
    enableRetry();
  } else if (status === idvFlow.statuses.WAITING_SELFIE_UPLOAD) {
    showMessage('Please capture your selfie to continue');
    enableRetry();
  } else if (status === idvFlow.statuses.AWAITING_CONSENT) {
    showMessage('Please provide consent to continue');
    enableRetry();
  }
});
```

***

### `processing`

Emitted when verification checks are processing.

**Arguments:**

```typescript theme={null}
{
  checkStatus: IDVStatus;
  entityId: string | null;
  [key: string]: any;
}
```

**Example:**

```javascript theme={null}
idvFlow.on('processing', (status) => {
  console.log('Processing verification. Status:', status.checkStatus);
  showLoadingSpinner();
});
```

***

### `results`

Emitted when verification reaches a terminal state. Only fires with `COMPLETE` or `FAILED` status. Other statuses surface through `input_required`, `error`, or `processing` events.

**Arguments:**

```typescript theme={null}
{
  checkStatus: IDVStatus;
  entityId: string | null;
  [key: string]: any;
}
```

**Example:**

```javascript theme={null}
idvFlow.on('results', (results) => {
  console.log('Verification results received');
  console.log('Status:', results.checkStatus);
  console.log('Entity ID:', results.entityId);

  if (results.checkStatus === idvFlow.statuses.COMPLETE) {
    navigateToSuccess();
  } else if (results.checkStatus === idvFlow.statuses.FAILED) {
    showFailureScreen(results);
  }
});
```

***

### `session_interrupted`

Emitted when the user interrupts the verification session.

**Arguments:** None

<Note>
  **Provider-Specific:**

  * **Onfido:** Emits this when the verification modal is closed.
</Note>

**Example:**

```javascript theme={null}
// Onfido-specific event
idvFlow.on('session_interrupted', () => {
  console.log('User interrupted the verification (Onfido)');
  saveProgress();
});
```

***

### `session_closed`

Emitted when the verification session is closed.

**Arguments:** None

**Example:**

```javascript theme={null}
idvFlow.on('session_closed', () => {
  console.log('Verification session closed');
  idvFlow.unmount();
});
```

***

### `session_data_failed_loading`

Emitted when session data fails to load.

**Arguments:** None

**Example:**

```javascript theme={null}
idvFlow.on('session_data_failed_loading', () => {
  console.error('Failed to load session data');
  showErrorMessage('Unable to start verification. Please try again.');
});
```

***

### `vendor_event`

Emitted for provider-specific events.

**Arguments:**

```typescript theme={null}
{
  [key: string]: any;  // Provider-specific event data
}
```

**Example:**

```javascript theme={null}
idvFlow.on('vendor_event', (event) => {
  console.log('Provider event:', event);
  // Handle provider-specific events
});
```

<Note>
  **Truuth:** `vendor_event` payloads are `{ provider: 'truuth', vendorEventType }` — the raw event `payload` (which could contain PII from the vendor SDK) is intentionally not included. If your integration previously relied on fields from the Truuth event payload, read them from the `results` event or your backend API instead.
</Note>

***

### Common Events

The IDV module also emits common events inherited from the event system:

* `error` - When an error occurs
* `warning` - For non-critical warnings
* `info` - Informational messages
* `loading` - Loading state changes

See [Event System Reference](/docs/sdk-reference/events) for details.

***

## Complete Example

```javascript theme={null}
import OneSdk from '@frankieone/one-sdk';

async function performIDV() {
  try {
    // Initialize SDK
    const sdk = await OneSdk({
      mode: 'production',
      session: { token: await getSessionToken() }
    });

    // Create IDV component with Onfido provider
    const idvFlow = sdk.flow('idv', {
      provider: {
        name: 'onfido',
        theme: 'light',
        product: 'idv',
        biometricsVariant: 'standard',
        showExitButton: true
      }
    });

    // Check if user has already completed IDV
    if (idvFlow.isPreloaded()) {
      console.log('User has existing IDV verification data');
      // Skip verification for returning user
      return navigateToNextStep();
    }

    // Set up event listeners
    idvFlow.on('session_data_generated', ({ session }) => {
      console.log('IDV session started for:', session.entityId);
    });

    idvFlow.on('detection_complete', () => {
      console.log('Capture complete, processing...');
      showMessage('Processing your verification...');
    });

    idvFlow.on('detection_failed', ({ message }) => {
      console.error('Capture failed:', message);
      showError(message);
    });

    idvFlow.on('processing', (status) => {
      console.log('Verification processing:', status.checkStatus);
    });

    idvFlow.on('results', (results) => {
      console.log('Verification complete');

      if (results.checkStatus === idvFlow.statuses.COMPLETE) {
        console.log('✓ Verification passed');
        navigateToSuccess();
      } else if (results.checkStatus === idvFlow.statuses.FAILED) {
        console.log('✗ Verification failed');
        showFailureScreen();
      } else {
        console.log('Status:', results.checkStatus);
        handleOtherStatus(results);
      }
    });

    idvFlow.on('session_interrupted', () => {
      console.log('User closed verification');
      saveProgress();
    });

    idvFlow.on('error', (error) => {
      console.error('IDV error:', error);
      showError('Verification error. Please try again.');
    });

    // Mount and start verification
    idvFlow.mount('#idv-container');

  } catch (error) {
    console.error('IDV initialization failed:', error);
    throw error;
  }
}
```

***

## Best Practices

1. **Handle all events, not just `results`** - The `results` event only fires with `COMPLETE` or `FAILED`. Also listen to `input_required` (for recoverable states like INCOMPLETE or INTERRUPTED), `error` (for system failures such as PROVIDER\_OFFLINE), and `processing` (for intermediate states).

2. **Set up event listeners before mounting** - Register all event handlers before calling `mount()` to avoid missing events.

3. **Unmount on navigation** - Always call `unmount()` when the user leaves the page to clean up resources.

4. **Provider-specific configuration** - Review each provider's documentation for optimal configuration.

5. **Error handling** - Always listen to the `error` event and provide user-friendly error messages.

***

## Common Issues

### Component not displaying

Ensure the mount element exists in the DOM and has sufficient size:

```css theme={null}
#idv-container {
  width: 100%;
  min-height: 600px;
}
```

### Session data failed to load

This usually means the backend session setup failed. Ensure your backend is correctly generating IDV tokens.

### Provider-specific errors

Check the `vendor_event` emissions for provider-specific error details and consult the provider's documentation.

***

## Related

* [SDK Initialization](/docs/sdk-reference/sdk-initialization)
* [Individual Module](/docs/sdk-reference/individual-module)
* [Event System](/docs/sdk-reference/events)
* [Component System](/docs/sdk-reference/components)
