Digital Onboarding
Here you will find an overview of how to implement a digital onboarding use case with Alice Onboarding.
Onboarding flow
The digital onboarding process can be divided into 3 steps:
- User creation: your backend registers a new user.
- User onboarding: the user uploads a selfie and N documents to the Alice Onboarding platform.
- Report processing: your backend gets and checks the onboarding result.
1. User creation
Create a user from your backend in the Alice Onboarding API.
curl --request POST \
--url https://apis.alicebiometrics.com/onboarding/user \
--header 'Authorization: Bearer <BACKEND_TOKEN>' \
--header 'Content-Type: multipart/form-data' \
--form email=example@example.com
from alice import Config, Onboarding
ALICE_ONBOARDING_API_KEY="<YOUR-API-KEY>"
config = Config(api_key=ALICE_ONBOARDING_API_KEY)
onboarding = Onboarding.from_config(config)
user_id = onboarding.create_user(verbose=True).unwrap()
2. User onboarding
From the client-side (front-end), the user starts the onboarding and captures a selfie and some documents. This can be done manually by calling the API or automatically by taking advantage of the capture functionalities of the SDKs.
curl --request POST \
--url <https://apis.alicebiometrics.com/onboarding/user/selfie> \
--header 'Authorization: Bearer <USER_TOKEN>' \
--header 'Content-Type: multipart/form-data' \
--form video=@/path/to/selfie/video.mp4
curl --request POST \
--url https://apis.alicebiometrics.com/onboarding/user/document \
--header 'Authorization: Bearer <USER_TOKEN>' \
--header 'Content-Type: multipart/form-data' \
--form type=<DOCUMENT_TYPE> \
--form issuing_country=<ISSUING_COUNTRY>
curl --request PUT \
--url https://apis.alicebiometrics.com/onboarding/user/document \
--header 'Authorization: Bearer <USER_TOKEN>' \
--header 'Content-Type: multipart/form-data' \
--form document_id=<DOCUMENT_ID> \
--form side=<DOCUMENT_SIDE> \
--form image=@/path/to/doc/image.jpeg \
--form manual=true \
--form source=file
from alice import Config, Onboarding
ALICE_ONBOARDING_API_KEY="<YOUR-API-KEY>"
config = Config(api_key=ALICE_ONBOARDING_API_KEY)
//Upload a selfie (Recommended 1-second video)
SELFIE_MEDIA_DATA=open(f"{RESOURCES_PATH}/selfie.png", "rb").read()
onboarding.add_selfie(
user_id=user_id, media_data=SELFIE_MEDIA_DATA
)
//Create and upload front and back side from a document
document_id = onboarding.create_document(
user_id=user_id, type="idcard", issuing_country="ESP"
).unwrap()
DOCUMENT_FRONT_MEDIA_DATA=open(f"{RESOURCES_PATH}/idcard_esp_front_example.png", "rb").read()
onboarding.add_document(
user_id=user_id,
document_id=document_id,
media_data=DOCUMENT_FRONT_MEDIA_DATA,
side="front",
manual=True,
)
DOCUMENT_BACK_MEDIA_DATA=open(f"{RESOURCES_PATH}/idcard_esp_back_example.png", "rb").read()
onboarding.add_document(
user_id=user_id,
document_id=document_id,
media_data=DOCUMENT_BACK_MEDIA_DATA,
side="back",
manual=True,
)
let userToken = "<ADD-YOUR-USER-TOKEN-HERE>"
let config = OnboardingConfig.builder()
.withUserToken(userToken)
.withAddSelfieStage()
.withAddDocumentStage(ofType: .idcard, issuingCountry: "ESP")
let onboarding = Onboarding(self, config: config)
onboarding.run { result in
switch result {
case let .success(userStatus):
print("userStatus: (String(describing: userStatus))")
case let .failure(error):
print("failure: (error.localizedDescription)")
case .cancel:
print("User has cancelled the onboarding")
}
}
val userToken = "<ADD-YOUR-USER-TOKEN-HERE>"
val config = OnboardingConfig.builder()
.withUserToken(userToken)
.withAddSelfieStage()
.withAddDocumentStage(type = DocumentType.IDCARD, issuingCountry = "ESP")
val onboarding = Onboarding(this, config: config)
onboarding.run(ONBOARDING_REQUEST_CODE)
...
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == ONBOARDING_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
val userInfo = data!!.getStringExtra("userStatus")
} else if (resultCode == Activity.RESULT_CANCELED) {
}
}
}
const ONBOARDING_CONFIG = {
"stages": [
{"stage": "addSelfie"},
{"stage": "addDocument", "type": "idcard", "issuingCountry": "ESP"},
]
}
<Onboarding
userToken={userToken}
config={ONBOARDING_CONFIG}
onSuccess={(userStatusJson) => console.log("onSuccess:" + userStatusJson) }
onFailure={(failureJson) => console.log("onFailure:" + failureJson)
onCancel={(value) => console.log("onCancel:" + value) }
/>
let userToken = "<ADD-YOUR-USER-TOKEN-HERE>"
let config = new aliceonboarding.OnboardingConfig()
.withUserToken(userToken)
.withAddSelfieStage()
.withAddDocumentStage(aliceonboarding.DocumentType.IDCARD)
function onSuccess(userInfo) {console.log("onSuccess: " + userInfo)}
function onFailure(error) {console.log("onFailure: " + error)}
function onCancel() { console.log("onCancel")}
new aliceonboarding.Onboarding("alice-onboarding-mount", config).run(onSuccess, onFailure, onCancel);
3. Report processing
After the user's onboarding has finished, you will receive a callback
from the client-side SDK into your app. Then, from your backend, you
should ask for a Report
. A report
collects all the information extracted for a user during the onboarding
process.
curl --request GET \
--url https://apis.alicebiometrics.com/onboarding/user/report> \
--header 'Authorization: Bearer <BACKEND_TOKEN_WITH_USER_ID>' \
--header 'Content-Type: multipart/form-data' \
--header 'Alice-Report-Version: <1>'
from alice import Config, Onboarding
ALICE_ONBOARDING_API_KEY="<YOUR-API-KEY>"
config = Config(api_key=ALICE_ONBOARDING_API_KEY)
report = onboarding.create_report(
user_id=user_id
).unwrap_or_throw()
If the document's results do not fulfill your criteria (see How to accept an Onboarding), you should invalidate (void) the user's document and/or selfie and ask him/her to repeat the onboarding.
3.1 Invalidate selfie
curl --request PATCH \
--url <https://apis.alicebiometrics.com/onboarding/user/selfie> \
--header 'Authorization: Bearer <BACKEND_TOKEN_WITH_USER_ID>'
from alice import Config, Onboarding
ALICE_ONBOARDING_API_KEY="<YOUR-API-KEY>"
config = Config(api_key=ALICE_ONBOARDING_API_KEY)
onboarding.void_selfie(
user_id=user_id
).unwrap_or_throw()
3.1 Invalidate document
curl --request PATCH \
--url https://apis.alicebiometrics.com/onboarding/user/document/<DOCUMENT_ID> \
--header 'Authorization: Bearer <BACKEND_TOKEN_WITH_USER_ID>' \
--header 'Content-Type: application/merge-patch+json' \
--data '{"voided": true}'
from alice import Config, Onboarding
ALICE_ONBOARDING_API_KEY="<YOUR-API-KEY>"
config = Config(api_key=ALICE_ONBOARDING_API_KEY)
onboarding.void_document(
user_id=user_id,
document_id=document_id
).unwrap_or_throw()
How to accept an onboarding
In this section we show you how to analyze the results of an onboarding and define your acceptance criteria.
The acceptance criteria can be divided into 2 stages:
- Checking the document data
- Checking the selfie data
Warning
This flow has been designed to optimized user automatic conversion. If your use case differs, the integration might be different.
In the case of retrying the onboarding a couple of times and still having problems with face validation, liveness or data gathered, we suggest having a manual verification.
1. Check the document data
1.0. Get the document report
The document report collects all the necessary info to accept or deny a document. Take a look at the Document report included at the documents array.
{
"created_at": "2021-07-20T15:16:33.845112",
"documents": [
{
"checks": [],
"created_at": "2021-03-02T09:13:15",
"id": "67101f93-5525-48b9-aced-67bf557a6382",
"meta": {},
"sides": {},
"summary_fields": []
}
],
"events": [],
"id": "8d2ce06e-a80e-47a3-8095-ab7a677675a8",
"selfies": [],
"summary": {},
"user_id": "deb78277-af90-47b6-b3b7-461129a819bf",
"version": 1
}
1.1. Check if the document is complete
The first step is to check whether the document is complete. This means that every side was successfully uploaded.
If it is incomplete, you should invalidate (void) the document and ask the user to capture it again.
{
"created_at": "2021-07-20T15:16:33.845112",
"documents": [
{
"checks": [],
"created_at": "2021-03-02T09:13:15",
"id": "67101f93-5525-48b9-aced-67bf557a6382",
"meta": {
"completed": true,
"issuing_country": "AUTO",
"type": "passport",
"voided": false
},
"sides": {},
"summary_fields": []
}
],
"events": [],
"id": "8d2ce06e-a80e-47a3-8095-ab7a677675a8",
"selfies": [],
"summary": {},
"user_id": "deb78277-af90-47b6-b3b7-461129a819bf",
"version": 1
}
1.2 Define your document checks
Our API implements some checks that might be suitable for you to accept or deny a document. For instance, checking whether the selfie and the document are from the same person, whether the document has expired,whether the document is fake, etc.
The Report includes Check elements.These are collected at the checks array of the Document report. Please see which are available at the Document-level-checks section.
Each check has a value between 0-100 or null. If its value is greater or equal to 50, the condition is met. Null values mean that the check does not apply. Therefore, a null value should never be a reason for rejection. It only means that there is not enough evidence to compute it.
If the checks you have selected are not met, you should invalidate (void) the document and ask the user to capture it again.
{
"created_at": "2021-07-20T14:13:12.295516",
"documents": [
{
"checks": [
{
"detail": "The document and active selfie faces are from the same person",
"key": "face_matching",
"value": 99.539
},
{},
{}
],
"created_at": "2021-03-02T09:13:15",
"id": "67101f93-5525-48b9-aced-67bf557a6382",
"meta": {},
"sides": {},
"summary_fields": [],
}
],
"events": [],
"id": "22e50a8c-1ff7-4e97-87b2-59b042a2e3d2",
"selfies": [],
"summary": {},
"user_id": "deb78277-af90-47b6-b3b7-461129a819bf",
"version": 1
}
1.3. Define and check your key fields
First, you need to define which common document fields are suitable for your use case. Please check the Fields per document section.
Most customers choose at least these 5 fields:
first_name
last_name
birth_date
expiration_date
id_number
/license_number
/passport_number
You will find all the fields read by Alice OCR technology at the summary_fields section of the Document report. A Document Field contains:
- A
name
- A
value
- A
score
, which holds the reading confidence - An array of Check elements see Field-level checks
A field is considered as well read if one of these two conditions is met:
- The
checked_field
check IS in the array of checks and its value is greater than or equal to 50. - The
checked_field
check IS NOT in the array of checks but the field's score is greater than or equal to 70.
If none of these is fulfilled, you should invalidate (void) the document and ask the user to capture it again.
{
"created_at": "2021-07-20T15:16:33.845112",
"documents": [
{
"checks": [],
"created_at": "2021-03-02T09:13:15",
"id": "67101f93-5525-48b9-aced-67bf557a6382",
"meta": {},
"sides": {},
"summary_fields": [
{
"checks": [
{
"detail": "The field passes its checksum",
"key": "checked_field",
"value": 100
}
],
"name": "id_number",
"score": 91,
"value": "99999999R"
}
]
}
],
"events": [],
"id": "8d2ce06e-a80e-47a3-8095-ab7a677675a8",
"selfies": [],
"summary": {},
"user_id": "deb78277-af90-47b6-b3b7-461129a819bf",
"version": 1
}
2. Check the selfie data
Finally, review the selfie's liveness to check whether it is from a real person. This analysis detects signs of spoofing attacks through printed pictures, videos shown on screens, masks, etc.
{
"created_at": "2021-07-20T14:13:12.295516",
"documents": [],
"events": [],
"id": "22e50a8c-1ff7-4e97-87b2-59b042a2e3d2",
"selfies": [{
"checks": [
{
"detail": "The selfie is from a real person",
"key": "liveness",
"value": 78.25
},
{},
],
"created_at": "2021-11-09T09:16:11",
"id": "505b89cc-6799-4167-8f97-5d3ac6d07a6c",
"media": {},
"number_of_faces": 1,
"voided": false
}],
"summary": {},
"user_id": "deb78277-af90-47b6-b3b7-461129a819bf",
"version": 1
}
Reference liveness threshold: 50, as any other check
If the liveness score is below the recommended threshold, you should void the user's selfie and ask the user to repeat its capture.