> ## 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.

# OCR Module

> Complete reference for the OCR (Document Capture) module

## Overview

The OCR (Optical Character Recognition) module handles document capture and extraction of identity information from government-issued documents. It integrates with third-party OCR providers to capture document images and extract data such as name, date of birth, document number, and expiry date.

## Accessing the Module

The OCR module is accessed through the SDK's component factory:

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

// Create OCR component instance
const ocrComponent = sdk.component('ocr', options);
```

## Supported Providers

The OCR module supports multiple document capture 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)       |
| IDVerse  | `'idverse'` | [idverse.com](https://www.idverse.com) |
| Daon     | `'daon'`    | [daon.com](https://www.daon.com)       |

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

***

## Configuration Options

### Basic Configuration

```javascript theme={null}
const ocrComponent = sdk.component('ocr', {
  provider: {
    name: 'onfido'
  }
});
```

### Common Options

| Option             | Type      | Description                                                     |
| ------------------ | --------- | --------------------------------------------------------------- |
| `maxDocumentCount` | `number`  | Maximum number of documents to capture                          |
| `documents`        | `array`   | Array of document configurations specifying types and countries |
| `skipInitProcess`  | `boolean` | Skip initialization process (advanced use)                      |

**Documents Array Structure:**

```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>

***

### Provider-Specific Options

#### Onfido Provider

```javascript theme={null}
const ocrComponent = sdk.component('ocr', {
  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
    },
    showExitButton: true,            // Show exit button in UI
    crossDevicePolicy: 'disable',    // Cross-device flow: 'force' or 'disable'
    onUserExit: () => {              // Callback when user exits
      console.log('User exited');
    },
    customUI: {                      // Custom UI configuration
      // See Onfido documentation for customUI options
    }
  },
  documents: [
    { type: 'PASSPORT', countries: ['AUS'] }
  ]
});
```

**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. 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. |
| `showExitButton`          | `boolean`                                  | Display exit button in the UI                                                                                                                                                                                                                                    |
| `crossDevicePolicy`       | `'force' \| 'disable'`                     | Enable/disable cross-device flow                                                                                                                                                                                                                                 |
| `onUserExit`              | `() => void`                               | Callback function when user exits                                                                                                                                                                                                                                |
| `customUI`                | `object`                                   | Custom UI styling configuration (see Custom UI section below)                                                                                                                                                                                                    |
| `_crossDeviceLinkMethods` | `Array<'qr_code' \| 'copy_link' \| 'sms'>` | Cross-device sharing methods (internal)                                                                                                                                                                                                                          |

