The KYC Documents Capture SDK gives your organization full control over the document and selfie capture experience. You own the UI, the branding, and the flow — Trulioo powers the underlying image capture and verification technology.
This means you can build capture experiences that are fully aligned with your brand guidelines, with custom overlays, animations, and messaging, while relying on Trulioo's built-in verification intelligence for accuracy and security.
Looking for a ready-made solution?
If you prefer a complete Trulioo-designed UI out of the box, see the KYC Documents SDK instead. It delivers the same trusted capture and verification technology with minimal setup.
Quick Start
- Install
@trulioo/kyc-documents-capture. - Get a shortcode from your backend for the active transaction.
- Call
initializeCapture(shortCode)and wait for it to resolve. - Create a document or selfie camera with
createCaptureCamera(config?). - Render the camera into an existing DOM element.
- Use
startFeedback()for auto capture orcaptureLatestFrame()for manual capture. - Call
verifyImage()thenacceptImage()on the capture result. - Call
submitCapture()when all required images have been accepted. - Call
clearSession()when the flow is complete.
What This SDK Covers
This guide is for integrations where your application owns the page shell and embeds the SDK camera into your own UI. The SDK handles:
- Camera initialization and teardown
- Frame analysis for auto capture
- Post-capture image verification
- Accepted-image association with the active transaction
Your application handles:
- The surrounding DOM, controls, and page layout
- Browser camera permission prompts
- Whether the current step is document or selfie capture
- Whether to use auto capture or manual capture
- Whether to accept or retake a verified image
- When to submit or clear the session
Package
| Entrypoint | Purpose |
|---|---|
@trulioo/kyc-documents-capture/api | Camera, session, and capture operations |
@trulioo/kyc-documents-capture/docs | Configuration context, consent, metadata, and desktop handoff helpers |
@trulioo/kyc-documents-capture/network | Network state and status subscriptions |
Installation
npm:
npm install @trulioo/kyc-documents-captureCDN (latest):
import {
initializeCapture,
createCaptureCamera,
submitCapture,
clearSession,
} from "https://cdn.jsdelivr.net/npm/@trulioo/kyc-documents-capture/api/+esm";CDN (pinned version — recommended for production):
import {
initializeCapture,
createCaptureCamera,
submitCapture,
clearSession,
} from "https://cdn.jsdelivr.net/npm/@trulioo/kyc-documents-capture@VERSION_NUMBER/api/+esm";Replace VERSION_NUMBER with the SDK version you want to lock to.
End-to-End Example
import {
initializeCapture,
createCaptureCamera,
submitCapture,
clearSession,
} from "@trulioo/kyc-documents-capture/api";
const shortCode = "generated-from-trulioo-api";
initializeCapture(shortCode)
.then((transactionId) => {
console.log("Initialized transaction:", transactionId);
const camera = createCaptureCamera();
return camera.render("camera-root").then(() => {
return camera.startFeedback().then((result) => {
return result.verifyImage().then((verifyFeedback) => {
const accepted = verifyFeedback.verifyResponses.some((value) => {
return value === "SUCCESS" || value === "SUCCESS_REQUIRES_BACK";
});
if (!accepted) {
throw new Error("Captured image was not accepted");
}
return result.acceptImage();
});
});
});
})
.then(() => submitCapture())
.then(() => {
clearSession();
console.log("Capture flow completed");
})
.catch((error) => {
console.error("Capture flow failed:", error);
});Initialization
Call initializeCapture(shortCode) before creating cameras or submitting the transaction. It resolves the active Capture session, authorizes the transaction, fetches configuration, and returns the transaction ID.
import { initializeCapture } from "@trulioo/kyc-documents-capture/api";
const transactionId = await initializeCapture(shortCode);
console.log("Active transaction:", transactionId);Always initialize with a shortcode created for the active transaction. Do not reuse a stale shortcode across sessions. After calling clearSession(), a new initializeCapture() call is required before reusing the SDK.
Creating and Rendering a Camera
Use createCaptureCamera() to create a camera. Document capture is the default.
import { createCaptureCamera, DetectionType } from "@trulioo/kyc-documents-capture/api";
// Document camera (default)
const documentCamera = createCaptureCamera();
// Selfie camera
const selfieCamera = createCaptureCamera({
detectionType: DetectionType.BIOMETRIC_SELFIE,
});Render the camera into an existing DOM element by passing the parent element ID:
const camera = createCaptureCamera();
camera.onFeedbackState((state) => {
console.log("Feedback state:", state);
});
camera.onCaptureRegion((region) => {
console.log("Capture region:", region);
});
camera
.render("parent-element-id", {
backgroundColor: "#00000050",
})
.then(() => {
console.log("Camera loaded");
})
.catch((error) => {
console.error("Camera failed to load:", error);
});After rendering, you can inspect the active stream resolution:
camera.getResolution().then((resolution) => {
console.log("Resolution:", resolution.width, resolution.height);
});To tear down and resume the camera:
camera.remove();
camera.resume();Capturing an Image
Auto Capture (Recommended)
Call startFeedback() to let the SDK process frames until it captures an acceptable image:
camera.startFeedback().then((result) => {
console.log("Captured image:", result.imageId);
console.log("Detection type:", result.detectionType);
console.log("Feedback:", result.imageFeedbacks);
});To stop an active auto-capture session:
camera.stopFeedback();If stopFeedback() is called during an in-progress startFeedback(), the promise rejects with a stopped-feedback error. Handle this as an expected case, not a fatal error:
camera.startFeedback().catch((error) => {
if (error && error.code === 1100) {
console.log("Feedback stopped intentionally.");
return;
}
console.error("Unexpected feedback error:", error);
});To apply your own acceptance rule while still using SDK frame analysis:
camera
.startFeedbackWithFilter((feedback) => {
return feedback.imageFeedbacks.includes("SUCCESS");
})
.then((result) => {
console.log("Captured filtered image:", result.imageId);
});Manual Capture
Use captureLatestFrame() to trigger a manual capture instead of waiting for auto capture:
camera.captureLatestFrame().then((result) => {
console.log("Manually captured image:", result.imageId);
});Verifying and Accepting an Image
After capturing, call verifyImage() to get post-capture feedback. Then call acceptImage() to mark the image as accepted for the transaction.
verifyImage() does not finalize the transaction — it gives your application the information to decide whether to keep or retake the image.
camera.startFeedback().then((result) => {
result.verifyImage().then((verifyFeedback) => {
if (!verifyFeedback.isVerifyAttemptAvailable) {
console.log("No further verify attempts available.");
}
console.log("Verify responses:", verifyFeedback.verifyResponses);
const accepted = verifyFeedback.verifyResponses.some((value) => {
return value === "SUCCESS" || value === "SUCCESS_REQUIRES_BACK";
});
if (accepted) {
result.acceptImage().then(() => {
console.log("Image accepted.");
});
}
});
});Verify attempts are limited. Check isVerifyAttemptAvailable before calling verifyImage() again. Avoid repeated verify calls once this value is false.
Recommended acceptance rule: treat SUCCESS and SUCCESS_REQUIRES_BACK as accepted outcomes for image upload.
Submitting and Clearing the Session
Call submitCapture() after all required images have been accepted:
await submitCapture();Then call clearSession() to clear local runtime state:
clearSession();submitCapture() does not clear local runtime state by itself. Always call clearSession() when the flow is done or abandoned.
Docs and Network Helpers
Use the docs entrypoint for configuration context, consent, metadata, and desktop-to-mobile handoff:
import {
getConfigurationContext,
recordConsent,
sendMetadata,
} from "@trulioo/kyc-documents-capture/docs";Use the network entrypoint to react to connectivity changes:
import {
getNetworkStatus,
observeNetworkStatus,
} from "@trulioo/kyc-documents-capture/network";
console.log(getNetworkStatus());
const subscription = observeNetworkStatus({
onChange(status) {
console.log("Network status changed:", status);
},
});
subscription.cancel();Result Reference
| Method | Returns | Key fields |
|---|---|---|
startFeedback() | CaptureImageResult | imageId, detectionType, imageFeedbacks |
startFeedbackWithFilter() | CaptureImageResult | imageId, detectionType, imageFeedbacks |
captureLatestFrame() | CaptureResult | imageId, detectionType |
verifyImage() | CaptureVerifyFeedback | isVerifyAttemptAvailable, verifyResponses |
Public API Reference
Session and submission:
initializeCapture(shortCode) · submitCapture() · clearSession()
Camera creation:
createCaptureCamera(config?) · DetectionType
Camera operations:
render(parentElementId, props?) · startFeedback() · startFeedbackWithFilter(filter) · captureLatestFrame() · stopFeedback() · onFeedbackState(callback) · onCaptureRegion(callback) · getResolution() · resume() · remove()
Capture result operations:
verifyImage() · acceptImage()
Common Mistakes
Calling createCaptureCamera() before initializeCapture() completes. Initialization must succeed before creating or rendering a camera.
Rendering into a DOM element that does not exist yet. Confirm the parent element is present in the DOM before calling render(...).
Calling submitCapture() before all required images are accepted. Verify and accept each required image before submitting.
Assuming submitCapture() also clears local state. Always call clearSession() after submitting or abandoning a flow.
Treating a stopped feedback session as a fatal error. A stopFeedback() call during auto capture rejects the startFeedback() promise with error code 1100. This is expected — handle it as an intentional stop, not an unexpected failure.
Troubleshooting
Initialization fails: Confirm the shortcode is valid and belongs to the expected environment.
Camera UI does not appear: Confirm the parent DOM element exists and that browser camera permission has been granted.
Auto capture never completes: Use onFeedbackState() to inspect whether the SDK is repeatedly requesting a retake condition. This usually indicates a lighting or framing issue in your camera environment.
Verify or accept fails: Confirm the image came from the current active session and was not invalidated by a prior clearSession() call.
Diagnostic Checklist
When filing a support issue, include:
- Capture SDK version.
- Browser name and version.
- Operating system and device type.
- Whether the flow was document or selfie capture.
- Whether the issue occurred during auto capture or manual capture.
- The transaction ID, if available.
- The latest feedback state or verify responses.
- Which stage the failure occurred at: initialize, render, capture, verify, accept, or submit.

