IDify Sessions (API)
The go-to solution for using Datakeen's screens in your application
Verification of Identity documents is essential for onboarding processes and KYC compliance. It allows you to confirm the identity of an individual, ensuring that they are who they claim to be. This is vital for preventing identity fraud and building trust with your customers.
As a developer looking to integrate Datakeen's screens in your application you can generate a IDify link that you can send to your end customers in order for them to capture their identity card and take a selfie. Results are available by API.
Please note that contrary to Off the Shelf APIs the host URL for IDify sessions is https://app.datakeen.co
I. Create sessions by API
1. Retrieve a new token (POST)
In order to retrieve a token you must make a POST call on the /auth endpoint. The token is valid 24h.
POST Request
curl --location 'https://app.datakeen.co/backend/auth' \
--header 'Content-Type: application/json' \
--data '{
"username": string,
"password": string
}'
const axios = require('axios');
let data = JSON.stringify({
"username": string,
"password": string
});
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://app.datakeen.co/backend/auth',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import http.client
import json
conn = http.client.HTTPSConnection("app.datakeen.co")
payload = json.dumps({
"username": string,
"password": string
})
headers = {
'Content-Type': 'application/json'
}
conn.request("POST", "/backend/auth", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
POST Answer
The POST answer is the following :
{
"status": 200,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2M2RhNzU4NGVmNWViYTAwMTIzNDRjOTciLCJmdWxsTmFtZSI6IkFkbWluIE9ueSIsImVtYWlsIjoiYWRtaW5AZGF0YWtlZW4uY29tIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNzI2NzM1MzUzLCJleHAiOjE3MjY4MjE3NTN9.PcdqdPstUO9ByVhkTuYRidmB-m-44M25SKykKs-FmKQ"
}
}
2. Retrieve session templates (GET)
If you have more than one session template for your customers. For example :
- Template 1 : verify identity document and selfie
- Template 2 : verify identity document and proof of address
You can retrieve template ids with the following call :
You must add a header with Authorization: Basic {token} to be authorized
GET Request
curl --location 'https://app.datakeen.co/backend/admin/templates'
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {token}'
const axios = require('axios');
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://app.datakeen.co/backend/api/v1/session/{sessionId}',
headers: { }
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import http.client
conn = http.client.HTTPSConnection("app.datakeen.co")
payload = ''
headers = {}
conn.request("GET", "/backend/api/v1/session/{sessionId}", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
GET Answer
[
{
"name": "Vérification Identité avec selfie",
"default": true,
"status": "active",
"_id": "6747253f954e810012b37zer",
"createdAt": "2024-11-27T13:57:19.752Z"
},
{
"name": "Vérification Identité et Justificatif de domicile",
"default": false,
"status": "active",
"_id": "6745fcdf34177200112cc345",
"createdAt": "2024-11-26T16:52:47.731Z"
}
]
You will receive a link to access the session, along with a sessionId and a QR code encoded in base64 if set to true.
3. Create a new session (POST)
A session corresponds to the verification of one client. Each session is single-use and comes with an expiration time of 1 hour. Once the expiration time has passed, you cannot perform ID verification using that session, and a new session must be created.
In order to retrieve a new session link (unique URL) you must make a POST call on the /session endpoint.
In option you can provide the following information : "templateId", "firstName", "lastName", "birthDate", "callbackURL", "webhookURL" and are detailed below :
POST Request
- templateId [OPTIONAL] : STRING - the unique identifier of the template
- firstName [OPTIONAL] : STRING - the first name of the person to verify
- lastName [OPTIONAL] : STRING - the last name of the person to verify
- birthDate [OPTIONAL] : STRING - the birth date of the person to verify ('dd/mm/yyyy' format)
- callbackURL [OPTIONAL] : STRING - a URL to redirect the user when the session is over
- webhookURL [OPTIONAL] : STRING -a URL to call when the session is over. The call made is a POST request with the following payload : {sessionId : ""}.
- QR : BOOLEAN [OPTIONAL] - True/False. option to generate a QR Code. This QR Code redirects the user to the unique session URL.
Authentication
You must add a header with Authorization: Basic {token} to be authorized
curl --location 'https://app.datakeen.co/backend/api/v1/session' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {token}' \
--data '{
"QR": boolean,
"firstName": "JEAN",
"lastName": "DUPONT",
"birthDate": "01/01/1970",
"webhookURL": "https://google.com",
"callbackURL": "https://google.com"
}'
const axios = require('axios');
let data = JSON.stringify({
"QR": boolean,
"firstName": `${firstname}`,
"lastName": `${lastName}`
});
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://app.datakeen.co/backend/api/v1/session',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic {token}'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import http.client
import json
conn = http.client.HTTPSConnection("app.datakeen.co")
payload = json.dumps({
"QR": True,
"firstName": "alex",
"lastName": "bdt"
})
headers = {
'Content-Type': 'application/json',
'Authorization': 'Basic {token}'
}
conn.request("POST", "/backend/api/v1/session", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
POST Answer
{
"status": 200,
"message": "Magic Link",
"data": {
"link": "https://app.datakeen.co/client/test?sessionId=662f5f9c9c18e30012c2f021",
"sessionId": "662f5f9c9c18e30012c2f021",
"QRCode": "data:image/png;base64,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"
}
}
You will receive a link to access the session, along with a sessionId and a QR code encoded in base64 if set to true.
4. Get the result of an IDify session by sessionId (GET)
You can retrieved the result of a past session with it's id.
You must add a header with Authorization: Basic {token} to be authorized
GET Request
curl --location 'https://app.datakeen.co/backend/api/v1/session/{sessionId}'
--header 'Content-Type: application/json' \
--header 'Authorization: Basic {token}'
const axios = require('axios');
let config = {
method: 'get',
maxBodyLength: Infinity,
url: 'https://app.datakeen.co/backend/api/v1/session/{sessionId}',
headers: { }
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import http.client
conn = http.client.HTTPSConnection("app.datakeen.co")
payload = ''
headers = {}
conn.request("GET", "/backend/api/v1/session/{sessionId}", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
GET Answer
{
"status": 200,
"message": "Analysis Completed Successfully",
"data": {
"analysid_id": "662f60359c8e30012c2f026",
"job_status": {
"predictions": [
{
"message": "Success",
"results": {
"controls": {
"matchNameInAllDocuments": {
"confidence": 1,
"value": true
}
},
"documents": [
{
"cardSide": "front-back",
"cardType": "national_id_card_fr_2003",
"controls": {
"dateValidity": {
"confidence": 0.9410978288185845,
"value": true
},
"dateValidityDelivery": {
"confidence": 0.8780886995840937,
"value": true
},
"globalStatus": {
"confidence": 1,
"score": 1,
"value": true
},
"initialsIsPresent": {
"confidence": 0.838485836982727,
"value": true
},
"matchFirstName": {
"confidence": 0.8,
"value": true
},
"matchFullName": {
"confidence": 0.8,
"value": true
},
"matchLastName": {
"confidence": 0.8,
"value": true
},
"mrzConformity": {
"confidence": 1,
"value": true
},
"mrzValidity": {
"confidence": 1,
"value": true
},
"photoIsPresent": {
"confidence": 0.9731155633926392,
"value": true
},
"rfSymbolIsPresent": {
"confidence": 0.8,
"value": false
},
"stampIsPresent": {
"confidence": 0.9458823204040527,
"value": true
},
"waveIsPresent": {
"confidence": 0.920028030872345,
"value": true
}
},
"entities": [
"b39076f8-c136-4a1f-ac71-c53684dae890"
],
"extractedInformation": {
"address": {
"bbox": {
"height": 0.045536440396186206,
"page_num": 1,
"topleft": [
0.5683991917675899,
0.14604948642527874
],
"width": 0.11743640092436902
},
"confidence": 0.8494784035838663,
"value": "rue test"
},
"birthCountry": {
"bbox": {},
"confidence": 0.9,
"value": "FR"
},
"birthDate": {
"bbox": {
"height": 0.027245300711734838,
"page_num": 0,
"topleft": [
0.8430066552675333,
0.19681494109217543
],
"width": 0.08184069041905984
},
"confidence": 0.8965237202750131,
"value": "11.07.1984"
},
"birthDateMRZ": {
"bbox": {},
"confidence": 1,
"value": "11.07.1984"
},
"birthDepartment": {
"bbox": {},
"confidence": 0.9,
"value": "58"
},
"birthPlace": {
"bbox": {
"height": 0.022571622609683206,
"page_num": 0,
"topleft": [
0.6871805064190977,
0.2220821740492335
],
"width": 0.05135558565409615
},
"confidence": 0.8697428888736098,
"value": "NEVERS"
},
"countryCode": {
"bbox": {},
"confidence": 0.9,
"value": "FR"
},
"deliveryDate": {
"bbox": {
"height": 0.020620277365525852,
"page_num": 1,
"topleft": [
0.5853487727431606,
0.2319673044194897
],
"width": 0.08293186911936967
},
"confidence": 0.8780886995840937,
"value": "07.10.2019"
},
"expiryDate": {
"bbox": {
"height": 0.024056998984073485,
"page_num": 1,
"topleft": [
0.6422509558976345,
0.20275524263725478
],
"width": 0.08474794177939848
},
"confidence": 0.9410978288185845,
"value": "06.10.2034"
},
"expiryDateMRZ": {
"bbox": {},
"confidence": 1,
"value": ""
},
"firstName": {
"bbox": {
"height": 0.039630294459557236,
"page_num": 0,
"topleft": [
0.7269859821361094,
0.14201411252160834
],
"width": 0.2369282917359432
},
"confidence": 0.8395038864262432,
"value": "Jean"
},
"firstNameMRZ": {
"bbox": {},
"confidence": 1,
"value": "Jean"
},
"fullName": {
"bbox": {
"height": 0.08199123166642099,
"page_num": 0,
"topleft": [
0.7031703150978688,
0.09965317531474459
],
"width": 0.2607439587741839
},
"confidence": 0,
"value": "Jean Jean"
},
"gender": {
"bbox": {
"height": 0.014224894868775456,
"page_num": 0,
"topleft": [
0.7042034107655684,
0.20430835442518494
],
"width": 0.009692559939918355
},
"confidence": 0.8518331084707675,
"value": "M"
},
"genderMRZ": {
"bbox": {},
"confidence": 1,
"value": ""
},
"idNumber": {
"bbox": {
"height": 0.027244652932953875,
"page_num": 0,
"topleft": [
0.7311969650988135,
0.062305901921633794
],
"width": 0.09856373280683195
},
"confidence": 0.9566656017742048,
"value": "000000000000"
},
"idNumberMRZ": {
"bbox": {},
"confidence": 1,
"value": "000000000000"
},
"lastName": {
"bbox": {
"height": 0.02393023063960656,
"page_num": 0,
"topleft": [
0.7031703150978688,
0.09965317531474459
],
"width": 0.04111142141210711
},
"confidence": 0.9243657590001533,
"value": "JEAN"
},
"lastNameMRZ": {
"bbox": {},
"confidence": 1,
"value": "JEAN"
},
"mrz": {
"bbox": {
"height": 0.09441730374946394,
"page_num": 0,
"topleft": [
0.5328696826349002,
0.36830785630293206
],
"width": 0.4396144585569075
},
"confidence": 0.9094363349968262,
"value": "IDJEAN<<<<<<<<<<<<<<<<<<<<<21ASKD"
},
"nationality": {
"bbox": {},
"confidence": 0.9,
"value": "FR"
},
"spouseName": {
"bbox": {},
"confidence": null,
"value": ""
}
},
"origin": "CNI.pdf",
"pages": [
{
"num": 0,
"path": "CNI.pdf",
"type": "national-id-card-fr-recto"
},
{
"num": 1,
"path": "CNI.pdf",
"type": "national-id-card-fr-verso"
}
],
"path": "CNI_jean-jean.pdf",
"type": "id-card"
},
{
"entities": [],
"extractedInformation": {},
"origin": "Screenshot 2024-04-29 at 09.29.59.png",
"pages": [
{
"num": 0,
"path": "Screenshot 2024-04-29 at 09.29.59.png",
"type": ""
}
],
"path": "",
"type": "other"
}
],
"entities": [
{
"firstName": "Jean,
"fullName": "Jean Jean",
"id": "b39076f8-c136-4a1f-ac71-c53684dae890",
"lastName": "Jean"
}
],
"report": null
},
"status": 200,
"verificationId": "",
"webhook": null
}
]
}
}
}
II. Common integrations into mobile applications
React Native
Here is an example of an integration of the session in React Native
For each client generate a session thanks to the create a new session API call.
Redirect the client to the given session in a web view, like so :
import WebView from "react-native-webview";
export function DatakeenScreen() {
return (
<WebView
allowsInlineMediaPlayback
source={{
uri: "https://staging.datakeen.co/client/test?sessionId=6634a788316f3d00116c4378",
}}
/>
);
}
At the end of the session a webhook is called.
Flutter
Here is an example of an integration of the session in Flutter
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
Widget buildWebView() {
return WebView(
initialUrl: 'https://staging.datakeen.co/client/test?sessionId=6634abb6316f3d00116c4578',
javascriptMode: JavascriptMode.unrestricted,
);
}
Updated 16 days ago