**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`

**Onfido Custom UI Properties:**

The `customUI` object allows extensive styling customization:

```javascript theme={null}
customUI: {
  // Typography
  fontWeightBody: 400,
  fontSizeBody: '16px',
  fontSizeSubtitle: '18px',
  fontSizeTitle: '24px',

  // Colors - Background
  colorBackgroundSurfaceModal: '#FFFFFF',
  colorBackgroundIcon: '#353FF4',
  colorBackgroundInput: '#FFFFFF',

  // Colors - Content/Text
  colorContentBody: '#475467',
  colorContentTitle: '#101828',
  colorContentSubtitle: '#344054',
  colorContentInput: '#101828',

  // Colors - Buttons (Primary)
  colorContentButtonPrimaryText: '#FFFFFF',
  colorBackgroundButtonPrimary: '#353FF4',
  colorBackgroundButtonPrimaryHover: '#2835E5',
  colorBackgroundButtonPrimaryActive: '#1F2AD1',

  // Colors - Buttons (Secondary)
  colorContentButtonSecondaryText: '#344054',
  colorBackgroundButtonSecondary: '#FFFFFF',
  colorBackgroundButtonSecondaryHover: '#F9FAFB',
  colorBackgroundButtonSecondaryActive: '#F2F4F7',

  // Colors - Buttons (Tertiary)
  colorContentButtonTertiaryText: '#344054',

  // Borders
  borderRadiusButton: '8px',
  borderStyleSurfaceModal: '1px solid #E4E7EC',
  colorBorderInput: '#D0D5DD',
  colorInputOutline: '#353FF4',

  // Additional UI elements
  colorIcon: '#667085',
  colorBackgroundInfoPill: '#F2F4F7',
  colorContentInfoPill: '#344054',
  // ... see Onfido documentation for full list
}
```

***

#### Incode Provider

```javascript theme={null}
const ocrComponent = sdk.component('ocr', {
  provider: {
    name: 'incode',
    sdkVersion: '1.0.0',         // SDK version
    lang: 'es',                  // UI language (optional)
    translations: {              // Custom translation strings (optional)
      // See Incode documentation for translation keys
    },
    numberOfTries: 3,            // Max capture attempts
    consentId: 'consent_123',    // Consent identifier
    renderCamera: {
      showDocSelector: true,     // Show document selector
      showTutorial: true         // Show tutorial screens
    }
  },
  documents: [
    { type: 'DRIVERS_LICENCE' }
  ]
});
```

**Incode Options:**

| Option          | Type             | Description                                                                                                                                                                                                    |
| --------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sdkVersion`    | `string`         | Version of the Incode SDK to use. Default: `'1.75.2'`. Refer to the [Incode documentation](https://docs.incode.com/docs/omni-web-sdk/release-notes) for available versions.                                    |
| `lang`          | `string`         | Language code for the Incode UI. See supported values below.                                                                                                                                                   |
| `translations`  | `object`         | Custom translation strings to override default Incode copy. See the [Incode language keys docs](https://documentation.identity.entrust.com/sdk/web/#identifying-language-keys) for available translation keys. |
| `numberOfTries` | `number`         | Maximum number of capture attempts                                                                                                                                                                             |
| `consentId`     | `string \| null` | Consent identifier for the session                                                                                                                                                                             |
| `renderCamera`  | `object`         | Camera rendering options (see below)                                                                                                                                                                           |

**Supported `lang` values:**

`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`

**renderCamera Options:**

| Option            | Type      | Description                    |
| ----------------- | --------- | ------------------------------ |
| `showDocSelector` | `boolean` | Display document type selector |
| `showTutorial`    | `boolean` | Display tutorial/instructions  |

***

#### Sumsub Provider

```javascript theme={null}
const ocrComponent = sdk.component('ocr', {
  provider: {
    name: 'sumsub',
    config: {
      theme: 'light',              // 'light' or 'dark'
      lang: 'en',                  // Language code
      email: 'user@example.com',   // Pre-fill email
      phone: '+1234567890'         // Pre-fill phone
    },
    options: {
      addViewportTag: true,        // Add viewport meta tag
      adaptIframeHeight: true      // Auto-adjust iframe height
    }
  }
});
```

**Sumsub Options:**

| Option    | Type     | Description                                                                                                                                    |
| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `config`  | `object` | Sumsub configuration (theme, lang, email, phone). See [IDV Module - Sumsub](/docs/sdk-reference/idv-module#sumsub-provider) for details.       |
| `options` | `object` | Sumsub SDK options (addViewportTag, adaptIframeHeight). See [IDV Module - Sumsub](/docs/sdk-reference/idv-module#sumsub-provider) for details. |

***

#### IDVerse Provider

```javascript theme={null}
const ocrComponent = sdk.component('ocr', {
  provider: {
    name: 'idverse',
    translations: {              // Custom translations (optional)
      // Language-specific strings
    },
    retryCount: 3,              // Max retry attempts
    skipLoad: false,            // Skip loading vendor SDK
    workerPathString: '/path',  // Worker script path
    assetPathString: '/assets'  // Asset files path
  }
});
```

**IDVerse Options:**

| Option             | Type      | Description                        |
| ------------------ | --------- | ---------------------------------- |
| `translations`     | `object`  | Custom translation strings         |
| `retryCount`       | `number`  | Maximum retry attempts             |
| `skipLoad`         | `boolean` | Skip loading vendor SDK (advanced) |
| `workerPathString` | `string`  | Path to worker script files        |
| `assetPathString`  | `string`  | Path to asset files                |

***

#### Daon Provider

```javascript theme={null}
const ocrComponent = sdk.component('ocr', {
  provider: {
    name: 'daon',
    products: ['IdentityX', 'VeriFLY'],  // Daon products to use
    processInstanceParameters: [
      {
        name: 'param1',
        mandatory: true,
        minimumLength: 1,
        maximumLength: 50,
        default: 'value'
      }
    ]
  }
});
```

**Daon Options:**

| Option                      | Type       | Description                                       |
| --------------------------- | ---------- | ------------------------------------------------- |
| `products`                  | `string[]` | Array of Daon product names to use                |
| `processInstanceParameters` | `array`    | Process instance parameters (see structure below) |

**Process Instance Parameters:**

| Property        | Type               | Description                     |
| --------------- | ------------------ | ------------------------------- |
| `name`          | `string`           | Parameter name                  |
| `mandatory`     | `boolean`          | Whether parameter is required   |
| `minimumLength` | `number`           | Minimum value length (optional) |
| `maximumLength` | `number`           | Maximum value length (optional) |
| `default`       | `string \| number` | Default value                   |

***

## Methods

### `mount()`

Mounts the OCR component to a DOM element.

**Signature:**

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

**Parameters:**

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

**Description:**
Mounts the OCR component to the specified DOM element. After mounting, call `start()` to begin the document capture process.

**Example:**

```javascript theme={null}
// Mount to element by ID - capture begins automatically
ocrComponent.mount('#ocr-container');

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

***

### `start()`

<Warning>
  **Legacy Method:** This method is for headless OCR integration and is not recommended for standard use. Modern provider integrations handle the capture flow automatically after mounting. Avoid using this method unless you have a specific headless integration requirement.
</Warning>

Starts the document capture process in headless mode.

**Signature:**

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

**Description:**
Initiates the document capture flow for headless OCR implementations. For standard provider integrations, the capture flow begins automatically when mounting.

***

### `unmount()`

Unmounts the OCR component from the DOM.

**Signature:**

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

**Description:**
Removes the OCR component from the DOM and cleans up resources. Call this when the user navigates away or document capture is complete.

**Example:**

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

***

### `isPreloaded()`

<Warning>
  **Not typically used:** `isPreloaded()` is not used in standard OCR integrations and can be safely ignored. Use events (`detection_complete`, `results`) to track document capture progress instead. This method was designed for legacy headless OCR flows.
</Warning>

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

**Signature:**

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

**Returns:** `boolean | null` - `true` if OCR data exists for this entity, `false` if not, `null` if unable to determine

**Description:**
Returns `true` if the entity has existing OCR/document data in local state. This method was designed for headless integrations where you need to check local state before rendering capture UI.

**For standard provider integrations**, document capture status should be determined by:

* Using the `results` event to receive capture completion status
* Querying your backend API for document verification results
* Checking entity status through the FrankieOne API

**Example:**

```javascript theme={null}
// ✅ Use events to track capture progress
ocrComponent.on('results', ({ document }) => {
  console.log('Document captured:', document);
  proceedToNextStep();
});

ocrComponent.mount('#ocr-container');
// Capture begins automatically
```

<Warning>
  This method only checks for the presence of document data in local state, not the actual verification result. Always verify document status through your backend API before proceeding with verification workflows.
</Warning>

***

### `access()`

<Warning>
  **Legacy Method:** This method is for headless OCR integration and is not recommended for standard use. For standard provider integrations, use events to track document capture progress instead of polling status. Avoid using this method unless you have a specific headless integration requirement.
</Warning>

Accesses reactive data accessors for the OCR component state.

**Signature:**

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

**Description:**
Provides access to internal OCR status for headless implementations. For standard provider integrations, listen to events (`detection_complete`, `results`, etc.) instead of polling status.

***

### `statuses`

Object containing all possible OCR status constants.

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

**Description:**
Provides access to OCR 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 provider's workflow and capabilities.
</Note>

| Status                    | Value                                      | Description                                      |
| ------------------------- | ------------------------------------------ | ------------------------------------------------ |
| `WAITING_OCR_RUN`         | `'AWAITING_DOCUMENT_OCR'`                  | Waiting for OCR processing to run                |
| `WAITING_BACK`            | `'AWAITING_DOCUMENT_UPLOAD_BACK'`          | Waiting for back side of document                |
| `WAITING_FRONT`           | `'AWAITING_DOCUMENT_UPLOAD_FRONT'`         | Waiting for front side of document               |
| `COMPLETE`                | `'COMPLETE_OCR'`                           | OCR capture and processing complete              |
| `DOCUMENTS_INVALID`       | `'AWAITING_DOCUMENT_UPLOAD_INVALID_TYPE'`  | Invalid document type provided                   |
| `DOCUMENTS_UPLOAD_FAILED` | `'AWAITING_DOCUMENT_UPLOAD_FAILED_OCR'`    | Document upload failed                           |
| `PROVIDER_OFFLINE`        | `'AWAITING_OCR_RESULTS_PROVIDER_OFFLINE'`  | OCR provider is offline/unavailable              |
| `FAILED_FILE_SIZE`        | `'DOCUMENT_INVALID_EXCEEDED_SIZE_LIMIT'`   | File size exceeds limit                          |
| `FAILED_FILE_FORMAT`      | `'DOCUMENT_INVALID_INCORRECT_FILE_FORMAT'` | Incorrect file format                            |
| `INTERRUPTED`             | `'INTERRUPTED'`                            | Capture flow was interrupted (provider-specific) |

**Example:**

```javascript theme={null}
const ocrComponent = sdk.component('ocr', { provider: { name: 'onfido' } });

ocrComponent.on('input_required', (info, status) => {
  if (status === ocrComponent.statuses.WAITING_FRONT) {
    console.log('Please capture front of document');
  } else if (status === ocrComponent.statuses.WAITING_BACK) {
    console.log('Please capture back of document');
  }
});

ocrComponent.on('results', ({ document }) => {
  const status = ocrComponent.access('status').getValue();

  if (status === ocrComponent.statuses.COMPLETE) {
    console.log('OCR completed successfully');
    console.log('Extracted data:', document);
  }
});
```

***

## Events

The OCR module emits events throughout the document capture 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;
    vendorParameters: unknown;
  }
}
```

**Example:**

```javascript theme={null}
ocrComponent.on('session_data_generated', ({ session }) => {
  console.log('OCR session created for entity:', session.entityId);
});
```

***

### `ready`

Emitted when the OCR component is ready and mounted.

**Arguments:**

```typescript theme={null}
{
  domElement: HTMLElement;
}
```

**Example:**

```javascript theme={null}
ocrComponent.on('ready', ({ domElement }) => {
  console.log('OCR component ready in element:', domElement);
});
```

***

### `detection_complete`

Emitted when document capture is complete.

**Arguments:**

```typescript theme={null}
{
  provider: string;
} | []
```

**Example:**

```javascript theme={null}
ocrComponent.on('detection_complete', (data) => {
  if (data && data.provider) {
    console.log(`Document captured with ${data.provider}`);
  } else {
    console.log('Document capture complete');
  }
  showProcessingMessage();
});
```

***

### `detection_failed`

Emitted when document capture fails.

**Arguments:**

```typescript theme={null}
{
  message?: string;
}
```

**Example:**

```javascript theme={null}
ocrComponent.on('detection_failed', ({ message }) => {
  console.error('Capture failed:', message);
  showErrorMessage(message || 'Failed to capture document. Please try again.');
});
```

***

### `input_required`

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

**Arguments:**

```typescript theme={null}
(
  info: {
    documentType: string | null;
    side: 'front' | 'back' | null;
  },
  status: OCRStatus,
  provideFile: (blob: File) => void
)
```

**Description:**
This event indicates that document capture cannot proceed in its current state, but the issue is typically recoverable. Common scenarios include:

* Waiting for front or back side of document
* User needs to retry capture
* Document type mismatch

<Warning>
  **Legacy Parameter:** The `provideFile` callback is for headless OCR integration and is not recommended for standard use. For standard provider integrations, the provider handles file capture automatically. Avoid using this parameter unless you have a specific headless integration requirement.
</Warning>

**Example:**

```javascript theme={null}
ocrComponent.on('input_required', (info, status) => {
  console.log('Input required:', {
    documentType: info.documentType,
    side: info.side,
    status: status
  });

  if (status === ocrComponent.statuses.WAITING_FRONT) {
    showMessage('Please capture the front of your document');
  } else if (status === ocrComponent.statuses.WAITING_BACK) {
    showMessage('Please capture the back of your document');
  }
});
```

***

### `results`

Emitted when OCR processing is complete and document data is available.

**Arguments:**

```typescript theme={null}
{
  document: Document | null;
  entityId: string | null;
}
```

**Description:**
Contains the extracted document information including ID number, expiry date, date of birth, and other fields depending on document type. The document structure matches the [Document Structure](/docs/sdk-reference/individual-module#document-structure) used in the Individual module.

**Example:**

```javascript theme={null}
ocrComponent.on('results', ({ document, entityId }) => {
  if (document) {
    console.log('Document extracted:', {
      type: document.idType,
      number: document.idNumber,
      expiry: document.idExpiry,
      dateOfBirth: document.dateOfBirth,
      country: document.country
    });

    // Document is automatically added to Individual module
    navigateToNextStep();
  } else {
    console.log('No document data extracted');
    showRetryOption();
  }
});
```

***

### `file_uploaded`

Emitted when a file is successfully uploaded.

<Note>
  **Legacy Headless OCR:** This event is primarily used in legacy headless OCR implementations. For standard provider integrations, use the `results` event instead.
</Note>

**Arguments:**

```typescript theme={null}
{
  fileName: string | null;
  mimeType: string | null;
  scanId: string | null;
  statusAfterUpload: OCRStatus;
  statusBeforeUpload: OCRStatus | null;
}
```

**Example:**

```javascript theme={null}
ocrComponent.on('file_uploaded', (meta) => {
  console.log('File uploaded:', meta.fileName);
  console.log('Status changed:', meta.statusBeforeUpload, '→', meta.statusAfterUpload);
});
```

***

### `session_closed`

Emitted when the OCR session is closed.

**Arguments:** None

**Example:**

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

***

### `session_interrupted`

Emitted when the user interrupts the capture session.

**Arguments:**

```typescript theme={null}
{
  eventName: string;
  reason: string;
  module: 'OCR' | 'BIOMETRICS';
}
```

<Note>
  **Provider-Specific:**

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

**Example:**

```javascript theme={null}
ocrComponent.on('session_interrupted', ({ reason, eventName }) => {
  console.log(`Session interrupted: ${reason}`);
  console.log('Event:', eventName);
  saveProgress();
});
```

***

### `session_data_failed_loading`

Emitted when session data fails to load.

**Arguments:**

```typescript theme={null}
{
  code?: unknown;
  message: string;
}
```

**Example:**

```javascript theme={null}
ocrComponent.on('session_data_failed_loading', ({ message, code }) => {
  console.error('Failed to load session:', message);
  console.error('Error code:', code);
  showError('Unable to start document capture. Please try again.');
});
```

***

### `vendor_event`

Emitted for provider-specific events.

**Arguments:**

```typescript theme={null}
Record<string, unknown>  // Provider-specific event data
```

**Example:**

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

***

### Common Events

The OCR 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 captureDocument() {
  try {
    // Initialize SDK
    const sdk = await OneSdk({
      mode: 'production',
      session: { token: await getSessionToken() }
    });

    // Create OCR component with Onfido provider
    const ocrComponent = sdk.component('ocr', {
      provider: {
        name: 'onfido',
        theme: 'light',
        showExitButton: true
      },
      documents: [
        { type: 'DRIVERS_LICENCE', countries: ['AUS'] },
        { type: 'PASSPORT' }
      ]
    });

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

    ocrComponent.on('ready', () => {
      console.log('OCR component ready');
      // Capture begins automatically - no need to call start()
    });

    ocrComponent.on('detection_complete', () => {
      console.log('Document captured, processing...');
      showMessage('Processing your document...');
    });

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

    ocrComponent.on('input_required', (info, status) => {
      console.log('Input required:', info.documentType, info.side);

      if (status === ocrComponent.statuses.WAITING_FRONT) {
        showInstruction('Please capture the front of your document');
      } else if (status === ocrComponent.statuses.WAITING_BACK) {
        showInstruction('Please capture the back of your document');
      }
    });

    ocrComponent.on('file_uploaded', (meta) => {
      console.log('File uploaded:', meta.fileName);
      updateProgress();
    });

    ocrComponent.on('results', ({ document, entityId }) => {
      console.log('OCR complete for entity:', entityId);

      if (document) {
        console.log('Extracted document data:', {
          type: document.idType,
          number: document.idNumber,
          expiry: document.idExpiry,
          dateOfBirth: document.dateOfBirth
        });

        // Document automatically added to Individual module
        ocrComponent.unmount();
        navigateToNextStep();
      } else {
        console.log('No document data extracted');
        showRetryOption();
      }
    });

    ocrComponent.on('session_closed', () => {
      console.log('User closed OCR session');
      ocrComponent.unmount();
    });

    ocrComponent.on('error', (error) => {
      console.error('OCR error:', error);
      showError('Document capture error. Please try again.');
    });

    // Mount the component - capture begins automatically
    ocrComponent.mount('#ocr-container');

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

***

## Best Practices

1. **Handle all events, not just `results`** - Also listen to `input_required` (for recoverable states like WAITING\_FRONT, WAITING\_BACK, DOCUMENTS\_INVALID), `detection_failed` (for capture failures), and `error` (for system failures).

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}
#ocr-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)
* [IDV Module](/docs/sdk-reference/idv-module)
* [Event System](/docs/sdk-reference/events)
* [Document Structure](/docs/sdk-reference/individual-module#document-structure)
