Identity Verification allows you to securely verify the identity of your users by collecting a government-issued document (such as a driver's license, passport, or national ID card) and a live selfie, and then matching them against each other. This is useful for scenarios like onboarding new customers, account recovery, or verifying identity before granting access to sensitive operations.
This guide explains how to implement Identity Verification using Journeys and SDKs.
When a user needs to verify their identity, the client starts the verification journey and Mosaic creates an Identity Verification session.
On mobile, the Orchestration SDK intercepts Document Acquisition and Selfie Acquisition, runs capture, and submits the result. On web, your client receives the start_token from the Orchestration SDK and starts the Identity Verification session, captures the document and selfie, and submits an empty client response.
After both images are collected, the Platform IDV Recommendation step evaluates the verification data. This step is client-facing: keep calling submitClientResponse() until the journey proceeds to the next step or returns an error. Based on the recommendation, the journey branches and either completes successfully or rejects access.
iOS:
- iOS 13+
- Xcode 11+
- Orchestration SDK 1.2.3 or later
- Identity Verification SDK 1.3.5 or later
Android:
- Android 5+ (API level 21+)
- Orchestration SDK 1.0.34 or later
- Identity Verification SDK 1.3.5 or later
Web:
- SDK 2.4.0 or later
If this is your first time integrating with Mosaic, create an application in the Admin Portal as described here.
In the Admin Portal, go to B2C Identity or B2B Identity based on your setup, and open the Journeys section. Create a journey that collects the user's document and selfie and obtains a verification recommendation, and branches based on the result. It can include the following actions:
- Document Acquisition step: captures a document image from the user.
- Selfie Acquisition step: captures a selfie image from the user.
- Platform IDV Recommendation step: obtains an identity verification recommendation based on the collected document and selfie.
- Condition step: checks the recommendation using a condition expression, for example,
idv_recommendation.recommendation == 'ALLOW'. Iftrue, the journey completes successfully (Complete journey step). Iffalse, the journey rejects access (Reject access step).

As an alternative to running capture on desktop, you can start the journey there and use cross-session messages to hand off the verification process from a desktop session to a mobile device.
To run this flow, your integration needs both the Orchestration SDK and Identity Verification SDK.
Make sure to initialize all SDKs within the context of the same client ID and the same region.
For Web, see instructions here:
- Adding to project/loading: Orchestration module, Identity Verification module
- Initializing: Orchestration module, Identity Verification module
For Android, see instructions here:
- Adding to project/loading: Orchestration SDK, Identity Verification SDK
- Initializing: Orchestration SDK, Identity Verification SDK
For iOS, see instructions here:
- Adding to project/loading: Orchestration SDK, Identity Verification SDK
- Initializing: Orchestration SDK, Identity Verification SDK
Implement the client-side code needed to execute the journey on the user's device.
In a nutshell, you have to implement:
- Starting the journey
- Handling document and selfie acquisition
- Polling for the IDV recommendation
Condition, Complete journey, and Reject access are executed by Mosaic and don't require any client-side code.
On mobile, register an ITSUIHandler after you initialize the Orchestration SDK and before you start the journey. The SDK intercepts Document Acquisition and Selfie Acquisition, so you don't handle those journeyStepId values in your journey switch. You still handle Platform IDV Recommendation in the switch: keep calling submitClientResponse() until the next step arrives.
On web, implement a switch (or other routing mechanism) that invokes a handler for each journey step (returned in idoServiceResponse.journeyStepId). Each handler processes data, displays whatever UI is needed, and calls submitClientResponse() when the interaction is concluded.
The journey loops back to the switch unless Mosaic signals journey completion by setting the journeyStepId property to Rejection.type or Success.type. The idoServiceResponse.token property contains a JWT token as a proof of journey completion.
For more guidance, see the Orchestration SDK quickstarts for Web, Android, or iOS, as well as the Document Acquisition and Selfie Acquisition step guides.
Implement a handler that starts the journey by replacing YOUR_JOURNEY_ID with the journey ID you created in Step 1. On mobile, register the UI handler before you call startJourney().
const idoResponse = await ido.startJourney('YOUR_JOURNEY_ID');Implement image collection and submission for verification:
Mosaic checks camera permissions on the client but doesn't grant them. Make sure camera access is already in place before capture starts.
Register an ITSUIHandler after you initialize the Orchestration SDK and before you start the journey. The SDK intercepts Document Acquisition and Selfie Acquisition, runs capture, and submits the result. You don't start the Identity Verification SDK yourself.
Implement onBefore and onAfter to present your own UI around the SDK capture screens (e.g., introduction screen, consent screen), then call proceed() to continue.
// Hook into document and selfie acquisition steps.
class MyUIHandler(private val activity: FragmentActivity) : ITSUIHandler {
override fun provideDocumentAcquisitionHandler(): TSIDVStepHandler = TSIDVStepHandler().apply {
onBefore = { context ->
// Show your own UI before the SDK document capture starts, then continue.
context.proceed()
}
onAfter = { context ->
// Show your own UI after document acquisition completes, then continue.
context.proceed()
}
}
override fun provideSelfieAcquisitionHandler(): TSIDVStepHandler = TSIDVStepHandler().apply {
onBefore = { context ->
// Show your own UI before the SDK selfie capture starts, then continue.
context.proceed()
}
onAfter = { context ->
// Show your own UI after selfie acquisition completes, then continue.
context.proceed()
}
}
}
// Register after TSIdo.initializeSDK(...) and before TSIdo.startJourney(...).
TSIdo.setUIHandler(MyUIHandler(activity))
TSIdo.startJourney("YOUR_JOURNEY_ID", startJourneyOptions, callback)When the journey reaches Document Acquisition (transmit_platform_document_acquisition) or Selfie Acquisition (transmit_platform_selfie_acquisition), the response data includes:
acquisition_id(required): ID used to start capturestart_token(optional): used to start an Identity Verification session if one isn't already active
If start_token is present, start the Identity Verification session, then call captureDocument() or captureSelfie() with the acquisition_id. After capture completes, submit an empty client response. Handle capture errors in the app (for example, inform the user or retry).
async function handleDocumentAcquisition(idoResponse) {
const startToken = idoResponse.data?.start_token;
const acquisitionId = idoResponse.data?.acquisition_id;
// Start an Identity Verification session when the journey provides a start token
if (startToken !== undefined) {
await idv.start(startToken);
}
await idv.captureDocument({ acquisitionId });
// After acquiring the document, the client response does not need to include any data
// If SDK was loaded via script tag, invoke functions inside 'window.tsPlatform'
return ido.submitClientResponse(ClientResponseOptionType.ClientInput);
}
async function handleSelfieAcquisition(idoResponse) {
const startToken = idoResponse.data?.start_token;
const acquisitionId = idoResponse.data?.acquisition_id;
if (startToken !== undefined) {
await idv.start(startToken);
}
await idv.captureSelfie({ acquisitionId });
return ido.submitClientResponse(ClientResponseOptionType.ClientInput);
}Platform IDV Recommendation is client-facing (transmit_platform_idv_recommendation) on web and mobile. Processing runs asynchronously on the backend. Keep calling submitClientResponse() with an empty client response until the journey proceeds to the next step or returns an error. Show a loader while processing runs. Mosaic recommends polling about once per second.
async function handleIdvRecommendation() {
let idoResponse;
do {
await new Promise((resolve) => setTimeout(resolve, 1000));
// If SDK was loaded via script tag, invoke functions inside 'window.tsPlatform'
idoResponse = await ido.submitClientResponse(ClientResponseOptionType.ClientInput);
} while (idoResponse.journeyStepId === IdoJourneyActionType.WaitForIdvRecommendations);
return handleJourneyResponse(idoResponse);
}- Implement fallback logic for cases where document capture fails.
- Use the verification result data (stored in the
idv_recommendationoutput variable) to enrich user profiles with verified personal information. - Instead of running capture on desktop, start the journey there and use cross-session messages to hand off verification to a mobile device.