---
title: "Document Capture Module"
url: "https://developer.incode.com/sdk-reference/web-sdk-2-module-document-capture/"
section: "sdk-reference"
group: "Incode Web SDK 2 Reference / Web SDK 2 Individual Modules"
version: "v1.1"
status: "live"
---
# Document Capture Module

:::note
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation [here](/sdk-reference/web-sdk-reference).  Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade. <br /><br />Full rollout to all clients still TBD.
:::

The Document Capture module captures generic documents (utility bills, lease agreements, tax documents, address proofs, vehicle logbooks, etc.) — anything that isn't an identity document but needs to be uploaded as part of verification. Supports both camera-based capture and file-picker upload, with optional multi-page support.

This module follows the [camera-capture pattern](/sdk-reference/web-sdk-2-module-patterns/#2-camera-capture-modules), but extends it with file-upload alternatives and multi-page state.

## Tag

`<incode-document-capture>` is a standard Web Component. Importing the UI subpath registers the custom element; importing the CSS applies the module's styles.

```ts
import '@incodetech/web/document-capture';
import '@incodetech/web/document-capture/styles.css';
```

## Properties

| Property   | Type                                   | Required | Description                   |
| ---------- | -------------------------------------- | -------- | ----------------------------- |
| `config`   | `DocumentCaptureConfig`                | ❌       | Configuration options         |
| `onFinish` | `() => void`                           | ❌       | Called when capture completes |
| `onError`  | `(error: string \| undefined) => void` | ❌       | Called when an error occurs   |

## Configuration

```typescript
type DocumentCaptureConfig = {
  processingType?: DocumentType; // Backend routing key (default 'addressStatement')
  captureMode?: 'file' | 'camera'; // 'camera' = capture only (hides upload); 'file' = upload only (hides camera); absent = capture + upload
  allowSkipDocumentCapture?: boolean; // Default false
  disableSkipPoa?: boolean; // Backend ADDRESS field; inverse of allowSkipDocumentCapture
  title?: string; // Tutorial screen title override
  text?: string; // Tutorial screen text override
  step2Title?: string; // Multi-page tutorial second-page title
  step2Text?: string; // Multi-page tutorial second-page text
  captureAttempts?: number; // Default 3
  sendBase64?: boolean; // Default false (sends raw bytes)
  maxFileSize?: number; // Default 10 MB
  onlyPdf?: boolean; // Default false. Restrict uploads to PDF; camera capture unaffected
};
```

`processingType` accepts: `addressStatement`, `otherDocument1`, `otherDocument2`, `otherDocument3`, `v5cMultiPageLogbook`, `circulationCard`, `financeSettlement`, `carInvoice`, `w8Ben`, `w8BenE`, plus `process*` variants for OCR-driven processing — including `processW8BenOcr` and `processW8BenEOcr` for the IRS W-8 tax forms. The multi-page types (`v5cMultiPageLogbook`, `circulationCard`, `financeSettlement`, `w8BenE`) trigger the `nextPage` flow described below. W-8BEN is single-page; W-8BEN-E is multi-page.

Set `sendBase64: false` (the default) to upload the file as raw bytes with its MIME type as `Content-Type`. Address statements and generic documents use `/omni/add/document`; setting `sendBase64: true` sends base64 JSON to their respective v2 endpoints. Types that use `/omni/add/document/v3` or `/omni/process/cfdi` keep those routes in both modes. The option applies to camera captures, selected images, and PDFs.

Set `onlyPdf: true` when the document only makes sense as a PDF, such as a tax form the user downloads and re-uploads. It narrows the file picker and rejects non-PDF selections; it does not disable camera capture, so pair it with `captureMode: 'file'` for a PDF-only step.

## State machine

`DocumentCaptureState` is a discriminated union over `status`. The states extend the camera-capture pattern with file-upload and multi-page handling:

| Status               | Description                                                                          |
| -------------------- | ------------------------------------------------------------------------------------ |
| `tutorial`           | Initial guidance screen.                                                             |
| `permissions` | Camera permission check, prompt, or help. |
| `initializingCamera` | Camera starting up (when camera capture is offered and the user picks camera). |
| `capturing` | Camera preview or file selection, depending on `captureMethod`. |
| `preview`            | After capture or file pick, user reviews the image before accept/retake.             |
| `uploading`          | Uploading the (accepted) image to the backend.                                       |
| `success` | Upload accepted; call `continue()` to advance. |
| `nextPage` | Choose how to capture another page; offer completion only when the next page is optional. |
| `finalizing`         | Server-side finalization after all pages uploaded.                                   |
| `failure` | Upload or finalization failed; retry when attempts remain, otherwise continue. |
| `finished`           | Terminal — module complete.                                                          |
| `closed`             | User dismissed.                                                                      |

### State properties

| Property | Type | Available in | Description |
| --- | --- | --- | --- |
| `pageNumber` | `number` | `tutorial`, `capturing`, `nextPage` | Current document page. |
| `imageBase64` | `string` | `preview`, `uploading`, `success`, `nextPage` | Image for the current preview; keep it out of logs. |
| `fileType`, `fileName` | `string` | `preview`, `uploading`, `success`, `nextPage` | MIME type and display filename. |
| `progress` | `number` | `uploading` | Upload progress. |
| `nextPageType` | `'none' \| 'required' \| 'optional'` | `success` | Whether another page is expected. |
| `nextPageType` | `'required' \| 'optional'` | `nextPage` | Whether the next page is mandatory. |
| `permissionStatus` | See below | `permissions` | Permission presentation state. |

Additional properties for custom capture controls:

| Property | Type | Available in | Description |
| --- | --- | --- | --- |
| `stream` | `MediaStream \| undefined` | `capturing` | Live camera stream when available. |
| `captureMethod` | `'camera' \| 'file' \| 'gallery' \| undefined` | `capturing` | Current capture method. |
| `onlyCapture`, `onlyUpload`, `onlyPdf` | `boolean` | `tutorial`, `capturing`, `nextPage` | Resolved camera/upload restrictions. |
| `allowSkipDocumentCapture` | `boolean` | `tutorial` | Whether the first-page skip action is available. |
| `error` | `DocumentCaptureErrorCode \| undefined` | `tutorial`, `capturing` | Current file-selection feedback. |
| `error` | `DocumentCaptureErrorCode` | `failure` | Failure code. |
| `attemptsRemaining` | `number` | `failure` | Determines whether to offer retry or continuation. |

In a headless camera UI, attach `stream` to your video element, capture a frame in your host, then pass its `File` and preview data URL to `setFile()`. In `nextPage`, choose a capture method before submitting another file. `capture()` does not pull a frame from `capturing`.

The shared `permissionStatus` type includes `checking`, `idle`, `motionOnly`, `requesting`, `denied`, and `learnMore`. Document Capture currently emits `checking`, `idle`, `requesting`, `denied`, and `learnMore`. Show no prompt while `checking`; show the request action in `idle`, a busy state in `requesting`, and permission instructions after denial.

## API methods

| Method | Purpose | Callable when |
| --- | --- | --- |
| `requestPermission()` | Request camera access. | `permissions` with `idle`, `checking`, or `learnMore` |
| `goToLearnMore()` | Show permission help. | `permissions` with `idle` or `checking` |
| `back()` | Return to the permission check. | `permissions` with `learnMore` |
| `capture()` | Start camera permission/setup when camera capture is allowed. | `tutorial` |
| `setFile(file, imageBase64)` | Submit a selected file or a camera frame as a `File` with its preview data URL; accepted files move to `preview`. | `tutorial`, `capturing` |
| `accept()` | Accept the preview and upload it. | `preview` |
| `retake()` | Return to `tutorial` for file upload, or `capturing` for camera/gallery selection. | `preview` |
| `retry()` | Return to the tutorial and restart from the first page. | `failure` with `attemptsRemaining > 0` |
| `continue()` | Advance to `nextPage` or `finished` after success; finish after attempts are exhausted. | `success`, or `failure` with `attemptsRemaining <= 0` |
| `skip()` | Skip the document step. | First-page `tutorial` with resolved `allowSkipDocumentCapture: true` |
| `close()` | Dismiss the module. | `tutorial`, `permissions`, `initializingCamera`, `capturing`, `preview`, `success`, `nextPage`, `failure` |
| `captureNextPageFromCamera()` | Select camera for the next page and enter permissions. | `nextPage` |
| `captureNextPageFromFile()` | Select gallery/file capture for the next page and enter `capturing`; your host opens the picker. | `nextPage` |
| `finishPageCapture()` | Finish page collection. Supported multi-page document types enter `finalizing` when the next page is optional; otherwise the manager enters `finished` directly. Offer this action only for an optional next page. | `nextPage` |

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

### Capture-method selection and help

When the step offers both camera and upload, the `tutorial` state lets the user choose between them, and the `capturing` state can show a "common issues" help overlay. Both are overlays over an existing state rather than states of their own, so each is driven by a boolean on the state you are already in:

| Method                   | Purpose                                                                  | Callable when             |
| ------------------------ | ------------------------------------------------------------------------ | ------------------------- |
| `openMethodSelection()`  | Open the camera-or-upload chooser. Sets `methodSelectionOpen` to `true`. | `tutorial`                |
| `closeMethodSelection()` | Dismiss the chooser without picking.                                     | `tutorial`, chooser open  |
| `selectUploadMethod()`   | Pick upload, which switches the chooser to its upload variant.           | `tutorial`, chooser open  |
| `deselectUploadMethod()` | Return to the camera-or-upload choice after picking upload.              | `tutorial`, upload picked |
| `openHelp()`             | Open the "common issues" overlay over the camera view. Sets `helpOpen`.  | `capturing`               |
| `closeHelp()`            | Dismiss the help overlay.                                                | `capturing`, help open    |

Read `methodSelectionOpen` from the `tutorial` state and `helpOpen` from the `capturing` state to decide what to render. Both default to `false`, so an integration that ignores them keeps the previous behavior.

## Camera and upload requirements

Camera capture requires a secure browser context (HTTPS in production) and camera permission. Users review the captured image or selected file before upload. Document Capture does not require warming up the ID Capture WASM pipeline. If your integration enables [end-to-end encryption](/sdk-reference/web-sdk-2-e2ee/), follow that feature's setup requirements separately.

## See also

- [Module Patterns → camera-capture](/sdk-reference/web-sdk-2-module-patterns/#2-camera-capture-modules)
- [WASM Configuration](/sdk-reference/web-sdk-2-wasm/)
- [Individual Modules](/sdk-reference/web-sdk-2-individual-modules/)