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:
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 |
| Sumsub | 'sumsub' | sumsub.com |
| Incode | 'incode' | incode.com |
| IDVerse | 'idverse' | idverse.com |
| Daon | 'daon' | daon.com |
Each provider has different capabilities, supported document types, and geographic coverage. Visit the provider’s website to understand their specific features and limitations.
Configuration Options
Basic Configuration
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:
documents: [
{
type: 'DRIVERS_LICENCE', // Document type
countries: ['AUS', 'NZL'] // ISO country codes (optional)
}
]
Provider-Specific Options
Onfido Provider
const ocrComponent = sdk.component('ocr', {
provider: {
name: 'onfido',
sdkVersion: '13.0.0', // Onfido SDK version
theme: 'light', // 'light' or 'dark'
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 for available versions. |
theme | 'light' | 'dark' | UI theme |
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) |
Onfido Custom UI Properties:
The customUI object allows extensive styling customization:
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
const ocrComponent = sdk.component('ocr', {
provider: {
name: 'incode',
sdkVersion: '1.0.0', // SDK version
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 for available versions. |
numberOfTries | number | Maximum number of capture attempts |
consentId | string | null | Consent identifier for the session |
renderCamera | object | Camera rendering options (see below) |
renderCamera Options:
| Option | Type | Description |
|---|
showDocSelector | boolean | Display document type selector |
showTutorial | boolean | Display tutorial/instructions |
Sumsub Provider
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 for details. |
options | object | Sumsub SDK options (addViewportTag, adaptIframeHeight). See IDV Module - Sumsub for details. |
IDVerse Provider
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
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:
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:
// 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()
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.
Starts the document capture process in headless mode.
Signature:
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:
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:
isPreloaded()
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.
Checks if OCR data has been previously captured for this entity.
Signature:
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:
// ✅ Use events to track capture progress
ocrComponent.on('results', ({ document }) => {
console.log('Document captured:', document);
proceedToNextStep();
});
ocrComponent.mount('#ocr-container');
// Capture begins automatically
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.
access()
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.
Accesses reactive data accessors for the OCR component state.
Signature:
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:
Provider-Specific: Not all statuses are used by all providers. The specific statuses emitted depend on your chosen provider’s workflow and capabilities.
| 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:
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.
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.
session_data_generated
Emitted when session data for the vendor is generated.
Arguments:
{
session: {
entityId: string;
vendorParameters: unknown;
}
}
Example:
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:
{
domElement: HTMLElement;
}
Example:
ocrComponent.on('ready', ({ domElement }) => {
console.log('OCR component ready in element:', domElement);
});
detection_complete
Emitted when document capture is complete.
Arguments:
{
provider: string;
} | []
Example:
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:
Example:
ocrComponent.on('detection_failed', ({ message }) => {
console.error('Capture failed:', message);
showErrorMessage(message || 'Failed to capture document. Please try again.');
});
Emitted when a non-positive flow has occurred but is likely recoverable by retrying.
Arguments:
(
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
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.
Example:
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:
{
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 used in the Individual module.
Example:
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.
Legacy Headless OCR: This event is primarily used in legacy headless OCR implementations. For standard provider integrations, use the results event instead.
Arguments:
{
fileName: string | null;
mimeType: string | null;
scanId: string | null;
statusAfterUpload: OCRStatus;
statusBeforeUpload: OCRStatus | null;
}
Example:
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:
ocrComponent.on('session_closed', () => {
console.log('OCR session closed');
ocrComponent.unmount();
});
session_interrupted
Emitted when the user interrupts the capture session.
Arguments:
{
eventName: string;
reason: string;
module: 'OCR' | 'BIOMETRICS';
}
Provider-Specific:
- Onfido: Emits this when the verification modal is closed.
Example:
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:
{
code?: unknown;
message: string;
}
Example:
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:
Record<string, unknown> // Provider-specific event data
Example:
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 for details.
Complete Example
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
-
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).
-
Set up event listeners before mounting - Register all event handlers before calling
mount() to avoid missing events.
-
Unmount on navigation - Always call
unmount() when the user leaves the page to clean up resources.
-
Provider-specific configuration - Review each provider’s documentation for optimal configuration.
-
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:
#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.