# ID OCR Module

<WebSDK2 />

The ID OCR module extracts structured data (name, address, document number, dates, etc.) from a captured ID image. Typically runs after [ID Capture](doc:web-sdk-2-module-id-capture).

> Follows the [form-based pattern](doc:web-sdk-2-module-patterns#1-form-based-modules), with an additional `readonly` state when `editableOcr` is `false` (display extracted data without letting the user edit). See the patterns page for the shared lifecycle.

## Availability

This module is headless-only — there is no public `<incode-id-ocr>` web component. Drive it with `createIdOcrManager` from `@incodetech/core/id-ocr` and render your own UI (form fields, validation messages, etc.).

## Configuration

```typescript
type IdOcrConfig = {
  editableOcr?: boolean; // Allow user to edit OCR data (default: false)
  secondId?: boolean; // After first ID OCR step, load second captured ID's OCR (orchestrated flow only)
  flowId?: string; // Session flow ID; when listed in CPFFlowIds, only the CPF field is shown
};
```

| Option        | Type      | Required | Description                                                                                 |
| ------------- | --------- | -------- | ------------------------------------------------------------------------------------------- |
| `editableOcr` | `boolean` | ❌        | When `true`, the user can edit extracted fields before submitting. Default `false`.         |
| `secondId`    | `boolean` | ❌        | Used in orchestrated flows when a second ID was captured. Loads OCR for that document next. |
| `flowId`      | `string`  | ❌        | Set by the orchestrator. CPF flows render only the CPF field; otherwise full OCR fields.    |

## State machine

`IdOcrState` is a discriminated union over `status`:

| Status       | Description                                                                                      |
| ------------ | ------------------------------------------------------------------------------------------------ |
| `idle`       | Initial state.                                                                                   |
| `loading`    | Fetching OCR data from the backend.                                                              |
| `readonly`   | Display extracted data; no edits allowed (`editableOcr === false`). User can confirm to advance. |
| `inputting`  | Editable form rendered. User can edit fields and validate.                                       |
| `submitting` | Sending the (possibly edited) data back to the backend.                                          |
| `success`    | Server accepted the submission.                                                                  |
| `finished`   | Terminal — the module is done.                                                                   |
| `error`      | Fatal error.                                                                                     |

## API methods

| Method                   | Purpose                                                                         |
| ------------------------ | ------------------------------------------------------------------------------- |
| `load()`                 | Fetch the OCR data and transition to `readonly` or `inputting`.                 |
| `setField(field, value)` | Update a field while in `inputting`. `field` is a key of `UpdateOcrDataParams`. |
| `validateField(field)`   | Run validation (required, minimum age, CPF format) on a single field.           |
| `continue()`             | Confirm and submit. Transitions to `submitting`.                                |
| `retry()`                | After `error`, restart the OCR fetch.                                           |

Plus the universal lifecycle: `subscribe`, `getState`, `reset`, `stop`.

## Headless example

```typescript
import { createIdOcrManager } from '@incodetech/core/id-ocr';

const manager = createIdOcrManager({
  config: { editableOcr: true },
});

manager.subscribe((state) => {
  switch (state.status) {
    case 'readonly':
      // Render state.formData read-only with a "Confirm" button → manager.continue()
      break;
    case 'inputting':
      // Render editable form. On change: manager.setField('firstName', value)
      // On submit: manager.continue()
      // state.validationErrors lists per-field error keys
      break;
    case 'finished':
      manager.stop();
      break;
  }
});

manager.load();
```

## See also

* [Module: ID Capture](doc:web-sdk-2-module-id-capture): typically runs before this module
* [Module Patterns → form-based](doc:web-sdk-2-module-patterns#1-form-based-modules)
* [Individual Modules](doc:web-sdk-2-individual-modules)
