Skip to main content
Sessions required

Every yes:id SDK module needs a valid session before it can run. Complete the Sessions Guide first β€” it takes 5 minutes and is required before the code below will work.

Using the Document Capture SDK

The widget validates the session, lets the user capture or upload the document, extracts the card, submits images to yes:id, and returns OCR on yesid:success.

Create the session on your backend. The browser only receives publishableKey and sessionId.

Prerequisites β€” create a session first​

Your backend calls the yes:id Session API with the secret key, then the frontend initializes the widget:

const [config, session] = await Promise.all([
fetch('/config').then((r) => r.json()),
fetch('/create-session', { method: 'POST' }).then((r) => r.json()),
]);

const publishableKey = config.publishableKey; // pk_…
const sessionId = session.sessionId; // vs_…

See the Sessions Guide for the backend request body, including documentCapture.allowedDocuments and sourceMode.

Web component​

<script type="module">
import { defineYesIdDocumentCapture } from '@yesid/document-scanner';

defineYesIdDocumentCapture();
</script>

<yesid-document-capture
id="document-scanner"
publishable-key="pk_live_xxx"
></yesid-document-capture>

<script>
const scanner = document.getElementById('document-scanner');
scanner.sessionId = sessionId; // set after /create-session returns

scanner.addEventListener('yesid:success', (event) => {
const { response, submission } = event.detail;
console.log(response);
console.log(submission.images);
});

scanner.addEventListener('yesid:failure', (event) => {
console.error(event.detail.message);
});
</script>

You can also set credentials as element properties:

scanner.publishableKey = publishableKey;
scanner.sessionId = sessionId;

React​

import { DocumentCapture } from '@yesid/document-scanner/react';

export function DocumentScanStep({ publishableKey, sessionId }) {
return (
<DocumentCapture
publishableKey={publishableKey}
sessionId={sessionId}
onSuccess={({ response, submission }) => {
console.log(response);
console.log(submission.images);
}}
onFailure={({ message }) => {
console.error(message);
}}
/>
);
}

Configuration reference​

OptionTypeRequiredDescription
publishableKey / publishable-keystringYesBrowser-safe key (pk_…)
sessionId / session-idstringYesSession created by your backend (vs_…)
selectedDocument{ type, country }NoPin a document when the session allows more than one type
disabledbooleanNoDisable interaction (for example until the user picks a document type)
cameraFacingMode'environment' | 'user'NoPreferred camera. Default 'environment'
cameraGuideEnabledbooleanNoShow the capture guide overlay
cameraGuidePreset'id-card' | 'a4' | 'custom'NoGuide and detection preset
labelsScannerLabelsNoOverride UI copy

Capture mode (single vs front + back) and camera/upload availability come from the session (sourceMode, allowedDocuments, requiredSides). You do not set those as widget attributes.

Selecting a document type​

yesid:session-validated returns the documents allowed for this session. If more than one type is allowed, set selectedDocument before capture:

scanner.addEventListener('yesid:session-validated', (event) => {
const allowed = event.detail?.documentCapture?.allowedDocuments ?? [];
if (allowed.length === 1) {
scanner.selectedDocument = {
type: allowed[0].type,
country: allowed[0].country,
};
}
});

// After the user picks from your own dropdown:
scanner.selectedDocument = { type: 'national_id', country: 'TZ' };

React equivalent: pass selectedDocument={{ type: 'national_id', country: 'TZ' }}.

Customising labels​

Omit a key to keep the SDK default. Set a value to "" to hide that label.

scanner.labels = {
sourcePicker: {
titleBoth: 'Capture your document',
hint: 'Make sure the entire document is clearly visible.',
cameraButton: 'Camera',
uploadButton: 'Upload',
},
permission: {
title: 'Camera permission required',
text: 'We need access to your camera to capture your document.',
button: 'Allow Camera',
},
};

Complete React example​

This mirrors the integration in the yes:id web demo β€” create a session, render the scanner, handle OCR on success:

import { useCallback, useEffect, useState } from 'react';
import { DocumentCapture } from '@yesid/document-scanner/react';

export function DocumentScanScreen() {
const [publishableKey, setPublishableKey] = useState('');
const [sessionId, setSessionId] = useState('');
const [error, setError] = useState('');

const createSession = useCallback(async () => {
setError('');
try {
const [config, session] = await Promise.all([
fetch('/config').then((r) => r.json()),
fetch('/create-session', { method: 'POST' }).then((r) => r.json()),
]);
setPublishableKey(config.publishableKey);
setSessionId(session.sessionId);
} catch (e) {
setError(e instanceof Error ? e.message : 'Failed to create session');
}
}, []);

useEffect(() => {
createSession();
}, [createSession]);

if (error) {
return (
<button type="button" onClick={createSession}>
Retry session
</button>
);
}

if (!publishableKey || !sessionId) {
return <p>Creating verification session…</p>;
}

return (
<DocumentCapture
key={sessionId}
publishableKey={publishableKey}
sessionId={sessionId}
onSuccess={({ response, submission }) => {
const ocr = response?.resultData?.ocr ?? response?.ocr;
const portrait = ocr?.portrait;
const fields = ocr?.documentData ?? [];
}}
onFailure={({ message }) => setError(message)}
onSessionInvalid={() => createSession()}
/>
);
}
Next

Listen for capture events and read OCR fields: Handling Results β†’