OneSDK IDV flow

The OneSDK IDV flow has been designed to provide an all-in-one flow that you can use in your application's onboarding, to have OCR and Biometrics together.

The IDV flow is responsible for integrating seamlessly with Vendor SDKs. It will also automatically execute any API calls required by both FrankieOne and Vendor’s systems. The IDV flow can be instantiated with OneSDK’s instance factory method flow as shown below:

const oneSdk = await OneSDK({ session: { token }})
const idvFlow = oneSdk.flow("idv")

No matter the IDV vendor being used, the OneSDK IDV flow will always use the same simplified interface for initializing the data capture:


At this point, different UIs may be injected into the provided CSS selector, depending on the selected vendor. The OneSDK will take care of initializing them internally to ensure a consistent experience to both developer and final user.

A code snippet of a JavaScript implementation using this module can be found at the end of the page.


All communication from OneSDK to the host application is done via events. Among others, the relevant events the IDV Flow emits are:

  • session_data_generated, when the Vendor session was initiated by the OneSDK internally. This event will contain details specific to the vendor that might be relevant to your application
  • session_data_failed_loading, when the Vendor session was NOT initiated successfully.
  • ready, when the Vendor UI is mounted. This will also provide a reference to the HTML element created by OneSDK and injected into the provided container element. Most of the time this will be an iframe HTML element.
  • detection_complete, when data extraction is completed, but before checks are run.

Events for check results

The results can be interpreted based on the checkStatus. The OneSDK facilitates that interpretation by emitting different events for different checkStatus. This allows the host application to execute different procedures based on different results. The events are detailed
on the table below.



Not all Check statuses are returned for all Vendors. We attempt to make them as uniform as possible across vendors, but some might never happen.

Event nameCheck statusEvent dataDetails/notes
resultsCOMPLETE ,
{ checkStatus, document, entityId }- checkStatus: “COMPLETE” | “FAILED”
“COMPLETE”: The process and the check results
are ready.
“FAILED”: The process is done but there was a genuine failure validating the captured ID and face.
- document: the document object generated after the OCR extract
- entityId: FrankieOne’s internal reference for the
{ entityId }, checkStatusData is split into two parameters. This makes it consistent with other components of the OneSDK, such as the OCR component.
The first parameter is an object containing FrankieOne’s entity id for the individual. The second parameter is the checkStatus itself:
The uploaded ID is not valid. A valid Gov ID needs to be recaptured.
- “WAITING_DOC_UPLOAD”: There’s no ID doc
available to process or there was an issue with upload.
- “WAITING_SELFIE_UPLOAD”: There’s no face/selfie
available to process or there was an issue with the
- “INCOMPLETE”: The process or the result is not
complete, or some data is missing.
- “INTERRRUPTED”\: The process has been interrupted
or cancelled.
{ message, payload: { errorStatu }The event will emit an OneSDKError object containing:
- message : A human-readable error message
- payload : An object containing
errorStatus , the checkStatus that triggered the error
“PROVIDER_OFFLINE”: In case the IDV Vendor
is offline, unreachable.
“AWAITING_CONSENT”: User consent wasn’t
provided to the API. When you create an entity with Frankie API, you need to attach consent.
For more info on the consent, please visit this link.
( consent. general and are
the most important ones).
error-{ message }Any general error from the vendor, including 400 or 500,
will come here without any payload.

The enum/object IDVStatus is exported by the NPM package @frankieone/one-sdk .

export enum IDVStatus {
 // Results
 // Errors
 // Missing data

JavaScript/EJS Example

The following section provides an example of how to execute the IDV flow:

  1. In the backend, create a session token.
  2. Initialize OneSDK
    a. const oneSdk = await OneSDK({ session });
    b. const idvFlow = oneSdk.flow('idv');
  3. Setup event listeners
    a. idvFlow.on('results', ({ checkStatus }) => {...});
    optionally get a check summary with individual.submit({ verify: true });
    b. idvFlow.on('input_required', ({ checkStatus }) => {...});
    c. idvFlow.on('error', ({ message, payload: { errorStatus } }) => {...});
  4. Start IDV Flow
    a. idvFlow.mount("#idv-container");
// 1) In the backend, before rendering the page
// Retrieve token from FrankieOne's backend
const token = "some-jwt-from-frankieone";
<div id="idv-container"></div>
 	// 2) In the frontend, inject the token into the OneSDK initialiser
 	const oneSdk = await OneSdk({ session: '<%= token %>' });
 	// Keep a reference to the "individual" and "idv flow" modules
 	const individual = oneSdk.individual();
 	const idvFlow = oneSdk.flow('idv');
 	// Method to start or restart the idv flow
 	const startIdv = () => idvFlow.mount("#idv-container");
 	// Capture user consent, if not already done and 
  // provide it to "individual"
  if (captureConsent()) individual.addConsent('idv');
  else interruptFlow();
  // The module "IDV flow" exposes a dictionary of idv statuses using
  // friendlier names for better code clarity
  const idvStatus = idvFlow.statuses;
 // 3) Register all the event "reactions"
 idvFlow.on('results', ({ checkStatus, document, entityId }) => {
 	if (checkStatus === idvStatus.COMPLETE && shouldVerify) {
   // Once the extraction is COMPLETE, optionally retrieve the overall check result
   // using the module "individual"
   const checkSummary = await individual.submit({ verify: true });
   if (checkSummary.status.key === "PASS") showSuccessScreen();
   if (checkSummary.status.key === "FAIL") flagForManualIntervention();
  if (checkStatus === idvStatus.FAILED) flagForManualIntervention(entityId);
 idvFlow.on('input_required', ({ entityId }, checkStatus) => {
 idvFlow.on('error', ({ message, payload: { errorStatus }}) => {
   const isMissingConsent = errorStatus === idvStatus.AWAITING_CONSENT
   // In case the error is related to the consent not being captured
   // Attempt to capture the consent and provide it to the OneSDK
   // Restart the flow by calling the method "mount" again
   if (isMissingConsent && captureConsent()) {
 // Optional) Show loading animation
 // Immediately before initialising the IDV flow
   idvFlow.on('ready', hideLoading);
   // Between data detection is completed and checks are completed
   idvFlow.on('detection_complete', showLoading);
   idvFlow.on('results', hideLoading);
   idvFlow.on('input_required', hideLoading);
   idvFlow.on('error', hideLoading);

   // 4) Now start the idv flow by mounting it to the host application

Dummy mode for quick prototyping

The OneSDK offers a quick and easy way for the host application to prototype the IDV flow. By setting the option mode to dummy, the host application can provide additional mocking configurations and test different outcomes without actually executing any real checks or manual IDV captures.

const oneSdk = await OneSdk({
  session: ...,
  mode: {
    modeName: "dummy",
    idvFlow: {
      result: 'COMPLETE', 
      failGeneratingSession: false


A note on dummy mode

Dummy mode is currently in a work in progress. If you want to test this functionality, please contact FrankieOne Support.

Currently the IDV flow only implements a very basic mocked screen for the vendor, Mastercard, which should be enough for initial prototyping. The OneSDK would be configured automatically by the FrankieOne team within the system, but it can also be configured in the frontend for quick integration with the Dummy mode. For this use case, the configuration looks like this:

import OneSdk, { IDVStatus } from "@frankieone/one-sdk";
const oneSdk = await OneSdk({
  mode: {
    modeName: OneSdk.modes.DUMMY,
    mocks: {
 			idvFlowResult: IDVStatus.COMPLETE,
	 recipe: {
		 idv: {
			 provider: {
 				name: "mastercard",

Where mode.mocks.idvFlowResult can take any of the statuses mentioned above.