How-to use Web SDK
Learn how to create a simple identity validation web app using the Incode Web SDK
Prerequisites
Please, you have read the following guides:
Sample Code
You can find sample code for this approach in Code Samples for Web Integrations, it includes a fake_backend.js
with all the steps that will be needed to move to a formal backend for production.
Steps
In the first part of this guide, you will learn how to initialize and run an onboarding web app using the Incode Web SDK.
We will use a linear approach, where all Incode verification modules are executed one after the other, as in the following diagram:

This approach is the most convenient for scenarios where you want your users to go through all the Incode modules before they go further on your application.
Setup project
For this guide, you will need the following project structure:
my-incode-app
|__ index.html
|__ app.js
my-incode-app
|__index.html
|__main.js
|__package.json
|__.env
Setup your HTML
Some SDK methods require an HTML element to contain the UI components. A div
element with the id incode-container
will hold the SDK components. https://demo-api.incodesmile.com/0/
index.html
<!DOCTYPE html>
<html lang="en" translate="no">
<head>
<title>Incode WebSdk</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="google" content="notranslate">
<script src="https://sdk.incode.com/sdk/onBoarding-<<WEB_SDK_VERSION>>.js" defer></script>
<script src="./app.js" defer></script>
</head>
<body>
<div id="incode-container"></div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" translate="no">
<head>
<title>Incode WebSdk</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="google" content="notranslate">
</head>
<body>
<div id="incode-container"> </div>
<script type="module" src="/main.js"></script>
</body>
</html>
Known Issue: DOM mutations by Google Translate
Observe the
translate="no"
attribute at thehtml
tag and the<meta name="google" content="notranslate">
within thehead
tag. Make sure to include them in your project to prevent undesired DOM mutations from Google Chrome's Translate functionality that may provoke DOM errors in your integration.If your application requires multiple languages, please read out guide on how to include and customize String Localizations
Initializing the Web SDK
- Initialize the Incode Web SDK using the
create
method - Create a new Onboarding Session.
- Create a reference to the HTML element that will contain the SDK UI components.
app.js
let incode;
async function app(){
incode = await window.OnBoarding.create({
apiURL: "{user.DEMO_URL_0}" // API URL provided by Incode
});
}
document.addEventListener("DOMContentLoaded", app);
import { create } from '@incodetech/welcome';
let incode;
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>", // API URL provided by Incode
});
}
document.addEventListener("DOMContentLoaded", app);
Fetching a session
object
session
objectCreate a session object
An Onboarding Session Token (or just "session token") is required to link all the user information and validation results.
📘 Make sure to read the guide on creating onboarding sessions from your application backend before continuing with this guide:How to Create an Onboarding Session?.
Saving the session token for later
If you already know how to create an onboarding session, you can fetch a new session object from your application backend and save the response in a variable (session
) for later use:
let incode;
let session;
async function app(){
incode = await window.OnBoarding.create({
apiURL: "{user.DEMO_URL_0}" // API URL provided by Incode
});
// Get the session from your backend
session = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);
import { create } from '@incodetech/welcome';
let incode;
let incodeSession;
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>", // API URL provided by Incode
});
// Get the session from the backend
incodeSession = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);
Using the Onboarding session
Object
session
ObjectThe session object will contain two properties:
{
token:"abc123",
interviewId:"xyz098"
}
token
: the session token that will be sent in every call to the Incode Omni APIinterviewId
: the unique identifier of the current Incode onboarding session
In almost all cases, you will need the full.session
object value as an input parameter for the SDK methods. However, specific methods only require the token
value. Ensure you read our official SDK Methods reference to know when to use each.
Organize your code:
To maintain a well-organized code, having a function for each step is a good practice.
1.- Check for any aplicable Mandatory Biometric Consent
Laws around the world might require you to get Biometric Consent to continue the process, but keeping track of the exact conditions that apply to your user is hard, that's why we simplified this process by returning a boolean result in our sendFingerprint()
method that clearly show you if a biometric consent is necessary and provides the relevant regulationType
of such consent.
You can then show the relevant biometric consent using renderBiometricConsent()
.
In almost all cases your end user will never see this consent, but this will change as privacy laws get more strict.
const incodeContainer = document.querySelector("#incode-container");
// 1.- Check if mandatory consent is required. and show it if it is.
function checkMandatoryConsent() {
incode.sendFingerprint({ token: incodeSession.token }).then((response) => {
// Send fingerprint returns a response with the following structure:
// {
// "success": true,
// "sessionStatus": "Alive",
// "ipCountry": "UNITED STATES",
// "ipState": "ILLINOIS",
// "showMandatoryConsent": true,
// "regulationType": "US_Illinois"
// }
// If the response has showMandatoryConsent and is set to true, we need to show the mandatory consent
if (response?.showMandatoryConsent) {
incode.renderBiometricConsent(incodeContainer, {
token: incodeSession,
onSuccess: captureCombinedConsent,
onCancel: () => showError("Mandatory consent was denied"),
regulationType: response.regulationType,
});
} else {
captureCombinedConsent();
}
});
}
International Privacy Laws are Hard
The laws around biometric consent apply to you depending on where the user is from and where the customer is accessing your system—even if they are using a VPN.
Laws can change from country to country and even from state to state, and you might be subject to fines and penalties even if you didn't know you had to get proper consent from the user.
Using this pattern of integration, you can leverage Incode's system to detect if the end user's location is subject to such regulations. Further verifications will be done once we know the user's geolocation via GPS and later when we analyze their ID card to determine their origin.
Capture flow:
Notice that the
onSuccess
callback it's being used to execute the function corresponding to the next step of the flow to create a "linear" experience for the user.
2.- Show the Combined Consent
Before being able to get anymore information from the end user, you will need to ask for their consent, our combinedConsent module make it easy, please take a look a the documentation , create your first consent and get the consentId
from Configuration > Consents

