ID Card
Comprehensive capture and extraction of National ID Cards.
Verification of ID cards 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.
Introduction
Datakeen's OCR service automatically extracts information from French ID Card. The platform handles 2003 and 2021 models.
- Information is captured as structured data and can be extracted as a .json file through our API.
- MRZ controls are information based checks operated on the MRZ band located on the front side of the card.
- Authenticity checks generate a compliance score to determine whether the card is authentic.
2003 Model
Extracted information | MRZ controls | Authenticity checks |
---|---|---|
- Name - Surnames - Spouse name - Date of birth - Place of birth - State of birth - Country of citizenship - Gender - Address - Delivery date - Expiry date - Card number - Country code | - MRZ band - Name on the MRZ - Surname on the MRZ - Card number on the MRZ - Date of birth on the MRZ | - Validity check - Delivery date check - Detection of identity photo - Detection of RF symbol - Detection of stamp - Detection of waves - Detection of initials - Public domain presence check |
2021 Model
Extracted information | MRZ controls | Authenticity checks |
---|---|---|
- Name - Surnames - Spouse name - Date of birth - Place of birth - State of birth - Country of citizenship - Gender - Address - Delivery date - Expiry date - Card number - Country code | - MRZ band - Name on the MRZ - Surname on the MRZ - Card number on the MRZ - Date of birth on the MRZ | - Compliance status - Validity control - Compliance control - Validity check - Detection of id photo - Detection of chip - Detection of hologram - Public domain presence check |
Setting up the API
The synchronous API model extracts data from ID cards in real time. The synchronous API model also performs verification checks in order to control Document Validity, MRZ conformity and Data consistency.
API token is required
In order to perform any call, you will need an API token that can be retrieved with your API credentials. To learn about authentification, please refer to this page
curl --request POST \
--url https://api.datakeen.co/api/v1/reco/id \
--header 'accept: application/json' \
--header 'content-type: application/json'
npm install api --save
const sdk = require('api')('@datakeen/v1.4.0#ax268r1ilnd0liqe');
sdk.postRecoId()
.then(({ data }) => console.log(data))
.catch(err => console.error(err));
require 'uri'
require 'net/http'
url = URI("https://api.datakeen.co/api/v1/reco/id")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["accept"] = 'application/json'
request["content-type"] = 'application/json'
response = http.request(request)
puts response.read_body
composer require guzzlehttp/guzzle
<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.datakeen.co/api/v1/reco/id', [
'headers' => [
'accept' => 'application/json',
'content-type' => 'application/json',
],
]);
echo $response->getBody();
python -m pip install requests
import requests
url = "https://api.datakeen.co/api/v1/reco/id"
headers = {
"accept": "application/json",
"content-type": "application/json"
}
response = requests.post(url, headers=headers)
print(response.text)
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, stdout);
curl_easy_setopt(hnd, CURLOPT_URL, "https://api.datakeen.co/api/v1/reco/id");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "accept: application/json");
headers = curl_slist_append(headers, "content-type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
CURLcode ret = curl_easy_perform(hnd);
dotnet add package RestSharp
using RestSharp;
var options = new RestClientOptions("https://api.datakeen.co/api/v1/reco/id");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("accept", "application/json");
request.AddHeader("content-type", "application/json");
var response = await client.PostAsync(request);
Console.WriteLine("{0}", response.Content);
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, stdout);
curl_easy_setopt(hnd, CURLOPT_URL, "https://api.datakeen.co/api/v1/reco/id");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "accept: application/json");
headers = curl_slist_append(headers, "content-type: application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
CURLcode ret = curl_easy_perform(hnd);
(require '[clj-http.client :as client])
(client/post "https://api.datakeen.co/api/v1/reco/id" {:content-type :json
:accept :json})
package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.datakeen.co/api/v1/reco/id"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("accept", "application/json")
req.Header.Add("content-type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}
POST /api/v1/reco/id HTTP/1.1
Accept: application/json
Content-Type: application/json
Host: api.datakeen.co
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.datakeen.co/api/v1/reco/id")
.post(null)
.addHeader("accept", "application/json")
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();
const options = {
method: 'POST',
headers: {accept: 'application/json', 'content-type': 'application/json'}
};
fetch('https://api.datakeen.co/api/v1/reco/id', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
val client = OkHttpClient()
val request = Request.Builder()
.url("https://api.datakeen.co/api/v1/reco/id")
.post(null)
.addHeader("accept", "application/json")
.addHeader("content-type", "application/json")
.build()
val response = client.newCall(request).execute()
#import <Foundation/Foundation.h>
NSDictionary *headers = @{ @"accept": @"application/json",
@"content-type": @"application/json" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.datakeen.co/api/v1/reco/id"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[request setAllHTTPHeaderFields:headers];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"%@", error);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSLog(@"%@", httpResponse);
}
}];
[dataTask resume];
opam install cohttp-lwt-unix cohttp-async
open Cohttp_lwt_unix
open Cohttp
open Lwt
let uri = Uri.of_string "https://api.datakeen.co/api/v1/reco/id" in
let headers = Header.add_list (Header.init ()) [
("accept", "application/json");
("content-type", "application/json");
] in
Client.call ~headers `POST uri
>>= fun (res, body_stream) ->
(* Do stuff with the result *)
$headers=@{}
$headers.Add("accept", "application/json")
$headers.Add("content-type", "application/json")
$response = Invoke-WebRequest -Uri 'https://api.datakeen.co/api/v1/reco/id' -Method POST -Headers $headers
library(httr)
url <- "https://api.datakeen.co/api/v1/reco/id"
response <- VERB("POST", url, content_type("application/json"), accept("application/json"))
content(response, "text")
import Foundation
let headers = [
"accept": "application/json",
"content-type": "application/json"
]
let request = NSMutableURLRequest(url: NSURL(string: "https://api.datakeen.co/api/v1/reco/id")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error as Any)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
Sending multiple documents
The API accepts one card at a time, the front and back of the same card can be sent in the same request. If you want to send multiple scans at the same time, please refer to the multi-docs API.
API Response
An instance of the usual response is displayed in the following JSON. You will find the complete information, including extraction and checks. More detailed examples of each extracted field are given below.
{
"cardSide": "front",
"cardType": "national_id_card_fr_2003",
"controls": {
"dateValidity": {
"confidence": null,
"value": null
},
"dateValidityDelivery": {
"confidence": 0,
"value": null
},
"globalStatus": {
"confidence": 1,
"score": 0.6,
"value": true
},
"initialsIsPresent": {
"bbox": {
"height": 0.04934210702776909,
"topleft": [
0.251162800937891,
0.20065789856016636
],
"width": 0.044186048209667206
},
"confidence": 0.7987252473831177,
"value": true
},
"mrzConformity": {
"confidence": 0.5,
"value": true
},
"mrzValidity": {
"confidence": 0.5,
"value": false
},
"photoIsPresent": {
"bbox": {
"height": 0.5394737124443054,
"topleft": [
0.01860465109348297,
0.18421050906181335
],
"width": 0.2906976640224457
},
"confidence": 0.9746031761169434,
"value": true
},
"rfSymbolIsPresent": {
"bbox": {},
"confidence": 0.8,
"value": false
},
"waveIsPresent": {
"bbox": {
"height": 0.20394736528396606,
"topleft": [
0.8069767393171787,
0.19736841320991516
],
"width": 0.0651162788271904
},
"confidence": 0.28632503747940063,
"value": true
}
},
"extractedInformation": {
"address": {
"confidence": null,
"value": ""
},
"birthCountry": {
"confidence": null,
"value": ""
},
"birthDate": {
"confidence": 0.7335174141228151,
"value": "06.12.1965"
},
"birthDateMRZ": {
"confidence": 0.5,
"value": "06.12.1965"
},
"birthDepartment": {
"confidence": 0.9,
"value": "99"
},
"birthPlace": {
"confidence": 0.7804153092105253,
"value": "PARIS 1ER ( 75 )"
},
"countryCode": {
"confidence": 0.9,
"value": "FR"
},
"deliveryDate": {
"confidence": null,
"value": ""
},
"expiryDate": {
"confidence": null,
"value": ""
},
"firstName": {
"confidence": 0.7593919999379608,
"value": "CORINNE"
},
"firstNameMRZ": {
"confidence": 0.5,
"value": "CORINNE"
},
"gender": {
"confidence": 0.8408435583114624,
"value": "F"
},
"idNumber": {
"confidence": 0.7615569009560375,
"value": "940992310285"
},
"idNumberMRZ": {
"confidence": 0.5,
"value": "940992310285"
},
"lastName": {
"confidence": 0.7986501646692794,
"value": "BERTHIER"
},
"lastNameMRZ": {
"confidence": 0.5,
"value": "BERTHIER"
},
"mrz": {
"confidence": 0.813361472313801,
"value": "IDFRABERTHIER<<<<<<<<<<<<<<<<<<<<<<<\n9409923102854CORINNE<<<<<<<6512068F4"
},
"nationality": {
"confidence": null,
"value": ""
},
"spouseName": {
"confidence": null,
"value": ""
}
},
"message": "",
"status": 200
}
Document type and side
For each ID card sent, the response will include information about the card type and side. The cardType of the card refers to the model used. The cardSide of the card changes whether the scan displays the front or back of the document.
cardType | ID card type |
---|---|
national_id_card_fr_2003 | French National ID card 2003 model |
national_id_card_fr_2021 | French National ID card 2021 model |
key | value |
---|---|
cardType | string |
cardSide | string |
"cardSide": "front",
"cardType": "national_id_card_fr_2003",
Extracted information format
For each field, the confidence value indicates the degree of certainty of the extraction with regard to the data on the card.
Name
The lastName (key) of the card holder is returned as a string (value).
lastName | Value |
---|---|
value | string |
confidence | number |
"lastName": {
"confidence": 0.7986501646692794,
"value": "BERTHIER"
}
Surnames
The firstName (key) of the card holder is returned as a string (value) separated by commas ",".
firstName | Value |
---|---|
value | string |
confidence | number |
"firstName": {
"confidence": 0.7986501646692794,
"value": "CORINNE"
}
Spouse name
The spouse (key) of the card holder is returned as a string (value).
spouse | Value |
---|---|
value | string |
confidence | number |
"spouse": {
"confidence": 0.7986501646692794,
"value": "CORINNE"
}
Date of birth
The birthDate (key) of the card holder is returned as a string (value).
birthDate | Value |
---|---|
value | string |
confidence | number |
"birthDate": {
"confidence": 0.7335174141228151,
"value": "06.12.1965"
}
Place of birth
The birthPlace (key) of the card holder is returned as a string (value).
birthPlace | Value |
---|---|
value | string |
confidence | number |
"birthPlace": {
"confidence": 0.7804153092105253,
"value": "PARIS 1ER ( 75 )"
}
State of birth
The birthDepartement (key) of the card holder is returned as a string (value).
birthDepartement | Value |
---|---|
value | string |
confidence | number |
"birthDepartment": {
"confidence": 0.9,
"value": "99"
},
Country of citizenship
The nationality (key) of the card holder is returned as a string (value).
nationality | Value |
---|---|
value | string |
confidence | number |
"nationality": {
"confidence": null,
"value": "FRA"
}
Gender
The gender or gender (key) of the card holder is returned as a string (value).
gender | Value |
---|---|
value | string |
confidence | number |
"gender": {
"confidence": 0.8408435583114624,
"value": "F"
}
Address
The address (key) of the card holder is returned as a string (value).
address | Value |
---|---|
value | string |
confidence | number |
"address": {
"confidence":0.823455583114624,
"value": "31 avenue de la république, Paris 13"
}
Delivery date
The deliveryDate (key) of the card holder is returned as a string (value).
deliveryDate | Value |
---|---|
value | string |
confidence | number |
"deliveryDate": {
"confidence": 0.8528435583114624,
"value": "10.05.2005"
}
Expiry date
The expiryDate (key) of the card holder is returned as a string (value).
expiryDate | Value |
---|---|
value | string |
confidence | number |
"expiryDate": {
"confidence": 0.8528435583114624,
"value": "10.05.2010"
}
Card number
The idNumber (key) of the card holder is returned as a string (value).
idNumber | Value |
---|---|
value | string |
confidence | number |
"idNumber": {
"confidence": 0.7615569009560375,
"value": "940992310285"
}
MRZ
The mrz (key) of the card holder is returned as a string (value).
value | |
---|---|
value |
Country code
The countryCode (key) of the card holder is returned as a string (value).
countryCode | Value |
---|---|
value | string |
confidence | number |
"countryCode": {
"confidence": 0.9,
"value": "FR"
}
Control results format
The controls applied to each document can be extracted in a boolean format. The confidence field indicated the degree of certainty of the control.
Global status
The globalStatus returns, as a boolean (value), whether the ID card is accepted or rejected with regard to our global minimum accepted rates.
globalStatus | Value |
---|---|
value | boolean |
confidence | number |
"globalStatus": {
"confidence": 1,
"score": 0.6,
"value": true
}
MRZ control
The mrzValidity controls the MRZ information with regard to the previously extracted fields. It is returned as a boolean (value).
mrzValidity | Value |
---|---|
value | boolean |
confidence | number |
"mrzValidity": {
"confidence": 0.5,
"value": false
}
MRZ conformity
The mrzConformity controls the conformity of the MRZ. It is returned as a boolean (value).
mrzConformity | Value |
---|---|
value | boolean |
confidence | number |
"mrzConformity": {
"confidence": 0.5,
"value": true
}
Date validity
The dateValidity controls the current validity of the document with regard to the expiry date. It is returned as a boolean (value).
dateValidity | Value |
---|---|
value | boolean |
confidence | number |
"dateValidity": {
"confidence": 0.5,
"value": True
}
Date validity delivery
The dateValidityDelivery controls the current validity of the document with regard to the delivery date. It is returned as a boolean (value).
dateValidityDelivery | Value |
---|---|
value | boolean |
confidence | number |
"dateValidity": {
"confidence": 0.5,
"value": True
},
Detection of photo
The photoIsPresent checks if the identity photo is detected on the document. It is returned as a boolean (value).
photoIsPresent | Value |
---|---|
value | boolean |
confidence | number |
"photoIsPresent": {
"confidence": 0.5,
"value": True
}
Detection of RF symbol
The rfSymbolIsPresent checks if the RF symbol is detected on the document. It is returned as a boolean (value).
rfSymbolIsPresent | Value |
---|---|
value | boolean |
confidence | number |
"rfSymbolIsPresent": {
"confidence": 0.5,
"value": True
}
Detection of stamp
The stampIsPresent checks if the stamp is detected on the document. It is returned as a boolean (value).
stampIsPresent | Value |
---|---|
value | boolean |
confidence | number |
"stampIsPresent": {
"confidence": 0.5,
"value": True
}
Detection of chip
The chipIsPresent checks if the chip is detected on the document. It is returned as a boolean (value).
chipIsPresent | Value |
---|---|
value | boolean |
confidence | number |
"chipIsPresent": {
"confidence": 0.5,
"value": True
}
Detection of hologram
The hologramIsPresent checks if the security hologram is detected on the document. It is returned as a boolean (value).
hologramIsPresent | Value |
---|---|
value | boolean |
confidence | number |
"hologramIsPresent": {
"confidence": 0.5,
"value": True
}
Detection of wave
The waveIsPresent checks if the security wave is detected on the document. It is returned as a boolean (value).
waveIsPresent | Value |
---|---|
value | boolean |
confidence | number |
"waveIsPresent": {
"confidence": 0.5,
"value": True
}
Detection of initials
The initialsIsPresent checks if the person's initials are detected on the document. It is returned as a boolean (value).
initialsIsPresent | Value |
---|---|
value | boolean |
confidence | number |
"initialsIsPresent": {
"confidence": 0.5,
"value": True
}
Field matching
You can provide, optionally, the declarative information from a user as an input to verify if it corresponds to the extracted information from the document. userInput supports the information as shown bellow in the example.
userInput | Value |
---|---|
firstName | string |
lastName | string |
birthDate | string |
gender | string |
photo | string (base64 encoded file) |
"userInput": {
"firstName": "",
"lastName": "",
"birthDate": "",
"gender": "",
"photo": ""
}
By providing a base64 string encoded photo of the person in userInput, we verify if is the same person present on the card.
Here is the as output example for field matching:
{
"matchFirstName" : {
"value": true,
"confidence": 0.8
},
"matchLastName" : {
"value": true,
"confidence": 0.8
},
"matchbirthDate" : {
"value": true,
"confidence": 0.8
},
"matchGender" : {
"value": true,
"confidence": 0.8
},
"matchPhoto" : {
"value": true,
"confidence": 0.8
}
}
Additional information
Loaded scans must pass prerequisites
To provide a qualitative service and a comprehensive data capture, every picture, scan, or document sent to our API must comply with determined prerequisites which can be found on this page
API limitations
- Maximum size : 5 MB
- Maximum number of calls per minute : 10 calls
Updated 11 months ago