Once armed with the consentId
create the following function in your app.js
// 2.- Show the combined consent
// This consent is created in the dashboard and has to be passed as a parameter
// to the renderCombinedConsent function.
function captureCombinedConsent() {
incode.renderCombinedConsent(incodeContainer, {
token: incodeSession,
onSuccess: sendGeolocation,
consentId: consentId, // id of a consent created in dashboard
});
}
3.- Capture the Geolocation
// 3.- Send geolocation and start the ID capture flow
function sendGeolocation() {
incode.sendGeolocation({ token: incodeSession.token });
captureId();
}
4.- Capture and validate an ID card
There are two steps to validate an ID card:
- Capture the front and back sides of the ID
- Execute the ID validation process
Capture the front and back sides of the ID using the renderCaptureId()
method.
renderCaptureId()
method.The renderCaptureId()
method is a ready-to-use component capable of activating the device camera and presenting a capture assistant to capture the Id
The following code shows how to implement the renderCaptureId()
method to create a flow for the user to capture both sides of the ID:
// 4.- Capture the ID
function captureId() {
incode.renderCaptureId(incodeContainer, {
session: incodeSession,
onSuccess: processId,
onError: showError,
forceIdV2: false //default to false
});
}
Important: Omni Dashboard configuration required.
Most of the options and settings for renderCaptureId such as number of capture attempts, manual-capture timeout or optional tutorials are configured from your Incode Omni Dashboard.
renderCamera()
expects three arguments:
container
(HTMLElement
): The container HTML element that will hold the UI component. In this case, you can see we have selected the element with idincode-container
optionsObject
(object
): The configuration options for the method:token
(object
): the fullsession
objectonSuccess
(function
): A callback to be executed after a successful capture.onError
(function
): A callback to be executed if the number of tries is reached.forceIdv2
(boolean
): If you want to forcibly enable the new Id capture experience, set totrue
, if not, it will dynamically adjust how many of your users it will present the old and the new capture experience.
Requesting permissions for the device camera:
The Web SDK takes care of requesting the use of the device's camera to the user. The camera cannot be activated without the user explicitly allowing its use.
If the user denies the use of the camera, the
renderCaptureId()
method will trigger theonError
callback with the error messageDOMException: Permission denied
which means the ID capture and validation cannot be performed.
5.- Process the Id
Identity validations and OCR extraction occur on the Incode platform. For that, we need to trigger the processing of the ID using the processId()
method:
// 5.- Process the ID
async function processId() {
return incode.processId({ token: incodeSession.token })
.then(() => {
captureSelfie();
})
.catch((error) => {
showError(error);
});
}
processId()
expects one argument:
optionsObject
(object
):token
(string
): The sessiontoken
value. As you can see, we are taking the token property value from thesession
object.
processId()
returns a promise. If the promise is resolved, the ID is processed. If it is rejected, it means there was an error trying to process the ID.
In this example, we are using then
to execute the next step of the user flow and catch
to display the error in the console.
processId()
does not return the result of the validation:The
processId()
method does not return neither scores or OCR data of the ID document. Validation scores and OCR data must be requested in your application backend.
6.- Validate the user selfie against the ID
The next step of the validation flow is to compare the face of the user against the photo in the ID. For that, we will use the renderCamera()
method one more time:
// 6.- Capture the selfie
function captureSelfie() {
incode.renderCaptureFace(incodeContainer, {
session: incodeSession,
onSuccess: finishOnboarding,
onError: showError,
forceV2: false //default to false
});
}
As you can notice, we are using the same configuration options for the ID capture step, but this time, we are the forceV2
option is slidghtly different in ide is forceIdV2
.
Important: Omni Dashboard configuration required.
Most of the options and settings for renderCaptureFace such as number of capture attempts, manual-capture timeout or optional tutorials are configured from your Incode Omni Dashboard.
7.- Mark the onboarding session as completed
Marking an onboarding session as completed tells the Incode platform that the user has finished all flow steps regardless of the scores. This is a critical step because it will tell you how many users went through all the steps from start to finish.
For this, you must call the Mark onboarding complete endpoint from your backend., you will need to pass the session token for the backend to be able to mark the session.
At this point, your app.js
The file should look like this:
let incode;
let incodeSession;
const incodeContainer = document.getElementById("camera-container");
// 1.- Check if mandatory consent is required. and show it if it is.
function checkMandatoryConsent() {
incode.sendFingerprint({ token: incodeSession.token }).then((response) => {
// Send fingerprint returns a response with the following structure:
// {
// "success": true,
// "sessionStatus": "Alive",
// "ipCountry": "UNITED STATES",
// "ipState": "ILLINOIS",
// "showMandatoryConsent": true,
// "regulationType": "US_Illinois"
// }
// If the response has showMandatoryConsent and is set to true, we need to show the mandatory consent
if (response?.showMandatoryConsent) {
incode.renderBiometricConsent(incodeContainer, {
token: incodeSession,
onSuccess: captureCombinedConsent,
onCancel: () => console.log("Mandatory consent was denied"),
regulationType: response.regulationType,
});
} else {
captureCombinedConsent();
}
});
}
// 2.- Show the combined consent
// This consent is created in the dashboard and has to be passed as a parameter
// to the renderCombinedConsent function.
function captureCombinedConsent() {
incode.renderCombinedConsent(incodeContainer, {
token: incodeSession,
onSuccess: sendGeolocation,
consentId: < CONSENT ID >, // id of a consent created in dashboard
});
}
// 3.- Send geolocation and start the ID capture flow
function sendGeolocation() {
incode.sendGeolocation({ token: incodeSession.token });
captureId();
}
// 4.- Capture the ID
function captureId() {
incode.renderCaptureId(incodeContainer, {
session: incodeSession,
onSuccess: processId,
onError: console.log,
forceIdV2: forceV2 // Use the global V2 flag
});
}
// 5.- Process the ID
async function processId() {
return incode.processId({ token: incodeSession.token })
.then(() => {
captureSelfie();
})
.catch((error) => {
console.log(error);
});
}
// 6.- Capture the selfie
function captureSelfie() {
incode.renderCaptureFace(incodeContainer, {
session: incodeSession,
onSuccess: finishOnboarding,
onError: console.log,
forceV2: forceV2 // defaults to false
});
}
// 7.- Finish the onboarding
function finishOnboarding() {
myFinishSessionRequestMethod(incodeSession.token)
.then((response) => {
console.log('Finished');
})
.catch((e) => {
console.log(e);
});
}
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>", // API URL provided by Incode
});
// Get the session from the backend
incodeSession = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);
import { create } from '@incodetech/welcome';
let incode;
let session;
const incodeContainer = document.querySelector("#incode-container");
function captureIdFrontSide() {
incode.renderCamera("front", incodeContainer, {
token: session,
numberOfTries: 3,
onSuccess: captureIdBackSide,
onError: console.log,
showTutorial: true,
});
}
function captureIdBackSide() {
incode.renderCamera("back", incodeContainer, {
token: session,
numberOfTries: 3,
onSuccess: validateId,
onError: console.log,
showTutorial: true,
});
}
function validateId() {
return incode.processId({ token: session.token })
.then(() => {
captureSelfie();
})
.catch((error) => {
console.log(error);
});
}
function captureSelfie() {
incode.renderCamera("selfie", container, {
token: session,
numberOfTries: 3,
onSuccess: () => mySessionFinishMethod(session.token),
onError: console.log,
showTutorial: true,
});
}
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>"
});
//Store the session object in a variable for later use
session = await mySessionRequestMethod();
}
document.addEventListener("DOMContentLoaded", app);
Start the flow
Go to the app()
function and add the first step of the flow by calling the captureIdFrontSide()
function:
async function app() {
incode = create({
apiURL: "<<DEMO_URL_0>>", // API URL provided by Incode
});
// Get the session from the backend
incodeSession = await mySessionRequestMethod();
// Run first step in the validation
checkMandatoryConsent();
}
Testing your app
Your application should be fully functional at this point. Here are some recommendations for making it available for testing.
HTTPS
All HTTP requests executed from the Web SDK are secured. Run your application over HTTPS; otherwise, it may cause mixed content warnings and CORS errors.
Development servers
Incode Web SDK is compatible with most development environments and frameworks like Express and Vite. You can use a local server or make it public so others can test it.
Testing and production environments:
Please make sure you use the Incode testing environment during your development process. Using the Incode production environment may result in service charges in your account. Please contact us to know more about the service fees.
Updated 8 days ago
Now that your identity validation app is complete, it's time to check the results of each onboarding.