Navbar
For Developers
HTTP Javascript PHP Python Ruby

Introduction

Shufti Pro’s Rest API (Representational State Transfer Application Programming Interface) uses Basic Auth & Access Token-based Authentication, HTTP Status Codes, JSON-Request & Response bodies and outlines all the parameters in detail that are being used. It also illustrates the supported countries, languages, browsers, devices, jurisdiction codes, and complete verification instructions of different services in case a custom UI/UX is to be built by the team at the web or mobile application level. Moreover, the provision of Shufti Pro TEST IDs aid in performing test verifications during the integration while making the complete process more seamless. Our API can help automate your business processes through by providing the following services:

  1. KYC Identity Verification
  2. Video KYC Identity Verification
  3. Biometric Verification
  4. Phone (2FA)
  5. AML Background Checks
  6. KYB (Know Your Business)
  7. OCR For Business

Shufti Pro’s API supports two verification types, i.e. on-site and off-site.

Getting Started

Before getting started, make sure you have the following:

  1. Shufti Pro Account. This is your individual user account to access the Shufti Pro’s REST API and back-office. To set up your Shufti Pro account, click here.

  2. API Keys. Shufti Pro API uses API keys to authenticate requests. You can view your API keys in the settings of your back-office. To get your API keys, click here.

Authorization

Shufti Pro API uses API keys to authenticate requests. You can view and manage your API keys in your Shufti Pro Backoffice. Authorization to API is performed via HTTP Basic Auth & Access Token. The verification request will fail without authorization.

BASIC AUTH

BASIC AUTH

//POST / HTTP/1.1 basic auth
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
{
    "reference"    : "1234567",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "verification_mode" : "any",
    "face" : {
        "proof"            : ""
    }
}
<?php
$url = 'https://api.shuftipro.com/';
$client_id  = 'YOUR-CLIENT-ID';
$secret_key = 'YOUR-SECRET-KEY';
$verification_request = [
    "reference"         => "ref-".rand(4,444).rand(4,444),
    "callback_url"      => "https://yourdomain.com/profile/notifyCallback",
    "email"             => "johndoe@example.com",
    "country"           => "GB",
    "language"          => "EN",
    "verification_mode" => "any",
];
$verification_request['face'] = [
    "proof" => ""
];
$auth = $client_id.":".$secret_key;
$headers = ['Content-Type: application/json'];
$post_data = json_encode($verification_request);
$response = send_curl($url, $post_data, $headers, $auth);
function send_curl($url, $post_data, $headers, $auth){
    $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_USERPWD, $auth);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $html_response = curl_exec($ch);
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $headers = substr($html_response, 0, $header_size);
        $body = substr($html_response, $header_size);
        curl_close($ch);
        return json_decode($body,true);
}
echo $response['verification_url'];
let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    email             : "johndoe@example.com",
    country           : "GB",
    language          : "EN",
    verification_mode : "any",
}
  payload['face'] = {
    proof : ""
  }
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY");
fetch('https://api.shuftipro.com/', {  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token
  },
  body: JSON.stringify(payload)}).then(function(response) {
     return response.json();
}).then(function(data) { return data; });

import requests, base64, json, hashlib 
from random import randint 
url = 'https://api.shuftipro.com/'
client_id  = 'YOUR-CLIENT-ID'
secret_key = 'YOUR-SECRET-KEY'
verification_request = {
    "reference"         :   "ref-{}{}".format(randint(1000, 9999), randint(1000, 9999)),
    "callback_url"      :   "https://yourdomain.com/profile/notifyCallback",
    "email"             :   "johndoe@example.com",
    "country"           :   "GB", 
    "language"          :   "EN",
    "verification_mode" :   "any"
}
verification_request['face'] = {
    "proof" : ""
}
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
response = requests.post(url, 
      headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
      data=json.dumps(verification_request))
json_response = json.loads(response.content)
print('Verification URL: {}'.format(json_response))
require 'uri'
require 'net/http'
require 'base64'
require 'json'
require 'open-uri'
url = URI("https://api.shuftipro.com/")
CLIENT_ID   = "YOUR-CLIENT-ID"
SECRET_KEY  = "YOUR-SECRET-KEY"
verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com",
    verification_mode:  "any"
}
verification_request["face"] = {
    proof: ""
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"
request.body = verification_request.to_json
response = http.request(request)
puts response.read_body

Shufti Pro provides Authorization to clients through the Basic Auth header. Your Client ID will serve as your Username while the Secret Key will serve as your Password. The API will require this header for every request.

Fields Required Description
username Yes Enter Client ID as username.
password Yes Enter your Secret Key as password.

ACCESS TOKEN

ACCESS TOKEN

//POST / HTTP/1.1 access token
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Bearer NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
{
    "reference"    : "1234567",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "verification_mode" : "any",
    "face" : {
        "proof"            : ""
    }
}
<?php
$url = 'https://api.shuftipro.com/';
$access_token = 'YOUR-ACCESS-TOKEN';
$verification_request = [
    "reference"         => "ref-".rand(4,444).rand(4,444),
    "callback_url"      => "https://yourdomain.com/profile/notifyCallback",
    "email"             => "johndoe@example.com",
    "country"           => "GB",
    "language"          => "EN",
    "verification_mode" => "any",
];
$verification_request['face'] = [
    "proof" => ""
];
$headers = ['Content-Type: application/json', 'Authorization: Bearer ' . $access_token];
$post_data = json_encode($verification_request);
$response = send_curl($url, $post_data, $headers);
function send_curl($url, $post_data, $headers){
    $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $html_response = curl_exec($ch);
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $body = substr($html_response, $header_size);
        curl_close($ch);
        return json_decode($body,true);
}
echo $response['verification_url'];
let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    email             : "johndoe@example.com",
    country           : "GB",
    language          : "EN",
    verification_mode : "any",
}
  payload['face'] = {
    proof : ""
  }
var token = "YOUR_ACCESS_TOKEN";
fetch('https://api.shuftipro.com/', {  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Bearer ' +token
  },
  body: JSON.stringify(payload)}).then(function(response) {
     return response.json();
}).then(function(data) { return data; });
import requests, base64, json, hashlib 
from random import randint
url = 'https://api.shuftipro.com/'
access_token = 'YOUR-ACCESS-TOKEN';
verification_request = {
    "reference"         :   "ref-{}{}".format(randint(1000, 9999), randint(1000, 9999)),
    "callback_url"      :   "https://yourdomain.com/profile/notifyCallback",
    "email"             :   "johndoe@example.com",
    "country"           :   "GB", 
    "language"          :   "EN",
    "verification_mode" :   "any"
}
verification_request['face'] = {
    "proof" : ""
}
response = requests.post(url, 
      headers={"Authorization": "Bearer %s" % access_token, "Content-Type": "application/json"},
      data=json.dumps(verification_request))
json_response = json.loads(response.content)
print('Verification URL: {}'.format(json_response))
require 'uri'
require 'net/http'
require 'base64'
require 'json'
require 'open-uri'
url = URI("https://api.shuftipro.com/")
ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"
verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com",
    verification_mode:  "any"
}
verification_request["face"] = {
    proof: ""
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"]  = "application/json"
request["Authorization"] = "Bearer #{ACCESS_TOKEN}"
request.body = verification_request.to_json
response = http.request(request)
puts response.read_body

Shufti Pro provides Bearer Access Token Authorization method. Client can generate temporary access token using new access token endpoint. The shared token will be used to authorize API requests.

Field Required Description
Authorization Yes Enter your authorization token.

Verification Services

The identity verification services suite of Shufti Pro consists of KYC and KYB screening, AML screening (of individuals and businesses), biometric verification, address verification, consent verification, and 2-factor authentication. All these verifications are performed using Artificial Intelligence to fetch and analyze the data from valid identity documents and by utilizing the information provided by our customers. This document will help our valuable customers gain useful insights about how our service works, the role of our customers and end-users in the verification process and technical aspects of this integration.

Know Your Customer (KYC)

KYC service of Shufti Pro screens the identities of end-users using identity documents such as ID card, passport, and driving license. KYC service includes face verification, address verification, document verification, 2-factor authentication, and consent verification services. A combination of these services with background checks enables you to perform thorough KYC and AML procedures and take proactive risk-prevention measures.

Common Parameters

The parameters mentioned below are applicable for both onsite and offsite verifications in KYC service.

Parameters Description
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
Each request is issued a unique reference ID which is sent back to Shufti Pro’s client with each response. This reference ID helps to verify the request. The client can use this ID to check the status of already performed verifications.
country Required: No
Type: string
Length: 2 characters
You may omit this parameter if you don't want to enforce country verification. If a valid country code is provided, then the proofs (images/videos) for document verification or address verification must be from the same country. Country code must be a valid ISO 3166-1 alpha-2 country code. Please consult Supported Countries for country codes.
language Required: No
Type: string
Length: 2 characters
If the Shufti Pro client wants their preferred language to appear on the verification screens they may provide the 2-character long language code of their preferred language. The list of Supported Languages can be consulted for the language codes. If this key is missing in the request the system will select the default language as English.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents email of the end-user.
callback_url Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
A number of server-to-server calls are made to Shufti Pro’s client to keep them updated about the verification status. This allows the clients to keep the request updated on their end, even if the end-user is lost midway through the process.
redirect_url Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
Once an on-site verification is complete, User is redirected to this link after showing the results.
verification_mode Required: No
Type: string
Accepted Values: any, image_only, video_only
This key specifies the types of proof that can be used for verification. In a “video_only” mode, Shufti Pro’s client can only send “Base64” of videos wherein formats of proofs should be MP4 or MOV. “any” mode can be used to send a combination of images and videos as proofs for verification.
allow_offline Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter allows users to upload images or videos in case of non-availability of a functional webcam.If value: 0, users can capture photos/videos with the camera only.
allow_online Required: No
Type: string
Accepted Values: 0, 1
Default-Value: 1
This parameter allows users to capture image or videos in real-time when internet is available. If value: 0 users can upload already captured images or videos.
Note: if allow_offline: 0 priority will be given to allow_offline
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
If enabled, it shows the Shufti Pro terms and conditions to the user at the start of the verification.
allow_na_ocr_inputs Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
In onsite with ocr verification request, it allows the end-user to select N/A on the OCR form and the verification step will be accepted.
decline_on_single_step Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
If enabled, the verification request will be declined when one of the verification steps is not verified.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve another alternative mechanism in place.
show_results Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
If Value for this parameter is 1, verification result will be displayed to the end-user, showing them whether their verification is accepted or declined. If the value of this parameter is set 0, verification results will not be shown to end-user.
show_feedback_form Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter will work only for onsite verification. If its value is 1 at the end of verification, a feedback form is displayed to the end-user to collect his/her feedback. If it is 0 then it will not display the feedback page to the end-user.
allow_retry Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
In onsite verification request, If the document is declined by AI, the end-user can re-upload the document up to 3 times.
manual_review Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
This key can be used if the client wants to review verifications after processing from Shufti Pro has completed. Once the user submits any/all required documents, Shufti Pro returns a status of review.pending. The client can then review the verification details and Accept OR Decline the verifications from the back-office.
ttl Required: No
Type: int
Minimum: 60
Give a numeric value for minutes that you want the verification url to remain active.
Onsite Verification

On-site verification means that Shufti Pro will be interacting directly with end-user and will be responsible for data collection in order to perform Identity verification. Shufti Pro customer will only be notified about the verification status via Shufti Pro Back Office.

Shufti Pro offers following services in On-site verification: (Face, Document, Address, Consent, Phone and Background Checks)

With OCR

On-site with OCR Verification Request

//POST / HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"
{
    "reference"    : "1234567",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "redirect_url" : "http://www.example.com",
    "ttl"          : 60,
    "verification_mode" : "any",
    "document"         : {
        "proof"           : "",
        "additional_proof" : "",
        "supported_types" : ["id_card","driving_license","passport"],
        "name"            : "",
        "dob"             : "",
        "age"             : "",
        "issue_date"      : "", 
        "expiry_date"     : "",
        "document_number" : "",
        "allow_offline"   : "1",
        "allow_online"    : "1",
        "gender"          : ""
    },

    "address"         : {
        "proof"            : "",
        "supported_types"  : ["id_card","bank_statement"],
        "name"             : "",
        "issue_date"       : "",
        "full_address"     : "",
        "address_fuzzy_match":"1",
        "document_number" : ""
    }
}
<?php
$url = 'https://api.shuftipro.com/';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
    'verification_mode' => 'any',
    'ttl'         => 60,
];

//Use this key if you want to perform document verification with OCR
$verification_request['document'] =[
    'proof' => '', 
    'additional_proof' => '',
    'name' => '',
    'dob'             => '',
    'age'             => '',
    'document_number' => '',
    'expiry_date'     => '',
    'issue_date'      => '',
    'allow_offline'      => '1', 
    'allow_online'     => '1',
    'supported_types' => ['id_card','passport'],
    "gender"          =>  ""
];

//Use this key if you want to perform address verification with OCR
$verification_request['address'] = [
    'proof' => '', 
    'name' => '',
    'full_address'    => '',
    'address_fuzzy_match' => '1',
    'issue_date' => '',
    'supported_types' => ['utility_bill','passport','bank_statement']
];

$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization: Bearer ' . $access_token); 
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);

// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];

if($event_name == 'request.pending'){
    if($sp_signature == $calculate_signature){
        $verification_url = $decoded_response['verification_url'];  
        echo "Verification url :" . $verification_url;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>
import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   'https://yourdomain.com/profile/notifyCallback',
    'verification_mode' :   'any',
    'ttl'               : 60,
}
# Use this key if you want to perform document verification with OCR
verification_request['document'] = {
    'proof'             :   '',
    'additional_proof'  :   '',
    'name'              :   '',
    'dob'               :   '',
    'age'               :   '',
    'document_number'   :   '',
    'expiry_date'       :   '',
    'issue_date'        :   '',
    'allow_offline'     :   '1',
    'allow_online'      :   '1',
    'supported_types'   :   ['id_card','passport'],
        'gender'        :  ''
}
# Use this key want to perform address verification with OCR
verification_request['address'] = {
    'proof'             :   '',
    'name'              :   '',
    'full_address'      :   '',
    'address_fuzzy_match' : '1',
    'issue_date'        :   '',
    'supported_types'   :   ['utility_bill','passport','bank_statement']
}

# Calling Shufti Pro request API using python  requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')
# Convert json string to json object
json_response = json.loads(response.content)
# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'request.pending':
    if sp_signature == calculated_signature:
        verification_url = json_response['verification_url']
        print ('Verification URL: {}'.format(verification_url))
    else:
        print ('Invalid signature: {}'.format(response.content))
let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    redirect_url      : "https://yourdomain.com/site/sp-redirect",
    country           : "GB",
    language          : "EN",
    verification_mode : "any",
    ttl               : 60,
}
//Use this key if you want to perform document verification with OCR
payload['document'] = {
  proof           : '',
  additional_proof : '',
  name            : '',
  dob             : '',
  age             : '',
  document_number : '',
  expiry_date     : '',
  issue_date      : '',
  allow_offline   : '1',
  allow_online    : '1',
  supported_types : ['id_card','passport'],
  gender        :  ''
}
//Use this key if you want to perform address verification with OCR
payload['address'] = {
  name               : '',
  full_address       : '',
  address_fuzzy_match : '1',
  issue_date         : '',
  supported_types    : ['utility_bill','passport','bank_statement']
}
//BASIC AUTH TOKEN
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
    if (data.event && data.event === 'request.pending') {
          createIframe(data.verification_url)
    }
});

//Method used to create an Iframe
function createIframe(src) {

    let iframe = document.createElement('iframe');
    iframe.style.position = 'fixed';
    iframe.id = 'shuftipro-iframe';
    iframe.name = 'shuftipro-iframe';
    iframe.allow = "camera";
    iframe.src = src;
    iframe.style.top = 0;
    iframe.style.left = 0;
    iframe.style.bottom = 0;
    iframe.style.right = 0;
    iframe.style.margin = 0;
    iframe.style.padding = 0;
    iframe.style.overflow = 'hidden';
    iframe.style.border = "none";
    iframe.style.zIndex = "2147483647";
    iframe.width = "100%";
    iframe.height = "100%";
    iframe.dataset.removable = true;

    document.body.appendChild(iframe);
}
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com",
    verification_mode:  "any",
    ttl:                 60,
}
# Use this key if you want to perform document verification with OCR
verification_request["document"] = {
    supported_types: ["id_card","driving_license","passport"],
    proof:            "",
    additional_proof: "",
    name:             "",
    dob:              "",
    age:              "",
    issue_date:       "", 
    expiry_date:      "",
    document_number:  "",
    allow_offline:    "1",
    allow_online:     "1",
    gender:           ""
}
# Use this key if you want to perform address verification with OCR
verification_request["address"] = {
    supported_types:     ["id_card","bank_statement"],
    name:                "",
    issue_date:          "",
    full_address:        "",
    address_fuzzy_match: "1"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json
response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY
if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

To read full API Documentation about Onsite Verification With OCR feature, click
here

Shufti Pro collects the image or video proofs from end-users. In the verification request, Shufti Pro customer specifies the keys for the parameters to be verified. Shufti Pro extracts the required information from the provided document and then the verification form is automatically filled with the extracted information. This reduces the manual work for the end-user. Next, Shufti Pro’s intelligently driven system verifies the provided documents for authenticity. Please consult This Document for Onsite with OCR verifications.

OCR is offered on the following services: (Document and Address) but Shufti Pro customers can also avail other non-OCR services such as Face & Phone Verification along with these OCR services.

<iframe src="" id="shuftipro-iframe" allow="camera" frameborder="0"></iframe>

Run in Postman

Without OCR

On-site without OCR Verification Request

//POST / HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"

{
    "reference"    : "5667456341",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "verification_mode" : "any",
    "ttl"           : 60,
    "face": {
        "proof": ""
    },

    "document"         : {
        "proof"           : "",
        "additional_proof" : "",
        "supported_types" : ["id_card","driving_license","passport"],
        "name"             : {
             "first_name"   : "John",
             "middle_name"  : "Middleman",
             "last_name"    : "Doe"
        },
        "dob"             : "1980-11-12",
        "age"             :  18,
        "issue_date"      : "1990-09-07", 
        "expiry_date"     : "2050-10-10",
        "gender"        :  "M",
        "document_number" : "0989-7752-6291-2387",
        "allow_offline"   : "1",
        "allow_online"    : "1"
    },

    "address"         : {
        "proof"            : "",
        "supported_types"  : ["id_card","bank_statement"],
        "name"             : {
             "first_name"   : "John",
             "middle_name"  : "Middleman",
             "last_name"    : "Doe"
        },
        "full_address"      : "3339 Maryland Avenue, Largo, Florida",
        "address_fuzzy_match":"1",
        "issue_date"        : "1990-09-07"
    },

    "consent":{
        "proof"  : "",
        "supported_types" : ["handwritten","printed"],
        "text"   : "My name is John Doe and I authorise this transaction of $100/- Date: July 15, 2020",
        "allow_offline"     : "1",
        "allow_online"      : "1"
    },

    "phone": {
        "phone_number" : "+4400000000",
        "random_code"  : "23234",
        "text"         : "Your verification code is 23234"
    },

    "background_checks": {
        "name"             : {
             "first_name"   : "John",
             "middle_name"  : "Middleman",
             "last_name"    : "Doe"
        },
        "dob"             : "1980-11-12"
    }
}
<?php
$url = 'https://api.shuftipro.com/';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';
$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
    'verification_mode' => 'any',
    'ttl'          => 60,
];
//Use this key if you want to perform face verification
$verification_request['face'] = [
       'proof' => '', 
       'allow_offline'   => '1',
       'allow_online'    => '1',
];
//Use this key if you want to perform document verification
$verification_request['document'] =[
    'name' => [
        'first_name' => 'Your first name',
        'middle_name' => 'Your middle name',
        'last_name'  => 'You last name',
        'fuzzy_match' => '1'
    ],
    'proof' => '', 
    'additional_proof' => '',
    'dob'             => '1992-10-10',
    'age'             =>  18,
    'document_number' => '2323-5629-5465-9990',
    'expiry_date'     => '2025-10-10',
    'issue_date'      => '2015-10-10',
    'allow_offline'   => '1',
    'allow_online'    => '1',
    'supported_types' => ['id_card','passport'],
    'gender'        =>  ''
];
//Use this key if you want to perform address verification
$verification_request['address'] = [
    'name' => [
        'first_name' => 'Your first name',
        'middle_name' => 'Your middle name',
        'last_name'  => 'You last name',
        'fuzzy_match' => '1'
    ],
    'proof' => '', 
    'full_address'    => 'your address',
    'address_fuzzy_match' => '1',
    'issue_date' => '2015-10-10',
    'supported_types' => ['utility_bill','passport','bank_statement']
];

//Use this key if you want to perform consent verification
$verification_request['consent'] =[
    'proof' =>           '', 
    'text'            => 'some text for consent verification',
    'supported_types' => ['handwritten'],
    'allow_offline'      => '1',
    'allow_online'       => '1',
];

//Use this key if you want to perform phone verification
$verification_request['phone'] =[
    'phone_number'    => '+1378746734',
    'random_code'     => '9977',
    'text'            => 'Your verification code is 9977'
];
//Use this key if you want to perform aml/background checks verification
$verification_request['background_checks'] = [
    'name' => [
        'first_name' => 'Your first name',
        'middle_name' => 'Your middle name',
        'last_name'  => 'You last name'
    ],
    'dob'             => '1992-10-10',
];
$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization : Bearer ' . $access_token);
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];
if($event_name == 'request.pending'){
    if($sp_signature == $calculate_signature){
        $verification_url = $decoded_response['verification_url'];
        echo "Verification url :" . $verification_url;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>
import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/'
callback_url = 'https://yourdomain.com/profile/notifyCallback'

# Your Shufti Pro account Client ID
client_id = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   callback_url,
    'verification_mode' :   'any',
    'ttl'               :   60,
}
# Use this key if want to perform face verification
verification_request['face'] = {}
# Use this key if want to perform document verification
verification_request['document'] = {
    'name'      :   {
        'first_name'    :   'Your first name', 
        'middle_name'   :   'Your middle name', 
        'last_name'     :   'Your last name',
        'fuzzy_match'   :   '1'
    },
    'proof'             :   '',
    'additional_proof'  :   '',
    'dob'             : '1992-10-10',
    'age'             :  18,
    'document_number' : '2323-5629-5465-9990',
    'expiry_date'     : '2025-10-10',
    'issue_date'      : '2015-10-10',
    'allow_offline'   :   '1',
    'allow_online'    :   '1',
    'supported_types' : ['id_card','passport'],
    'gender'        :  ''
}
# Use this key if want to perform address verification
verification_request['address'] =  {
    'name'      :   {
        'first_name'    :   'Your first name', 
        'middle_name'   :   'Your middle name', 
        'last_name'     :   'Your last name',
        'fuzzy_match'   :   '1'
    },
    'proof'             :   '',
    'full_address'    : 'your address',
    'address_fuzzy_match' : '1',
    'issue_date'        :   '2015-10-10',
    'supported_types' : ['utility_bill','passport','bank_statement']
}
# Use this key if want to perform consent verification
verification_request['consent'] =  {
    'proof'             :   '',
    'text'          :   'some text for consent verification',
    'supported_type':   ['handwritten'],
    'allow_offline' :   '1',
    'allow_online'  :   '1',
}
# Use this key if want to perform phone verification
verification_request['phone'] =    {
    'phone_number'    : '+1378746734',
    'random_code'     : '9977',
    'text'            : 'Your verification code is 9977'
}
# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')
# Convert json string to json object
json_response = json.loads(response.content)
# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'request.pending':
    if sp_signature == calculated_signature:
        verification_url = json_response['verification_url']
        print ('Verification URL: {}'.format(verification_url))
    else:
        print ('Invalid signature: {}'.format(response.content))
let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    redirect_url      : "https://yourdomain.com/site/sp-redirect",
    country           : "GB",
    language          : "EN",
    verification_mode : "any",
    ttl               : 60,
}
//Use this key if you want to perform face verification
payload['face'] = {
    proof          : "",
    allow_offline  : "1",
};
//Use this key if you want to perform document verification
payload['document'] = {
  name : {
        first_name  : 'Your first name',
        middle_name : 'Your middle name',
        last_name   : 'You last name',
        fuzzy_match : '1'
    },
    proof           : '',
    additional_proof : '',
    dob             : '1992-10-10',
    age             :  18,
    document_number : '2323-5629-5465-9990',
    expiry_date     : '2025-10-10',
    issue_date      : '2015-10-10',
    allow_offline   : '1',
    allow_online    : '1',
    supported_types : ['id_card','passport'],
    gender          :  ''
}
//Use this key if you want to perform address verification
payload['address'] = {
  name : {
        first_name  : 'Your first name',
        middle_name : 'Your middle name',
        last_name   : 'You last name',
        fuzzy_match : '1'
    },  
    proof           : '',
    full_address    : 'your address',
    address_fuzzy_match : '1',
    issue_date : '2015-10-10',
    supported_types : ['utility_bill','passport','bank_statement']
}

//Use this key if you want to perform background checks verification
payload['background_checks'] = {
  name : {
        first_name  : 'Your first name',
        middle_name : 'Your middle name',
        last_name   : 'You last name',
    },
    dob    : '1994-01-01',
}
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
    if (data.event && data.event === 'request.pending') {
          createIframe(data.verification_url)
    }
});

//Method used to create an Iframe
function createIframe(src) {

    let iframe = document.createElement('iframe');
    iframe.style.position = 'fixed';
    iframe.id = 'shuftipro-iframe';
    iframe.name = 'shuftipro-iframe';
    iframe.allow = "camera";
    iframe.src = src;
    iframe.style.top = 0;
    iframe.style.left = 0;
    iframe.style.bottom = 0;
    iframe.style.right = 0;
    iframe.style.margin = 0;
    iframe.style.padding = 0;
    iframe.style.overflow = 'hidden';
    iframe.style.border = "none";
    iframe.style.zIndex = "2147483647";
    iframe.width = "100%";
    iframe.height = "100%";
    iframe.dataset.removable = true;

    document.body.appendChild(iframe);
}
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:             "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com",
    verification_mode:  "any",
    ttl:                60,
}
# Use this key if you want to perform document verification with OCR
verification_request["document"] = {
    supported_types: ["id_card","driving_license","passport"],
    name:            {
      first_name: "Johon",
      last_name:  "Livone"
    },
    proof:            "",
    additional_proof: "",
    dob:             "1990-10-10",
    age:              18,
    issue_date:      "2015-10-10", 
    expiry_date:     "2025-10-10",
    document_number: "1234-1234-ABC",
    allow_offline:    "1",
    allow_online:     "1",
    gender:           ''
}
# Use this key if you want to perform address verification with OCR
verification_request["address"] = {
    supported_types:     ["id_card","bank_statement"],
    name:                {
      first_name: "Johon",
      last_name:  "Livone"
    },
    issue_date:          "2015-10-10",
    full_address:        "Candyland Avenue",
    address_fuzzy_match: "1"
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY
if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

To read full API Documentation about Onsite Verification Without OCR feature, click
here
.

Shufti Pro collects the image or video proofs from end-users. In the verification request, Shufti Pro customer specifies the keys for the parameters to be verified. Shufti Pro uses a unique template matching technique to match these values to the data on identity documents. Next, Shufti Pro’s intelligently driven system verifies the provided documents for authenticity. Please consult This Document for Onsite without OCR verifications.

These are the services offered in Onsite Verification without OCR: (Face, Document, Address, Consent, Phone and Background Checks)

<iframe src="" id="shuftipro-iframe" allow="camera" frameborder="0"></iframe>

Run in Postman

Offsite Verification

Offsite Verification means that Shufti Pro will not be interacting with end-user and Shufti Pro customer will be responsible to collect and provide verification data. Shufti Pro Customer will provide us with the proofs (images/videos) to complete user verification.

Shufti Pro offers following services in Off-site verification: (Face, Document, Address, Consent and Background Checks)

With OCR

Off-site with OCR Verification Request

//POST / HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"

{
    "reference"    : "567456314",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "verification_mode" : "any",
    "document"         : {
        "proof"           : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII=",
        "additional_proof": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII=",
        "supported_types" : ["id_card","driving_license","passport"],
        "name"            : "",
        "dob"             : "",
        "age"             : "",
        "issue_date"      : "", 
        "expiry_date"     : "",
        "document_number" : "",
        "gender"          : ""
    },
    "address"         : {
        "proof"            : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII=",
        "supported_types"  : ["id_card","bank_statement"],
        "name"             : "",
        "full_address"     : "",
        "address_fuzzy_match":"1",
        "issue_date":""
    }
}
<?php
$url = 'https://api.shuftipro.com/';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
    'verification_mode' => 'any',
];
//Use this key if you want to perform document verification
$verification_request['document'] =[
    'proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg')),
    'additional_proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg')),
    'name' => '',
    'dob'             => '',
    'age'             => '',
    'document_number' => '',
    'expiry_date'     => '',
    'issue_date'      => '',
    'supported_types' => ['id_card','passport'],
    'gender'          => '',
];
//Use this key if you want to perform address verification
$verification_request['address'] = [
    'proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg')),
    'name' => '',
    'full_address'    => '',
    'address_fuzzy_match' => '1',
    'issue_date' => '',
    'supported_types' => ['utility_bill','passport','bank_statement']
];
$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization : Bearer ' . $access_token);
$post_data = json_encode($verification_request);

//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];

if(in_array($event_name, ['verification.accepted', 'verification.declined', 'request.received']) ){
    if($sp_signature == $calculate_signature){
        echo $event_name." :" . $response_data;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $curl_info = curl_getinfo($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>

import base64, requests, json, hashlib, urllib2
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   'https://yourdomain.com/profile/notifyCallback',
    'verification_mode' :   'any',
}
# Use this key if you want to perform document verification
verification_request['document'] = {
    'proof'             :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').read()).decode(),
    'additional_proof'  :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').read()).decode(),
    'name'              :   '',
    'dob'               :   '',
    'age'               :   '',
    'document_number'   :   '',
    'expiry_date'       :   '',
    'issue_date'        :   '',
    'supported_types'   :   ['id_card','passport'],
    'gender'            :  ''
}
# Use this key if you want to perform address verification
verification_request['address'] = {
    'proof'             :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').read()).decode(),
    'name'              :   '',
    'full_address'      :   '',
    'address_fuzzy_match' : '1',
    'issue_date'        :   '',
    'supported_types'   :   ['utility_bill','passport','bank_statement']
}
# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()

# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')

# Convert json string to json object
json_response = json.loads(response.content)

# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'verification.accepted':
    if sp_signature == calculated_signature:
        print ('Verification accepted: {}'.format(response.content))
    else:
        print ('Invalid signature: {}'.format(response.content))
else:
    print ('Error: {}'.format(response.content))

var payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    redirect_url      : "https://yourdomain.com/site/sp-redirect",
    country           : "GB",
    language          : "EN",
    verification_mode : "any",
}
//get document sample proof base64
convertImgToBase64URL('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').then(response=>{

//Use this key if you want to perform document verification
payload['document'] = {
  proof : response,
  additional_proof : response,
  name : "",
    dob             : "",
    age             : "",
    document_number : "",
    expiry_date     : "",
    issue_date      : "",
    supported_types : ['id_card','passport'],
    gender        :  ''
}
//Use this key if you want to perform address verification
payload['address'] = {
  proof : response,
  name : "",
  full_address    : "",
  address_fuzzy_match : '1',
  issue_date : '',
  supported_types : ['utility_bill','passport','bank_statement']
}
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token           // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     console.log(data)
     return data;
});
})

/*METHOD USED TO Get image BASE 64 string*/
function convertImgToBase64URL(url){
  return new Promise(function(resolve, reject) {
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        var canvas    = document.createElement('CANVAS'),
        ctx           = canvas.getContext('2d'), dataURL;
        canvas.height = img.height;
        canvas.width  = img.width;
        ctx.drawImage(img, 0, 0);
        dataURL = canvas.toDataURL('image/jpeg');
        resolve(dataURL);
        canvas = null; 
    };
    img.src = url;
  })
}
require 'uri'
require 'net/http'
require 'base64'
require 'json'
require 'open-uri'

url = URI("https://api.shuftipro.com/")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

# Sample image
SAMPLE_DOCUMENT_IMAGE =  "https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com",
    verification_mode:  "any",
    show_results:       "0"
}
# Use this key if you want to perform document verification with OCR
verification_request["document"] = {
    proof:           Base64.encode64(URI.open(SAMPLE_DOCUMENT_IMAGE).read),
    supported_types: ["id_card","driving_license","passport"],
    name:            "",
    dob:             "",
    age:             "",
    issue_date:      "", 
    expiry_date:     "",
    document_number: "",
    gender:          ""
}
# Use this key if you want to perform address verification with OCR
verification_request["address"] = {
    proof:               Base64.encode64(URI.open(SAMPLE_DOCUMENT_IMAGE).read),
    supported_types:     ["id_card","bank_statement"],
    name:                "",
    issue_date:          "",
    full_address:        "",
    address_fuzzy_match: "1"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body
sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY

if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

To read full API Documentation about Offsite Verification With OCR feature, click
here

In offsite Verification with OCR, the verification data is extracted directly from the proofs (image/video) provided by the Shufti Pro customer. In the verification request, Shufti Pro customer specifies the keys for the parameters to be verified. Shufti Pro extracts the required information from the provided document and then the verification form is automatically filled with the extracted information. Please consult This Document for Offsite with OCR verifications.

OCR is offered on the following services: (Document and Address) but Shufti Pro customers can also avail other non-OCR services such as Face & Phone Verification along with these OCR services.

Run in Postman

Without OCR

Off-site without OCR Verification Request

//POST / HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"

{
    "reference"    : "56745631",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "verification_mode" : "any",
    "face": {
        "proof": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII="
    },
    "document"         : {
        "proof"           : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII=",
        "additional_proof": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII=",
        "supported_types" : ["id_card","driving_license","passport"],
        "name"             : {
             "first_name"   : "Johon",
             "last_name"    : "Livone"
        },
        "dob"             : "1990-10-10",
        "age"             :  18,
        "issue_date"      : "2015-10-10", 
        "expiry_date"     : "2025-10-10",
        "document_number" : "1234-1234-ABC",
        "gender"          :  "M"
    },

    "address"         : {
        "proof"            : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII=",
        "supported_types"  : ["id_card","bank_statement"],
        "name"             : {
             "first_name"   : "Johon",
             "last_name"    : "Livone"
        },
        "issue_date"       : "2015-10-10",
        "full_address"     : "Candyland Avenue",
        "address_fuzzy_match":"1"
    },

    "consent":{
        "proof"  : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII=",
        "supported_types" : ["printed"],
        "text"   : "My name is John Doe and I authorise this transaction of $100/- Date: July 15, 2020"
    },

    "background_checks": {
        "name"             : {
             "first_name"   : "John",
             "middle_name"  : "Middleman",
             "last_name"    : "Doe"
        },
        "dob": "1980-11-12"
    }
}
<?php
$url = 'https://api.shuftipro.com/';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
// $access_token = 'YOUR-ACCESS-TOKEN';

$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
    'verification_mode' => 'any',
];
//Use this key if you want to perform face verification
$verification_request['face'] = [
    'proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-face.jpg'))
];
//Use this key if want to perform document verification
$verification_request['document'] =[
    'proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg')),
    'additional_proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg')),
    'name' => [
        'first_name' => 'Your first name',
        'last_name'  => 'You last name',
        'fuzzy_match' => '1'
    ],
    'dob'             => '1992-10-10',
    'age'             =>  18,
    'document_number' => '2323-5629-5465-9990',
    'expiry_date'     => '2025-10-10',
    'issue_date'      => '2015-10-10',
    'supported_types' => ['id_card','passport'],
    'gender'          =>  "M"
];
//Use this key if you want to perform address verification
$verification_request['address'] = [
    'proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg')),
    'name' => [
        'first_name' => 'Your first name',
        'last_name'  => 'You last name',
        'fuzzy_match' => '1'
    ],
    'full_address'    => 'your address',
    'address_fuzzy_match' => '1',
    'issue_date' => '2015-10-10',
    'supported_types' => ['utility_bill','passport','bank_statement']
];
//Use this key if you want to perform consent verification
$verification_request['consent'] =[
    'proof' => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-consent-document.jpg')),
    'text'            => 'some text for consent verification',
    'supported_types' => ['handwritten'],
];
//Use this key if you want to perform aml/background checks verification
$verification_request['background_checks'] = [
    'name' => [
        'first_name' => 'Your first name',
        'last_name'  => 'You last name'
    ],
    'dob'             => '1992-10-10',
];

$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization : Bearer ' . $access_token);
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove this in case of Access Token

//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];

if(in_array($event_name, ['verification.accepted', 'verification.declined', 'request.received']) ){

    if($sp_signature == $calculate_signature){

        echo $event_name." :". $response_data;
    }else{
        echo "Invalid signature :".  $response_data;
    }

}else{

    echo "Error : $response_data";
}

function send_curl($url, $post_data, $headers, $auth){ // remove this in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $curl_info = curl_getinfo($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>
import base64, requests, json, hashlib, urllib2
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/'

# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   'https://yourdomain.com/profile/notifyCallback',
    'verification_mode' :   'any'
}
# Use this key if want to perform face verification
verification_request['face'] = {
    'proof'             :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-face.jpg').read()).decode()
}
# Use this key if you want to perform document verification
verification_request['document'] = {
    'proof'             :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').read()).decode(),
    'additional_proof'  :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').read()).decode(),
    'name'              :   {
        'first_name'    :   'Your first name',
        'last_name'     :   'Your last name',
        'fuzzy_match'   :   '1'
    },
    'dob'               :   '1992-10-10',
    'age'               :    18,
    'document_number'   :   '2323-5629-5465-9990',
    'expiry_date'       :   '2025-10-10',
    'issue_date'        :   '2015-10-10',
    'supported_types'   :   ['id_card','passport'],
    'gender'            :   'M'
}
# Use this key if want to perform address verification
verification_request['address'] = {
    'proof'             :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').read()).decode(),
    'name'              :   {
        'first_name'    :   'Your first name',
        'last_name'     :   'Your last name',
        'fuzzy_match'   :   '1'
    },
    'full_address'      :   'your address',
    'address_fuzzy_match' : '1',
    'issue_date'        :   '2015-10-10',
    'supported_types'   :   ['utility_bill','passport','bank_statement']
}
# Use this key if you want to perform consent verification
verification_request['consent'] = {
    'proof'             :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-consent-document.jpg').read()).decode(),
    'text'              :   'some text for consent verification',
    'supported_types'   :   ['handwritten']
}
# Use this key if you want to perform AML/Background Checks verification
verification_request['background_checks'] = {
    'name'  :   {
        'first_name'    :   'Your first name',
        'last_name'     :   'You last name'
    },
    'dob'   :   '1992-10-10'
}

# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()

# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')

# Convert json string to json object
json_response = json.loads(response.content)

# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'verification.accepted':
    if sp_signature == calculated_signature:
        print ('Verification accepted: {}'.format(response.content))
    else:
        print ('Invalid signature: {}'.format(response.content))
else:
    print ("Error: {}".format(response.content))

var payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    redirect_url      : "https://yourdomain.com/site/sp-redirect",
    country           : "GB",
    language          : "EN",
    verification_mode : "any",
    ttl               : 60,
    document          : {},
    address           : {},
}

/*Get face sample proof Base64*/
convertImgToBase64URL('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-face.jpg').then(response=>{
  payload['face'] = {
    proof : response
  }
})

//get Document proof base64
convertImgToBase64URL('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').then(response=>{

//Use this key if you want to perform document verification with OCR
payload['document'] = {
  proof : response,
  additional_proof : response,
  name : {
        first_name  : 'Your first name',
        last_name   : 'You last name',
        fuzzy_match : '1'
    },
    dob             : '1992-10-10',
    age             :  18,
    document_number : '2323-5629-5465-9990',
    expiry_date     : '2025-10-10',
    issue_date      : '2015-10-10',
    supported_types : ['id_card','passport'],
    gender        :  'M'
}



//Use this key if you want to perform address verification with OCR
payload['address'] = {
  proof : response,
  name : {
        first_name  : 'Your first name',
        last_name   : 'You last name',
        fuzzy_match : '1'
    },
    full_address    : 'your address',
    address_fuzzy_match : '1',
    issue_date : '2015-10-10',
    supported_types : ['utility_bill','passport','bank_statement']
}

//Use this key if you want to perform background checks verification
payload['background_checks'] = {
  name : {
    first_name  : 'Your first name',
    middle_name : 'Your middle name',
    last_name   : 'Your last name'
  },
  dob : '1994-10-03'
}


//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     console.log(data)
     return data;
});

})

/*METHOD USED TO Get image BASE 64 string*/
function convertImgToBase64URL(url){
  return new Promise(function(resolve, reject) {
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        var canvas = document.createElement('CANVAS'),
        ctx = canvas.getContext('2d'), dataURL;
        canvas.height = img.height;
        canvas.width = img.width;
        ctx.drawImage(img, 0, 0);
        dataURL = canvas.toDataURL('image/jpeg');
        resolve(dataURL);
        canvas = null; 
    };
    img.src = url;
  })
}
require 'uri'
require 'net/http'
require 'base64'
require 'json'
require 'open-uri'

url = URI("https://api.shuftipro.com/")

# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

# Sample image
SAMPLE_DOCUMENT_IMAGE =  "https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com",
    verification_mode:  "any",
    show_results:       "0"
}

# Use this key if you want to perform document verification with OCR
verification_request["document"] = {
    proof:           Base64.encode64(URI.open(SAMPLE_DOCUMENT_IMAGE).read),
    supported_types: ["id_card","driving_license","passport"],
    name:            {
        first_name: "Johon",
        last_name:  "Livone" 
    },
    dob:             "1990-10-10",
    age:              18,
    issue_date:      "2015-10-10", 
    expiry_date:     "2025-10-10",
    document_number: "1234-1234-ABC",
    gender:          "M"
}

# Use this key if you want to perform address verification with OCR
verification_request["address"] = {
    proof:               Base64.encode64(URI.open(SAMPLE_DOCUMENT_IMAGE).read),
    supported_types:     ["id_card","bank_statement"],
    name:                {
        first_name: "Johon",
        last_name:  "Livone" 
    },
    issue_date:          "2015-10-10",
    full_address:        "Candyland Avenue",
    address_fuzzy_match: "1"
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY

if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

To read full API Documentation about Offsite Verification Without OCR feature, click
here

Shufti Pro customer collects the image or video proofs from end-users. In the verification request, Shufti Pro customer specifies the keys for the parameters to be verified. Shufti Pro uses a unique template matching technique to match these values to the data on identity documents. Next, Shufti Pro’s intelligently driven system verifies the provided documents for authenticity. Please consult This Document for Offsite without OCR verifications.

These are the services offered in Offsite Verification without OCR: (Face, Document, Address, Consent and Background Checks)

Run in Postman

Instructions

Below mentioned instructions for every service should be followed while uploading the proofs in the iframe.

Face Service
  1. Take a selfie or upload a video of your full face.

  2. Ensure the image or video is not blurred.

  3. Make sure light is not too low or too bright.

  4. Make sure your full face is within the image or video frame.

  5. Don’t crop or cut the edges.

  6. Remove all accessories like glasses, hats, etc.

  7. Don’t edit the image or video in any way (photoshop, crop, etc.).

  8. Maximum image size: 16MB

  9. Maximum video size: 20MB

  10. Image Format: JPG, JPEG, PNG, PDF

  11. Video Format: MP4/MOV

Document & Document Two Service
  1. Take a photo or upload a video of the front side of your document.

  2. There should be sufficient light and avoid glare on the document.

  3. Ensure the image or video is not blurred.

  4. Make sure your full Document is within the image or video.

  5. All edges of the document should be within the frame.

  6. Make sure that document number and expiry date are clearly visible.

  7. Don’t edit the image or video in any way.

  8. Don’t hide, fold or crop any part of the document.

  9. Maximum image size: 16MB

  10. Maximum video size: 20MB

  11. Image Format: JPG, JPEG, PNG, PDF

  12. Video Format: MP4/MOV

Address Service
  1. Upload a photo or upload a video of the full address document.

  2. There should be sufficient light and avoid glare on the address document.

  3. Ensure the image or video is not blurred.

  4. Address should be clearly visible in the image or video.

  5. Don’t edit the image or video in any way.

  6. Don’t hide, fold or crop any part of the address document.

  7. Proof of address document SHOULD NOT BE OLDER THAN THREE MONTHS.

  8. Maximum image size: 16MB

  9. Maximum video size: 20MB

  10. Image Format: JPG, JPEG, PNG, PDF

  11. Video Format: MP4/MOV

  1. Take a photo or Upload a video of your full face with Handwritten or Printed consent note.

  2. Ensure the image or video is not blurred.

  3. There should be sufficient light and avoid glare on the note.

  4. Remove all accessories like glasses, hats, etc.

  5. Your full face and consent note should be within the image or video frame.

  6. Given text should be mentioned on the consent note.

  7. Handwritten or Printed consent note should be legible.

  8. Don’t crop, hide or fold any part of the consent note.

  9. Maximum image size: 16MB

  10. Maximum video size: 20MB

  11. Image Format: JPG, JPEG, PNG, PDF

  12. Video Format: MP4/MOV

Services

Shufti Pro is providing variety of verifications for its customers. Our diverse services suite allows us to validate the identity of users through:

  1. Face Service
  2. Documents Service
  3. Address Service
  4. Background Checks Service
  5. Consent Service
  6. Phone Service
.

We can also check the authenticity of customised documents like official IDs and perform background checks for AML compliance. A mix of various service modules can also be acquired to perform multifaceted verifications like facial and document verification can help you perform a thorough KYC procedure.

Face Service

Face service sample object

{
    "face" : {
        "proof"         : "",
        "allow_offline" : "1",
        "check_duplicate_request" : "1" 
    }
}

The face verification of end-users is the simplest to perform. Shufti Pro authenticates the liveness of the face image of the user.

For offsite verification: The face image of end-user is provided by Shufti Pro’s client that is then verified by Shufti Pro.

For Onsite Verification: End-user will have to show their face in front of a webcam or phone camera for verification

Parameters Description
proof Required: No
Type: string
Image Format: JPG, JPEG, PNG, PDF Maximum: 16MB
Video Format: MP4/MOV Maximum: 20MB
Provide valid BASE64 encoded string. Leave empty for an on-site verification.
allow_offline Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter allows user to upload their selfie in case of non-availability of a functional webcam. If value is 0, users can only perform Face Verification with the camera only.
allow_online Required: No
Type: string
Accepted Values: 0, 1
Default-Value: 1
This parameter allows users to take their selfie in real-time when internet is available. If value: 0 users can upload already captured selfie.
Note: if allow_offline: 0 priority will be given to allow_offline
check_duplicate_request Required: No
Type: string
Accepted Values: 0, 1
Default-Value: 0
This parameter is used to enable the duplicate account detection service. Face mapping technology identify duplicate faces across all customers through which duplicate accounts are detected. The duplicate account detection will be disabled if the value is 0 and enabled if the value is 1.
Document Service

Document service sample object

{
   "document"         : {
        "proof"           : "",
         "additional_proof" : "",
         "supported_types" : ["id_card","driving_license","passport"],
         "name"            : {
           "first_name" : "Johon",
           "last_name"  : "Livone"
         },
         "dob"                  : "1990-10-10",
         "age"                  :  18,
         "issue_date"           : "2015-10-10", 
         "expiry_date"          : "2025-10-10",
         "gender"               :  "M",
         "document_number"      : "1234-1234-ABC",
         "allow_offline"        : "1",
         "fetch_enhanced_data"  : "1",
         "backside_proof_required" : "0",
         "show_ocr_form" : "1"

     }
}

Shufti Pro provides document verification through various types of documents. The supported formats are passports, ID Cards, driving licenses and debit/credit cards. You can opt for more than one document type as well. In that case, Shufti Pro will give an option to end-users to verify their data from any of the given document types.

In case of off-site verification, you can provide more than one document image and use “additional proof” parameter for this. This is to ensure that the required credentials are easily visible e.g. a document might have name and image of individual at the front but the date of birth of that person is printed at the back of the document or on another page of the passport. If you opt for both facial and document verification, face of individual from document will be used to validate uploaded selfie.

Parameters Description
proof Required: No
Type: string
Image Format: JPG, JPEG, PNG, PDF Maximum: 16MB
Video Format: MP4/MOV Maximum: 20MB
Provide valid BASE64 encoded string. Leave empty for an on-site verification.
additional_proof Required: No
Type: string
Image Format: JPG, JPEG, PNG, PDF Maximum: 16MB
Video Format: MP4/MOV Maximum: 20MB
Provide valid BASE64 encoded string. Leave empty for an on-site verification.
supported_types Required: No
Type: Array
Document verification have two parameters: proof and additional_proof. If these two are not set or empty, it means that it should be an on-site verification. You can provide any one, two or more types of documents to verify the identity of user. For example, if you opt for both passport and driving license, then your user will be given an opportunity to verify data from either of these two documents. Please provide only one document type if you are providing proof of that document with the request. All supported types are listed here
Example 1: ["driving_license"]
Example 2: ["id_card", "credit_or_debit_card", "passport"]
dob Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 1990-12-31
age Required: No
Type: integer/array
Allowed values are integers or array.
The Age parameter allows the client to set a minimum and maximum limit for acceptance of a user. The minimum age is defined as min and the maximum is defined as max within this object.
Example: 18
For More Details Age
document_number Required: No
Type: string
Maximum: 100 characters
Allowed Characters are numbers, alphabets, dots, dashes, spaces, underscores and commas.
Example: 35201-0000000-0, ABC1234XYZ098
issue_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2015-12-31
expiry_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2025-12-31
gender Required: No
Type: string
Accepted Values: M,F,O,m,f,o
Provide the gender which is given in the document.
F: Female
M: Male
O: Others
Example: M
allow_offline Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter allows user to upload their document in case of non-availability of a functional webcam. If value is 0, users can only perform Document Verification with the camera only.
allow_online Required: No
Type: string
Accepted Values: 0, 1
Default-Value: 1
This parameter allows users to capture their document in real-time when internet is available. If value: 0 users can upload already captured document.
Note: if allow_offline: 0 priority will be given to allow_offline
fetch_enhanced_data Required: No
Type: string
Value Accepted: 1
Provide 1 for enabling enhanced data extraction for the document. Shufti Pro provides its customers with the facility of extracting enhanced data features using OCR technology. Now, instead of extracting just personal information input fields, Shufti Pro can fetch all the additional information comprising more than 100 data points from the official ID documents supporting 150 languages. For example height, place_of_birth, nationality, marital_status, weight, etc.(additional charges apply)
Extracted data will be returned in object under the key additional_data in case of verification.accepted or verification.declined.
For Details on additional_data object go to Additional Data
name Required: No
Type: object
In name object used in document service, first_name is required if you don't want to perform OCR of the name parameter. Other fields are optional.
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "last_name" : "Doe", "fuzzy_match" : "1"}
Parameters for name are listed here
backside_proof_required Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
If the value of this parameter is set to 1, Shufti Pro will require the end-user to capture/upload both sides of the document to verify the identity. Enabling this parameter will also activate the front and back sides document match feature, which will verify if captured/uploaded front and back sides belong to the same document.
verification_instructions Required: No
Type: Object
This key allows clients to provide additional instruction for the service (document, document_two and address service). Such as if the client wants to allow paper-based, photocopied, laminated, screenshot, cropped or scanned documents for verification.
Example: {"allow_paper_based" : "1"}
For more details on Instructions Parameters click here
show_ocr_form Required: No
Type: boolean
Accepted Values: 0, 1
default value: 1
The default value for this is 1. If this is set to 0, the user will not be shown the OCR form to validate the extracted information. This can be used within the Document, Document Two, and Address service. This value can also be applied to all services collectively. However, preference will be given to the value set within the service.
Note: Setting the value at 0 may cause data inaccuracy as the user does not have option to validate the extracted information.
Document Two Service

Document Two service sample object

{
   "document_two"         : {
        "proof"           : "",
         "additional_proof" : "",
         "supported_types" : ["id_card","driving_license","passport"],
         "name"            : {
           "first_name" : "Johon",
           "last_name"  : "Livone"
         },
         "dob"                  : "1990-10-10",
         "age"                  :  18,
         "issue_date"           : "2015-10-10", 
         "expiry_date"          : "2025-10-10",
         "document_number"      : "1234-1234-ABC",
         "allow_offline"        : "1",
         "fetch_enhanced_data"  : "1",
         "backside_proof_required" : "0",
         "gender"               :  "M",
         "show_ocr_form" : "1"

     }
}

Document Two Service is provided to verify the personal details of a user from more than one document e.g. If you have verified the DOB & Name of a user from their ID Card, you can use Document Two Service to verify the Credit Card Number of your customer.

Just like the “Document Service”, the supported formats for this service are also passports, ID Cards, driving licenses and debit/credit cards and more than one document type can be selected as well. In that case, Shufti Pro will give an option to end-users to verify their data from any of the given document types.

It goes without saying that provided document proofs should belong to the same person in order to verify the identity of the user.

In case of off-site verification, you can provide more than one document image and use “additional proof” parameter for this. This is to ensure that the required credentials are easily visible e.g. a document might have name and image of individual at the front but the date of birth of that person is printed at the back of the document or on another page of the passport. If you opt for both facial and document verification, face of individual from document will be used to validate uploaded selfie.

Parameters Description
proof Required: No
Type: string
Image Format: JPG, JPEG, PNG, PDF Maximum: 16MB
Video Format: MP4/MOV Maximum: 20MB
Provide valid BASE64 encoded string. Leave empty for an on-site verification.
additional_proof Required: No
Type: string
Image Format: JPG, JPEG, PNG, PDF Maximum: 16MB
Video Format: MP4/MOV Maximum: 20MB
Provide valid BASE64 encoded string. Leave empty for an on-site verification.
supported_types Required: No
Type: Array
Document verification have two parameters: proof and additional_proof. If these two are not set or empty, it means that it should be an on-site verification. You can provide any one, two or more types of documents to verify the identity of user. For example, if you opt for both passport and driving license, then your user will be given an opportunity to verify data from either of these two documents. Please provide only one document type if you are providing proof of that document with the request. All supported types are listed here
Example 1: ["driving_license"]
Example 2: ["id_card", "credit_or_debit_card", "passport"]
dob Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 1990-12-31
age Required: No
Type: integer/array
Allowed values are integers or array.
The Age parameter allows the client to set a minimum and maximum limit for acceptance of a user. The minimum age is defined as min and the maximum is defined as max within this object.
Example: 18
For More Details Age
document_number Required: No
Type: string
Maximum: 100 characters
Allowed Characters are numbers, alphabets, dots, dashes, spaces, underscores and commas.
Example 35201-0000000-0, ABC1234XYZ098
issue_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2015-12-31
expiry_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2025-12-31
gender Required: No
Type: string
Accepted Values: M,F,O,m,f,o
Provide the gender which is given in the document.
F: Female
M: Male
O: Others
Example: M
allow_offline Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter allows user to upload their document in case of non-availability of a functional webcam. If value is 0, users can only perform Document Verification with the camera only.
allow_online Required: No
Type: string
Accepted Values: 0, 1
Default-Value: 1
This parameter allows users to capture their document in real-time when internet is available. If value: 0 users can upload already captured document.
Note: if allow_offline: 0 priority will be given to allow_offline
fetch_enhanced_data Required: No
Type: string
Value Accepted: 1
Provide 1 for enabling enhanced data extraction for the document. Shufti Pro provides its customers with the facility of extracting enhanced data features using OCR technology. Now, instead of extracting just personal information input fields, Shufti Pro can fetch all the additional information comprising more than 100 data points from the official ID documents supporting 150 languages. For example height, place_of_birth, nationality, marital_status, weight, etc.(additional charges apply)
Extracted data will be returned in object under the key additional_data in case of verification.accepted or verification.declined.
For Details on additional_data object go to Additional Data
name Required: No
Type: object
In name object used in document service, first_name is required if you don't want to perform OCR of the name parameter. Other fields are optional.
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "last_name" : "Doe", "fuzzy_match" : "1"}
Parameters for name are listed here
backside_proof_required Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
If the value of this parameter is set to 1, Shufti Pro will require the end-user to capture/upload both sides of the document to verify the identity. Enabling this parameter will also activate the front and back sides document match feature, which will verify if captured/uploaded front and back sides belong to the same document.
verification_instructions Required: No
Type: Object
This key allows clients to provide additional instruction for the service (document, document_two and address service). Such as if the client wants to allow paper-based, photocopied, laminated, screenshot, cropped or scanned documents for verification.
Example: {"allow_paper_based" : "1"}
For more details on Instructions Parameters click here
show_ocr_form Required: No
Type: boolean
Accepted Values: 0, 1
default value: 1
The default value for this is 1. If this is set to 0, the user will not be shown the OCR form to validate the extracted information. This can be used within the Document, Document Two, and Address service. This value can also be applied to all services collectively. However, preference will be given to the value set within the service.
Note: Setting the value at 0 may cause data inaccuracy as the user does not have option to validate the extracted information.
Address Service

Address service sample object

{
   "address" : {
       "proof"               : "", 
       "supported_types"     : ["id_card","bank_statement", "envelope"],
       "name"            : {
           "first_name" : "Johon",
           "last_name"  : "Livone"
        },
       "issue_date"          : "2015-10-10",
       "full_address"        : "Candyland Avenue",
       "address_fuzzy_match" : "1",
       "backside_proof_required" : "0",
       "show_ocr_form" : "1"
   }
}

For address verification, a valid identity document is required with the same address printed on it as the one claimed by the end-user. The address can also be verified with the help of Utility Bills and Bank Statements.

For offsite Verification: The address document is provided directly by Shufti Pro’s client that it has already collected from end-user

For Onsite Verification: The address document will be displayed or uploaded by end-user directly for verification.

Parameters Description
proof Required: No
Type: string
Image Format: JPG, JPEG, PNG, PDF Maximum: 16MB
Video Format: MP4/MOV Maximum: 20MB
supported_types Required: No
Type: Array
Provide any one, two or more document types in proof parameter in Address verification service. For example, if you choose id_card and utility_bill, then the user will be able to verify data using either of these two documents. Please provide only one document type if you are providing proof of that document with the request. The Following list Shows Supported Types of Address Verification. It can be found here.
Example 1: [ "utility_bill" ]
Example 2: [ "id_card", "bank_statement" ]
full_address Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
Allowed Characters are numbers, alphabets, dots, dashes, spaces, underscores, hashes and commas.
address_fuzzy_match Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
Provide 1 for enabling a fuzzy match for address verification. Enabling fuzzy matching attempts to find a match which is not 100% accurate. Default value will be 0, which means that only 100% accurate address will be verified.
issue_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2015-12-31
name Required: No
Type: object
In name object used in document service, first_name is required if you don't want to perform OCR of the name parameter. Other fields are optional.
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "last_name" : "Doe", "fuzzy_match" : "1"}
Parameters for name are listed here
backside_proof_required Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
If the value of this parameter is set to 1, Shufti Pro will require the end-user to capture/upload both sides of the document to verify the identity. Enabling this parameter will also activate the front and back sides document match feature, which will verify if captured/uploaded front and back sides belong to the same document.
verification_instructions Required: No
Type: Object
This key allows clients to provide additional instruction for the service (document, document_two and address service). Such as if the client wants to allow paper-based, photocopied, laminated, screenshot, cropped or scanned documents for verification.
Example: {"allow_paper_based" : "1"}
For more details on Instructions Parameters click here
show_ocr_form Required: No
Type: boolean
Accepted Values: 0, 1
default value: 1
The default value for this is 1. If this is set to 0, the user will not be shown the OCR form to validate the extracted information. This can be used within the Document, Document Two, and Address service. This value can also be applied to all services collectively. However, preference will be given to the value set within the service.
Note: Setting the value at 0 may cause data inaccuracy as the user does not have option to validate the extracted information.

Consent service sample object

{
    "consent" : {
          "proof" : "",
          "supported_types"  : ["printed"],
          "text"             : "My name is John Doe and I authorise this transaction of $100/- Date: July 15, 2020",
          "allow_offline"    : "1"
      }
}

Customised documents/notes can also be verified by Shufti Pro. Company documents, employee cards or any other personalised note can be authenticated by this module. You can choose handwritten or printed document format but only one form of document can be verified in this verification module. Text whose presence on the note/customized document is to be verified, is also needed to be provided.

For offsite Verification: The consent document is provided directly by Shufti Pro’s client that it has already collected from end-user

For Onsite Verification: The consent document will be displayed or uploaded by end-user directly for verification.

Parameters Description
proof Required: No
Type: string
Image Format: JPG, JPEG, PNG, PDF Maximum: 16MB
Video Format: MP4/MOV Maximum: 20MB
supported_types Required: No
Type: Array
Text provided in the consent verification can be verified by handwritten documents or printed documents. Supported types are listed here
Example 1: ["printed"]
Example 2: ["printed", "handwritten"]
text Required: Yes
Type: string
Minimum: 2 characters
Maximum: 100 characters
Provide text in the string format which will be verified from a given proof.
allow_offline Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter allows user to upload their Consent Document (Handwritten Note/printed document) in case of non-availability of a functional webcam. If value is 0, users can only perform Consent Verification with the camera only.
allow_online Required: No
Type: string
Accepted Values: 0, 1
Default-Value: 1
This parameter allows users to capture their Consent in real-time when internet is available. If value: 0 users can upload already captured Consent.
Note: if allow_offline: 0 priority will be given to allow_offline
with_face Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter is applicable if supported_type is handwritten and default value is 1. If value of with_face is 1 then hand written note will be accepted only with face which means your customer must need to show his/her face along with the consent on a paper. If value of with_face is 0 then hand written note is accepted with or without face.
Phone Service

Phone service sample object

{
  "phone" : {
      "phone_number"    : "+44127873938323",
      "random_code"     : "55667",
      "text"            : "Your verification code is 55667"
  }
}

Verify the phone number of end-users by sending a random code to their number from Shufti Pro. Once the sent code is entered into the provided field by end-user, phone number will stand verified. It is primarily an on-site verification and you have to provide phone number of the end-user to us, in addition to the verification code and the message that is to be forwarded to the end-user. Shufti Pro will be responsible only to send the message along with verification code to the end-user and verify the code entered by the end-user.
Verification is declined if a user enters the wrong code consecutively for five times.
If the user is unable to receive code then, user is provide with Code not received option if user clicks the “Code not received” option the verification will be declined automatically (because either the phone number was wrong or unreachable).

Parameters Description
phone_number Required: No
Type: string
Minimum: 6 characters
Maximum: 64 characters
Allowed Characters: numbers and plus sign at the beginning. Provide a valid customer’s phone number with country code. Shufti Pro will directly ask the end-user for phone number if this field is missing or empty.
random_code Required: No
Type: string
Minimum: 2 characters
Maximum: 10 characters
Provide a random code. If this field is missing or empty. Shufti Pro will generate a random code.
text Required: No
Type: string
Minimum: 2 characters
Maximum: 100 characters
Provide a short description and random code in this field. This message will be sent to customers. This field should contain random_code. If random_code field is empty then Shufti Pro will generate a random code and append the code with this message at the end.
Background Checks Service

Background checks service sample object

{
  "background_checks" : {
    "name" : {
             "first_name"  : "John",
             "middle_name" : "Carter",
             "last_name"   : "Doe"
    },
    "dob"  : "1995-10-10"
  }
}
{
  "background_checks" : {
    "name" : {
             "full_name"  : "John Carter Doe"         
    },
    "dob"  : "1995-10-10"
  }
}
{
  "background_checks" : {
    "name" : {
             "first_name"  : "John",
             "middle_name" : "Carter",
             "last_name"   : "Doe"
    }
  }
}

It is a verification process that will require you to send us the full Name of end-user in addition to date of birth. Shufti Pro will perform AML based background checks based on this information. Please note that the name and dob keys will be extracted from document service if these keys are empty.

Parameters Description
dob Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 1990-12-31
Note: It is recommended to send dob for more accurate results.
name Required: No
Type: object
In name object used in background checks service, first_name required and other fields are optional. Parameters for name are listed here:
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "middle_name" : "Carter", "last_name" : "Doe"}
Example 3: { "full_name" : "John Carter Doe"}
Note: If full name is provided with first and last name priority will be given to full name.
ongoing Required: No
Accepted values: 0, 1
Default: 0
This Parameter is used for Ongoing AML Screening, and is allowed only on Production Accounts. If Shufti Pro detects a change in AML statuses, then we will send you a webhook with event verification.status.changed. The new AML status can be checked using get status endpoint, or from the back-office. Use fuzzy_match = 1 in the name object for better results for Ongoing AML Screening.

Video KYC

Video KYC service of Shufti Pro verifies the identities of end-users using identity documents such as ID card, passport, and driving license through a live video call. A KYC expert guides the end-user to perform verification and AI will perform face and document verification during the video call. Video KYC service includes face verification, address verification, document verification, 2-factor authentication, and consent verification services. A combination of video KYC services with background checks enables you to perform in-depth identity screening of your customers.

With OCR Verification

With OCR Verification Request

//POST /real_time/verification HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"
{
    "reference"    : "1234567",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "redirect_url": "http://www.example.com",

    "document"         : {
        "supported_types" : ["id_card","driving_license","passport"],
        "name"            : "",
        "dob"             : "",
        "age"             : "",
        "issue_date"      : "", 
        "expiry_date"     : "",
        "document_number" : "",
        "gender"          :  ""
    },

    "address"         : {
        "supported_types"  : ["id_card","bank_statement"],
        "name"             : "",
        "issue_date"       : "",
        "full_address"     : "",
        "address_fuzzy_match":"1",
        "document_number" : ""
    }
}
<?php
$url = 'https://api.shuftipro.com/real_time/verification';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
];

//Use this key if you want to perform document verification with OCR
$verification_request['document'] =[
    'name' => '',
    'dob'             => '',
    'age'             => '',
    'document_number' => '',
    'expiry_date'     => '',
    'issue_date'      => '',
    'supported_types' => ['id_card','passport'],
    'gender'          =>  ''
];

//Use this key if you want to perform address verification with OCR
$verification_request['address'] = [
    'name' => '',
    'full_address'    => '',
    'address_fuzzy_match' => '1',
    'issue_date' => '',
    'supported_types' => ['utility_bill','passport','bank_statement']
];

$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization: Bearer ' . $access_token); 
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];

if($event_name == 'request.pending'){
    if($sp_signature == $calculate_signature){
        $verification_url = $decoded_response['verification_url'];  
        echo "Verification url :" . $verification_url;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>
import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/real_time/verification'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   'https://yourdomain.com/profile/notifyCallback'
}
# Use this key if you want to perform document verification with OCR
verification_request['document'] = {
    'name'              :   '',
    'dob'               :   '',
    'age'               :   '',
    'document_number'   :   '',
    'expiry_date'       :   '',
    'issue_date'        :   '',
    'supported_types'   :   ['id_card','passport'],
    'gender'            :  ''
}
# Use this key want to perform address verification with OCR
verification_request['address'] = {
    'name'              :   '',
    'full_address'      :   '',
    'address_fuzzy_match' : '1',
    'issue_date'        :   '',
    'supported_types'   :   ['utility_bill','passport','bank_statement']
}

# Calling Shufti Pro request API using python  requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')
# Convert json string to json object
json_response = json.loads(response.content)
# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'request.pending':
    if sp_signature == calculated_signature:
        verification_url = json_response['verification_url']
        print ('Verification URL: {}'.format(verification_url))
    else:
        print ('Invalid signature: {}'.format(response.content))
let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    redirect_url      : "https://yourdomain.com/site/sp-redirect",
    country           : "GB",
    language          : "EN",
}
//Use this key if you want to perform document verification with OCR
payload['document'] = {
  name            : '',
  dob             : '',
  age             : '',
  document_number : '',
  expiry_date     : '',
  issue_date      : '',
  supported_types : ['id_card','passport'],
  gender          :  ''
}
//Use this key if you want to perform address verification with OCR
payload['address'] = {
  name               : '',
  full_address       : '',
  address_fuzzy_match : '1',
  issue_date         : '',
  supported_types    : ['utility_bill','passport','bank_statement']
}
//BASIC AUTH TOKEN
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/real_time/verification', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
    if (data.event && data.event === 'request.pending') {
          createIframe(data.verification_url)
    }
});

//Method used to create an Iframe
function createIframe(src) {

    let iframe = document.createElement('iframe');
    iframe.style.position = 'fixed';
    iframe.id = 'shuftipro-iframe';
    iframe.name = 'shuftipro-iframe';
    iframe.allow = "camera";
    iframe.src = src;
    iframe.style.top = 0;
    iframe.style.left = 0;
    iframe.style.bottom = 0;
    iframe.style.right = 0;
    iframe.style.margin = 0;
    iframe.style.padding = 0;
    iframe.style.overflow = 'hidden';
    iframe.style.border = "none";
    iframe.style.zIndex = "2147483647";
    iframe.width = "100%";
    iframe.height = "100%";
    iframe.dataset.removable = true;

    document.body.appendChild(iframe);
}
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/real_time/verification")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com"
}
# Use this key if you want to perform document verification with OCR
verification_request["document"] = {
    supported_types: ["id_card","driving_license","passport"],
    name:             "",
    dob:              "",
    age:              "",
    issue_date:       "", 
    expiry_date:      "",
    document_number:  "",
    gender:  ''
}
# Use this key if you want to perform address verification with OCR
verification_request["address"] = {
    supported_types:     ["id_card","bank_statement"],
    name:                "",
    issue_date:          "",
    full_address:        "",
    address_fuzzy_match: "1"
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json
response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY
if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

In the verification request with OCR, Shufti Pro's customer specifies the keys for the parameters to be verified. Shufti Pro extracts the required information from the document and then the verification form is automatically filled with the extracted information. This reduces the manual work for the end-user. Next, Shufti Pro’s intelligently driven system verifies the provided documents for authenticity.

OCR is offered on the following services: (Document and Address) but Shufti Pro customers can also avail other non-OCR services such as Face & Phone Verification along with these OCR services.

Run in Postman

Parameters Description
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
Each request is issued a unique reference ID which is sent back to Shufti Pro’s client with each response. This reference ID helps to verify the request. The client can use this ID to check the status of already performed verifications.
country Required: No
Type: string
Length: 2 characters
You may omit this parameter if you don't want to enforce country verification. If a valid country code is provided, then the proofs for document verification or address verification must be from the same country. Country code must be a valid ISO 3166-1 alpha-2 country code. Please consult Supported Countries for country codes.
language Required: No
Type: string
Length: 2 characters
If the Shufti Pro client wants their preferred language to appear on the verification screens they may provide the 2-character long language code of their preferred language. The list of Supported Languages can be consulted for the language codes. If this key is missing in the request the system will select the default language as English.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents email of the end-user.
callback_url Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
A number of server-to-server calls are made to Shufti Pro’s client to keep them updated about the verification status. This allows the clients to keep the request updated on their end, even if the end-user is lost midway through the process.
redirect_url Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
Once an on-site verification is complete, User is redirected to this link after showing the results.
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays a screen to collect consent from end-user before the verification process starts. If the value is set 1, the screen will be displayed to end-user. If the value is set 0, the consent screen will not be displayed. Under the GDPR, we are bound to get user’s consent therefore the default value is 1 but you can set it to 0 if you’ve already acquired the user’s consent for this biometric verification.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve have another alternative mechanism in place.
show_feedback_form Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter will work only for onsite verification. If its value is 1 at the end of verification, a feedback form is displayed to the end-user to collect his/her feedback. If it is 0 then it will not display the feedback page to the end-user.
manual_review Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
This key can be used if the client wants to review verifications after processing from Shufti Pro has completed. Once the user submits any/all required documents, Shufti Pro returns a status of review.pending. The client can then review the verification details and Accept OR Decline the verifications from the back-office.
face Required: No
Type: object
This service key corresponds to Face Verification Service in which unique facial features of end-user are identified and verified in real-time.
Example 1: {}
for more details Face Service
document Required: No
Type: object
This service key corresponds to Document verification service in which the authenticity of identity documents submitted by end-users is checked. Once verified, these identity documents serve as proof of end-user’s identity.
Example 1: { "document_number": "", "issue_date": "", "expiry_date": "", "dob": "", "name": "", "supported_types": ["id_card", "credit_or_debit_card", "passport"]}
for more details Document Service
address Required: No
Type: object
This service key corresponds to Address Verification service in which the authenticity of an end-user's provided address is checked with the help of an authentic Identity document, Utility bill or bank statement
Example 1: {"supported_types" : ["id_card","bank_statement"],"name": "","full_address": "" }
for more details Address Service
consent Required: No
Type: object
This service key corresponds to Consent Verification services in which the consent provided by end-user for a certain action is cross-checked with the help of a handwritten document or customized printed document
Example 1: {"supported_types" : ["printed"],"text" : ""}
for more details Consent Service
phone Required: No
Type: object
This service key corresponds to Phone Verification service of Shufti Pro. A customized code is sent to end-user on their phone number, that is sent back by end-user to verify their identity.
Example 1: {"phone_number" : "","random_code" : "","text" : ""}
for more details Phone Service
background_checks Required: No
Type: object
This service key corresponds to AML Screening service offered by Shufti Pro. An AML background check is performed for every end-user in this service against a financial risk database compiled by Shufti Pro
Example 1: {"name" : "", "dob" : "" }
for more details Background Checks service

Without OCR Verification

Without OCR Verification Request

//POST /real_time/verification HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"

{
    "reference"    : "5667456341",
    "callback_url" : "http://www.example.com/",
    "email"        : "johndoe@example.com",
    "country"      : "GB",
    "language"     : "EN",
    "face": "",

    "document"         : {
        "supported_types" : ["id_card","driving_license","passport"],
        "name"             : {
             "first_name"   : "John",
             "middle_name"  : "Middleman",
             "last_name"    : "Doe"
        },
        "dob"             : "1980-11-12",
        "age"             :  18,
        "issue_date"      : "1990-09-07", 
        "expiry_date"     : "2050-10-10",
        "document_number" : "0989-7752-6291-2387",
        "gender"          :  "M"
    },

    "address"         : {
        "supported_types"  : ["id_card","bank_statement"],
        "name"             : {
             "first_name"   : "John",
             "middle_name"  : "Middleman",
             "last_name"    : "Doe"
        },
        "full_address"      : "3339 Maryland Avenue, Largo, Florida",
        "address_fuzzy_match":"1",
        "issue_date"        : "1990-09-07"
    },

    "consent":{
        "supported_types" : ["handwritten","printed"],
        "text"   : "My name is John Doe and I authorise this transaction of $100/- Date: July 15, 2020"
    },

    "phone": {
        "phone_number" : "+4400000000",
        "random_code"  : "23234",
        "text"         : "Your verification code is 23234"
    },

    "background_checks": {
        "name"             : {
             "first_name"   : "John",
             "middle_name"  : "Middleman",
             "last_name"    : "Doe"
        },
        "dob"             : "1980-11-12"
    }
}
<?php
$url = 'https://api.shuftipro.com/real_time/verification';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';
$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
];
//Use this key if you want to perform face verification
$verification_request['face'] = "";
//Use this key if you want to perform document verification
$verification_request['document'] =[
    'name' => [
        'first_name' => 'Your first name',
        'middle_name' => 'Your middle name',
        'last_name'  => 'You last name',
        'fuzzy_match' => '1'
    ],
    'dob'             => '1992-10-10',
    'age'             =>  18,
    'document_number' => '2323-5629-5465-9990',
    'expiry_date'     => '2025-10-10',
    'issue_date'      => '2015-10-10',
    'supported_types' => ['id_card','passport'],
    'gender'          =>  'M'
];
//Use this key if you want to perform address verification
$verification_request['address'] = [
    'name' => [
        'first_name' => 'Your first name',
        'middle_name' => 'Your middle name',
        'last_name'  => 'You last name',
        'fuzzy_match' => '1'
    ],
    'full_address'    => 'your address',
    'address_fuzzy_match' => '1',
    'issue_date' => '2015-10-10',
    'supported_types' => ['utility_bill','passport','bank_statement']
];

//Use this key if you want to perform consent verification
$verification_request['consent'] =[
    'text'            => 'some text for consent verification',
    'supported_types' => ['handwritten']
];

//Use this key if you want to perform phone verification
$verification_request['phone'] =[
    'phone_number'    => '+1378746734',
    'random_code'     => '9977',
    'text'            => 'Your verification code is 9977'
];
//Use this key if you want to perform aml/background checks verification
$verification_request['background_checks'] = [
    'name' => [
        'first_name' => 'Your first name',
        'middle_name' => 'Your middle name',
        'last_name'  => 'You last name'
    ],
    'dob'             => '1992-10-10',
];
$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization : Bearer ' . $access_token);
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];
if($event_name == 'request.pending'){
    if($sp_signature == $calculate_signature){
        $verification_url = $decoded_response['verification_url'];
        echo "Verification url :" . $verification_url;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>
import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/real_time/verification'
callback_url = 'https://yourdomain.com/profile/notifyCallback'

# Your Shufti Pro account Client ID
client_id = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   callback_url
}
# Use this key if want to perform face verification
verification_request['face'] = {}
# Use this key if want to perform document verification
verification_request['document'] = {
    'name'      :   {
        'first_name'    :   'Your first name', 
        'middle_name'   :   'Your middle name', 
        'last_name'     :   'Your last name',
        'fuzzy_match'   :   '1'
    },
    'dob'             : '1992-10-10',
    'age'             :  18,
    'document_number' : '2323-5629-5465-9990',
    'expiry_date'     : '2025-10-10',
    'issue_date'      : '2015-10-10',
    'supported_types' : ['id_card','passport'],
    'gender'        :  'M'
}
# Use this key if want to perform address verification
verification_request['address'] =  {
    'name'      :   {
        'first_name'    :   'Your first name', 
        'middle_name'   :   'Your middle name', 
        'last_name'     :   'Your last name',
        'fuzzy_match'   :   '1'
    },
    'full_address'    : 'your address',
    'address_fuzzy_match' : '1',
    'issue_date'        :   '2015-10-10',
    'supported_types' : ['utility_bill','passport','bank_statement']
}
# Use this key if want to perform consent verification
verification_request['consent'] =  {
    'text'          :   'some text for consent verification',
    'supported_type':   ['handwritten']
}
# Use this key if want to perform phone verification
verification_request['phone'] =    {
    'phone_number'    : '+1378746734',
    'random_code'     : '9977',
    'text'            : 'Your verification code is 9977'
}
# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')
# Convert json string to json object
json_response = json.loads(response.content)
# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'request.pending':
    if sp_signature == calculated_signature:
        verification_url = json_response['verification_url']
        print ('Verification URL: {}'.format(verification_url))
    else:
        print ('Invalid signature: {}'.format(response.content))
let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    redirect_url      : "https://yourdomain.com/site/sp-redirect",
    country           : "GB",
    language          : "EN"
}
//Use this key if you want to perform face verification
payload['face'] = {};
//Use this key if you want to perform document verification
payload['document'] = {
  name : {
        first_name  : 'Your first name',
        middle_name : 'Your middle name',
        last_name   : 'You last name',
        fuzzy_match : '1'
    },
    dob             : '1992-10-10',
    age             :  18,
    document_number : '2323-5629-5465-9990',
    expiry_date     : '2025-10-10',
    issue_date      : '2015-10-10',
    supported_types : ['id_card','passport'],
    gender          :  'M'
}
//Use this key if you want to perform address verification
payload['address'] = {
  name : {
        first_name  : 'Your first name',
        middle_name : 'Your middle name',
        last_name   : 'You last name',
        fuzzy_match : '1'
    },
    full_address    : 'your address',
    address_fuzzy_match : '1',
    issue_date : '2015-10-10',
    supported_types : ['utility_bill','passport','bank_statement']
}

//Use this key if you want to perform background checks verification
payload['background_checks'] = {
  name : {
        first_name  : 'Your first name',
        middle_name : 'Your middle name',
        last_name   : 'You last name',
    },
    dob    : '1994-01-01',
}
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/real_time/verification', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
    if (data.event && data.event === 'request.pending') {
          createIframe(data.verification_url)
    }
});

//Method used to create an Iframe
function createIframe(src) {

    let iframe = document.createElement('iframe');
    iframe.style.position = 'fixed';
    iframe.id = 'shuftipro-iframe';
    iframe.name = 'shuftipro-iframe';
    iframe.allow = "camera";
    iframe.src = src;
    iframe.style.top = 0;
    iframe.style.left = 0;
    iframe.style.bottom = 0;
    iframe.style.right = 0;
    iframe.style.margin = 0;
    iframe.style.padding = 0;
    iframe.style.overflow = 'hidden';
    iframe.style.border = "none";
    iframe.style.zIndex = "2147483647";
    iframe.width = "100%";
    iframe.height = "100%";
    iframe.dataset.removable = true;

    document.body.appendChild(iframe);
}
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/real_time/verification")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:             "johndoe@example.com",
    country:            "GB",
    language:           "EN",
    redirect_url:       "http://www.example.com"
}
# Use this key if you want to perform document verification with OCR
verification_request["document"] = {
    supported_types: ["id_card","driving_license","passport"],
    name:            {
      first_name: "Johon",
      last_name:  "Livone"
    },
    dob:             "1990-10-10",
    age:              18,
    issue_date:      "2015-10-10", 
    expiry_date:     "2025-10-10",
    document_number: "1234-1234-ABC",
    gender:          "M"
}
# Use this key if you want to perform address verification with OCR
verification_request["address"] = {
    supported_types:     ["id_card","bank_statement"],
    name:                {
      first_name: "Johon",
      last_name:  "Livone"
    },
    issue_date:          "2015-10-10",
    full_address:        "Candyland Avenue",
    address_fuzzy_match: "1"
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY
if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

In the verification request without OCR, Shufti Pro's customer specifies the keys for the parameters to be verified. Shufti Pro uses a unique template matching technique to match these values to the data on identity documents. Next, Shufti Pro’s intelligently driven system verifies the provided documents for authenticity.

These are the services offered in Verification without OCR: (Face, Document, Address, Consent, Phone and Background Checks)

Run in Postman

Parameters Description
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
Each request is issued a unique reference ID which is sent back to Shufti Pro’s client with each response. This reference ID helps to verify the request. The client can use this ID to check the status of already performed verifications.
country Required: No
Type: string
Length: 2 characters
You may omit this parameter if you don't want to enforce country verification. If a valid country code is provided, then the proofs for document verification or address verification must be from the same country. Country code must be a valid ISO 3166-1 alpha-2 country code. Please consult Supported Countries for country codes.
language Required: No
Type: string
Length: 2 characters
If the Shufti Pro client wants their preferred language to appear on the verification screens they may provide the 2-character long language code of their preferred language. The list of Supported Languages can be consulted for the language codes. If this key is missing in the request the system will select the default language as English.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents email of the end-user.
callback_url Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
A number of server-to-server calls are made to Shufti Pro’s client to keep them updated about the verification status. This allows the clients to keep the request updated on their end, even if the end-user is lost midway through the process.
redirect_url Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
Once an on-site verification is complete, User is redirected to this link after showing the results.
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays a screen to collect consent from end-user before the verification process starts. If the value is set 1, the screen will be displayed to end-user. If the value is set 0, the consent screen will not be displayed. Under the GDPR, we are bound to get user’s consent therefore the default value is 1 but you can set it to 0 if you’ve already acquired the user’s consent for this biometric verification.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve have another alternative mechanism in place.
show_feedback_form Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter will work only for onsite verification. If its value is 1 at the end of verification, a feedback form is displayed to the end-user to collect his/her feedback. If it is 0 then it will not display the feedback page to the end-user.
manual_review Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
This key can be used if the client wants to review verifications after processing from Shufti Pro has completed. Once the user submits any/all required documents, Shufti Pro returns a status of review.pending. The client can then review the verification details and Accept OR Decline the verifications from the back-office.
face Required: No
Type: object
This service key corresponds to Face Verification Service in which unique facial features of end-user are identified and verified in real-time.
Example 1: {}
for more details Face Service
document Required: No
Type: object
This service key corresponds to Document verification service in which the authenticity of identity documents submitted by end-users is checked. Once verified, these identity documents serve as proof of end-user’s identity.
Example 1: { "document_number": "ABC1234XYZ098", "issue_date": "2015-12-31", "expiry_date": "2025-12-31", "dob": "1990-12-31", "name": { "first_name" : "John", "last_name" : "Doe" } , "supported_types": ["id_card", "credit_or_debit_card", "passport"]}
for more details Document Service
address Required: No
Type: object
This service key corresponds to Address Verification service in which the authenticity of an end-user's provided address is checked with the help of an authentic Identity document, Utility bill or bank statement
Example 1: {"supported_types" : ["id_card","bank_statement"],"name" : {"first_name" : "John", "last_name" : "Doe" } ,"full_address": "Candyland Avenue" }
for more details Address Service
consent Required: No
Type: object
This service key corresponds to Consent Verification services in which the consent provided by end-user for a certain action is cross-checked with the help of a handwritten document or customized printed document
Example 1: {"supported_types" : ["printed"],"text" : "Hi, I am giving my consent"}
for more details Consent Service
phone Required: No
Type: object
This service key corresponds to Phone Verification service of Shufti Pro. A customized code is sent to end-user on their phone number, that is sent back by end-user to verify their identity.
Example 1: {"phone_number" : "+00000000000000","random_code" : "12345","text" : "Your Shuftipro verification code is "}
for more details Phone Service
background_checks Required: No
Type: object
This service key corresponds to AML Screening service offered by Shufti Pro. An AML background check is performed for every end-user in this service against a financial risk database compiled by Shufti Pro
Example 1: {"name" : {"first_name" : "John", "last_name" : "Doe"}, "dob" : "1990-12-31" }
for more details Background Checks service

Services

Shufti Pro is providing variety of verifications for its customers. Our diverse services suite allows us to validate the identity of users through:

  1. Face Service
  2. Documents Service
  3. Address Service
  4. Background Checks Service
  5. Consent Service
  6. Phone Service

We can also check the authenticity of customised documents like official IDs and perform background checks for AML compliance. A mix of various service modules can also be acquired to perform multifaceted verifications like facial and document verification can help you perform a thorough KYC procedure.

Face Service

Face service sample object

{
    "face" : {}
}

The face verification of end-users is the simplest to perform. Shufti Pro authenticates the liveness of the face image of the user.

Document Service

Document service sample object

{
   "document"         : {
         "supported_types" : ["id_card","driving_license","passport"],
         "name"            : {
           "first_name" : "Johon",
           "last_name"  : "Livone"
         },
         "dob"                  : "1990-10-10",
         "age"                  :  18,
         "issue_date"           : "2015-10-10", 
         "expiry_date"          : "2025-10-10",
         "document_number"      : "1234-1234-ABC",
         "fetch_enhanced_data"  : "1",
         "gender"               :  "M",
         "show_ocr_form"        :  "1"
     }
}

Shufti Pro provides document verification through various types of documents. The supported formats are passports, ID Cards, driving licenses and debit/credit cards. You can opt for more than one document type as well. In that case, Shufti Pro will give an option to end-users to verify their data from any of the given document types.

Parameters Description
supported_types Required: No
Type: Array
You can provide any one, two or more types of documents to verify the identity of user. For example, if you opt for both passport and driving license, then your user will be given an opportunity to verify data from either of these two documents. All supported types are listed here
Example 1: ["driving_license"]
Example 2: ["id_card", "credit_or_debit_card", "passport"]
dob Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 1990-12-31
age Required: No
Type: integer/array
Allowed values are integers or array.
The Age parameter allows the client to set a minimum and maximum limit for acceptance of a user. The minimum age is defined as min and the maximum is defined as max within this object.
Example: 18
For More Details Age
document_number Required: No
Type: string
Maximum: 100 characters
Allowed Characters are numbers, alphabets, dots, dashes, spaces, underscores and commas.
Example: 35201-0000000-0, ABC1234XYZ098
issue_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2015-12-31
expiry_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2025-12-31
gender Required: No
Type: string
Accepted Values: M,F,O,m,f,o
Provide the gender which is given in the document.
F: Female
M: Male
O: Others
Example: M
fetch_enhanced_data Required: No
Type: string
Value Accepted: 1
Provide 1 for enabling enhanced data extraction for the document. Shufti Pro provides its customers with the facility of extracting enhanced data features using OCR technology. Now, instead of extracting just personal information input fields, Shufti Pro can fetch all the additional information comprising more than 100 data points from the official ID documents supporting 150 languages. For example height, place_of_birth, nationality, marital_status, weight, etc.(additional charges apply)
Extracted data will be returned in object under the key additional_data in case of verification.accepted or verification.declined.
For Details on additional_data object go to Additional Data
name Required: No
Type: object
In name object used in document service, first_name is required if you don't want to perform OCR of the name parameter. Other fields are optional.
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "last_name" : "Doe", "fuzzy_match" : "1"}
Parameters for name are listed here
verification_instructions Required: No
Type: Object
This key allows clients to provide additional instruction for the service (document, document_two and address service). Such as if the client wants to allow paper-based, photocopied, laminated, screenshot, cropped or scanned documents for verification.
Example: {"allow_paper_based" : "1"}
For more details on Instructions Parameters click here
show_ocr_form Required: No
Type: boolean
Accepted Values: 0, 1
default value: 1
The default value for this is 1. If this is set to 0, the user will not be shown the OCR form to validate the extracted information. This can be used within the Document, Document Two, and Address service. This value can also be applied to all services collectively. However, preference will be given to the value set within the service.
Note: Setting the value at 0 may cause data inaccuracy as the user does not have option to validate the extracted information.
Document Two Service

Document Two service sample object

{
   "document_two"         : {
         "supported_types" : ["id_card","driving_license","passport"],
         "name"            : {
           "first_name" : "Johon",
           "last_name"  : "Livone"
         },
         "dob"                  : "1990-10-10",
         "age"                  :  18,
         "issue_date"           : "2015-10-10", 
         "expiry_date"          : "2025-10-10",
         "document_number"      : "1234-1234-ABC",
         "fetch_enhanced_data"  : "1",
         "gender"               :  "M",
         "show_ocr_form"        :  "1"

     }
}

Document Two Service is provided to verify the personal details of a user from more than one document e.g. If you have verified the DOB & Name of a user from their ID Card, you can use Document Two Service to verify the Credit Card Number of your customer.

Just like the “Document Service”, the supported formats for this service are also passports, ID Cards, driving licenses and debit/credit cards and more than one document type can be selected as well. In that case, Shufti Pro will give an option to end-users to verify their data from any of the given document types.

Parameters Description
supported_types Required: No
Type: Array
You can provide any one, two or more types of documents to verify the identity of user. For example, if you opt for both passport and driving license, then your user will be given an opportunity to verify data from either of these two documents. All supported types are listed here
Example 1: ["driving_license"]
Example 2: ["id_card", "credit_or_debit_card", "passport"]
dob Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 1990-12-31
age Required: No
Type: integer/array
Allowed values are integers or array .
The Age parameter allows the client to set a minimum and maximum limit for acceptance of a user. The minimum age is defined as min and the maximum is defined as max within this object.
Example: 18
For More Details Age
document_number Required: No
Type: string
Maximum: 100 characters
Allowed Characters are numbers, alphabets, dots, dashes, spaces, underscores and commas.
Example: 35201-0000000-0, ABC1234XYZ098
issue_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2015-12-31
expiry_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2025-12-31
gender Required: No
Type: string
Accepted Values: M,F,O,m,f,o
Provide the gender which is given in the document.
F: Female
M: Male
O: Others
Example: M
fetch_enhanced_data Required: No
Type: string
Value Accepted: 1
Provide 1 for enabling enhanced data extraction for the document. Shufti Pro provides its customers with the facility of extracting enhanced data features using OCR technology. Now, instead of extracting just personal information input fields, Shufti Pro can fetch all the additional information comprising more than 100 data points from the official ID documents supporting 150 languages. For example height, place_of_birth, nationality, marital_status, weight, etc.(additional charges apply)
Extracted data will be returned in object under the key additional_data in case of verification.accepted or verification.declined.
For Details on additional_data object go to Additional Data
name Required: No
Type: object
In name object used in document service, first_name is required if you don't want to perform OCR of the name parameter. Other fields are optional.
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "last_name" : "Doe", "fuzzy_match" : "1"}
Parameters for name are listed here
verification_instructions Required: No
Type: Object
This key allows clients to provide additional instruction for the service (document, document_two and address service). Such as if the client wants to allow paper-based, photocopied, laminated, screenshot, cropped or scanned documents for verification.
Example: {"allow_paper_based" : "1"}
For more details on Instructions Parameters click here
show_ocr_form Required: No
Type: boolean
Accepted Values: 0, 1
default value: 1
The default value for this is 1. If this is set to 0, the user will not be shown the OCR form to validate the extracted information. This can be used within the Document, Document Two, and Address service. This value can also be applied to all services collectively. However, preference will be given to the value set within the service.
Note: Setting the value at 0 may cause data inaccuracy as the user does not have option to validate the extracted information.
Address Service

Address service sample object

{
   "address" : {
       "supported_types"     : ["id_card","bank_statement"],
       "name"            : {
           "first_name" : "Johon",
           "last_name"  : "Livone"
        },
       "issue_date"          : "2015-10-10",
       "full_address"        : "Candyland Avenue",
       "address_fuzzy_match" : "1",
       "show_ocr_form"       : "1"
   }
}

For address verification, a valid identity document is required with the same address printed on it as the one claimed by the end-user. The address can also be verified with the help of Utility Bills and Bank Statements.

Parameters Description
supported_types Required: No
Type: Array
Provide any one, two or more document types in proof parameter in Address verification service. For example, if you choose id_card and utility_bill, then the user will be able to verify data using either of these two documents. Please provide only one document type if you are providing proof of that document with the request. The Following list Shows Supported Types of Address Verification. It can be found here.
Example 1: [ "utility_bill" ]
Example 2: [ "id_card", "bank_statement" ]
full_address Required: No
Type: string
Minimum: 6 characters
Maximum: 250 characters
Allowed Characters are numbers, alphabets, dots, dashes, spaces, underscores, hashes and commas.
address_fuzzy_match Required: No
Type: string
Accepted Values: 0, 1
Default Value: 0
Provide 1 for enabling a fuzzy match for address verification. Enabling fuzzy matching attempts to find a match which is not 100% accurate. Default value will be 0, which means that only 100% accurate address will be verified.
issue_date Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 2015-12-31
name Required: No
Type: object
In name object used in document service, first_name is required if you don't want to perform OCR of the name parameter. Other fields are optional.
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "last_name" : "Doe", "fuzzy_match" : "1"}
Parameters for name are listed here
verification_instructions Required: No
Type: Object
This key allows clients to provide additional instruction for the service (document, document_two and address service). Such as if the client wants to allow paper-based, photocopied, laminated, screenshot, cropped or scanned documents for verification.
Example: {"allow_paper_based" : "1"}
For more details on Instructions Parameters click here
show_ocr_form Required: No
Type: boolean
Accepted Values: 0, 1
default value: 1
The default value for this is 1. If this is set to 0, the user will not be shown the OCR form to validate the extracted information. This can be used within the Document, Document Two, and Address service. This value can also be applied to all services collectively. However, preference will be given to the value set within the service.
Note: Setting the value at 0 may cause data inaccuracy as the user does not have option to validate the extracted information.

Consent service sample object

{
    "consent" : {
          "supported_types"  : ["printed"],
          "text"             : "My name is John Doe and I authorise this transaction of $100/- Date: July 15, 2020"
      }
}

Customised documents/notes can also be verified by Shufti Pro. Company documents, employee cards or any other personalised note can be authenticated by this module. You can choose handwritten or printed document format but only one form of document can be verified in this verification module. Text whose presence on the note/customized document is to be verified, is also needed to be provided.

Parameters Description
supported_types Required: No
Type: Array
Text provided in the consent verification can be verified by handwritten documents or printed documents. Supported types are listed here
Example 1: ["printed"]
Example 2: ["printed", "handwritten"]
text Required: Yes
Type: string
Minimum: 2 characters
Maximum: 100 characters
Provide text in the string format which will be verified from a given proof.
with_face Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter is applicable if supported_type is handwritten and default value is 1. If value of with_face is 1 then hand written note will be accepted only with face which means your customer must need to show his/her face along with the consent on a paper. If value of with_face is 0 then hand written note is accepted with or without face.
Phone Service

Phone service sample object

{
  "phone" : {
      "phone_number"    : "+44127873938323",
      "random_code"     : "55667",
      "text"            : "Your verification code is 55667"
  }
}

Verify the phone number of end-users by sending a random code to their number from Shufti Pro. Once the sent code is entered into the provided field by end-user, phone number will stand verified. It is primarily an on-site verification and you have to provide phone number of the end-user to us, in addition to the verification code and the message that is to be forwarded to the end-user. Shufti Pro will be responsible only to send the message along with verification code to the end-user and verify the code entered by the end-user.
Verification is declined if a user enters the wrong code consecutively for five times.
If the user is unable to receive code then, user is provide with Code not received option if user clicks the “Code not received” option the verification will be declined automatically (because either the phone number was wrong or unreachable).

Parameters Description
phone_number Required: No
Type: string
Minimum: 6 characters
Maximum: 64 characters
Allowed Characters: numbers and plus sign at the beginning. Provide a valid customer’s phone number with country code. Shufti Pro will directly ask the end-user for phone number if this field is missing or empty.
random_code Required: No
Type: string
Minimum: 2 characters
Maximum: 10 characters
Provide a random code. If this field is missing or empty. Shufti Pro will generate a random code.
text Required: No
Type: string
Minimum: 2 characters
Maximum: 100 characters
Provide a short description and random code in this field. This message will be sent to customers. This field should contain random_code. If random_code field is empty then Shufti Pro will generate a random code and append the code with this message at the end.
Background Checks Service

Background Checks service sample object

{
  "background_checks" : {
    "name" : {
             "first_name"  : "John",
             "middle_name" : "Carter",
             "last_name"   : "Doe"
    },
    "dob"  : "1995-10-10"
  }
}
{
  "background_checks" : {
    "name" : {
             "full_name"  : "John Carter Doe"         
    },
    "dob"  : "1995-10-10"
  }
}
{
  "background_checks" : {
    "name" : {
             "first_name"  : "John",
             "middle_name" : "Carter",
             "last_name"   : "Doe"
    }
  }
}

It is a verification process that will require you to send us the full Name of end-user in addition to date of birth. Shufti Pro will perform AML based background checks based on this information. Please note that the name and dob keys will be extracted from document service if these keys are empty.

Parameters Description
dob Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 1990-12-31
Note: It is recommended to send dob for more accurate results.
name Required: No
Type: object
In name object used in background checks service, first_name required and other fields are optional. Parameters for name are listed here:
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "middle_name" : "Carter", "last_name" : "Doe"}
Example 3: { "full_name" : "John Carter Doe"}
Note: If full name is provided with first and last name priority will be given to full name.
ongoing Required: No
Accepted values: 0, 1
Default: 0
This Parameter is used for Ongoing AML Screening, and is allowed only on Production Accounts. If Shufti Pro detects a change in AML statuses, then we will send you a webhook with event verification.status.changed. The new AML status can be checked using get status endpoint, or from the back-office. Use fuzzy_match = 1 in the name object for better results for Ongoing AML Screening.

Biometric

Shufti Pro Biometric SDK/API authenticates users with Facial Authentication. The SDK uses two different security tokens to handle requests. It collects image/video proofs, and processes and saves them for future authentication. It generates different responses according to the nature of request.

Request

Every verification request received from the end-user or Shufti Pro customer is assessed on certain parameters (discussed in detail below) by Shufti Pro’s intelligent system.

Biometric Request Example

//POST /biometric/auth HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic WU9VUiBDTElFTlQgSUQ6WU9VUiBDTElFTlQgU0VDUkVU

{
    "webhook_url" : "http://www.example.com/",
    "reference"   : "123weqwe1231",
    "language"    : "EN",
    "document"    : 1,
    "phone"       : 1,
    "question"    : 1,
    "request_type" : "enroll",
    "email" : ""
}

<?php

$clientID = 'YOUR CLIENT ID';
$clientSecret = 'YOUR CLIENT SECRET';
$basic_auth = base64_encode ( $clientID . ":" . $clientSecret );

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.shuftipro.com/biometric/auth",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\"webhook_url\": \"http://www.example.com\",\"request_type\" : \"enroll\",\"language\" : \"EN\",\"reference\": \"123abc123\",\"document\": 1,\"phone\": 1,\"question\": 1,\"email\" : \"\"}",
  CURLOPT_HTTPHEADER => array(
    "Authorization: Basic " . $basic_auth,
    "Content-Type: application/json",
  )
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

?>


import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/'

# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'

# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'

auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()

url = "https://api.shuftipro.com/biometric/auth"

payload = "{\"webhook_url\": \"http://www.example.com\",\"language\" : \"EN\",\"request_type\" : \"enroll\",\"email\" : \"\",\"reference\": \"123abc123\",\"document\": 1,\"phone\": 1,\"question\": 1}"
headers = {
    'Content-Type': "application/json",
    'Authorization': "Basic %s" % b64Val
    }

response = requests.request("POST", url, data=payload, headers=headers)

print(json.loads(response.text))


//We will be using two common practises for send Api calls
//Dispatch request via Jquery Ajax API
var payload = {
  "async": true,
  "crossDomain": true,
  "url": "https://api.shuftipro.com/biometric/auth",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Basic WU9VUiBDTElFTlQgSUQ6WU9VUiBDTElFTlQgU0VDUkVU",
    "cache-control": "no-cache",
  },
  "processData": false,
  "data": {
          "webhook_url": "http://www.example.com",
          "request_type": "enroll",
          "language"    : "EN",
          "email"      : "",
          "reference": "123abc123",
          "document": 1,
          "phone": 1,
          "question": 1
      }
}

$.ajax(payload).done(function (response) {
  console.log(response);
});

require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/biometric/auth")
# Your Shufti Pro account Client ID
CLIENT_ID  = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY = "YOUR-SECRET-KEY"
post_data = { 
     webhook_url: "http://www.example.com",
     reference: "123abc123",
     language: "EN",
     request_type: "enroll",
     email: "",
     document: 1,
     phone: 1,
     question: 1
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body             = post_data.to_json

response = http.request(request)
response_data    = JSON.parse(response.read_body)

puts response_data

Token request received from the end-user is assessed on specific parameters (discussed below):

Request Parameters

Parameters Description
webhook_url Required: Yes
Type: string
This allows the Client to receive response of request, either success or fail.
language Required: No
Type: string
Length: 2 characters
If the Shufti Pro client wants their preferred language to appear on the authentication screens they may provide the 2-character long language code of their preferred language. The list of Supported Languages can be consulted for the language codes. If this key is missing in the request the system will select the default language as English.
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 64 characters
Each request has a unique Reference ID which is sent back to Client against each response. The Client can use the Reference ID to check status of each verification.
request_type Required: Yes
Type: string
This parameter decides the type of verification you want to perform.
Note: Use "enroll" as the value for request_type if you want end-user to sign-up, or "authenticate" if you want end-user to sign-in.
document Required: No
Type: boolean
This option decides if End-User’s ID document is validated or not. Give value 1 if you want to validate the ID document, or 0 if you want to skip it.
phone Required: No
Type: boolean
This option decides if End-User’s phone number is validated or not. Give value 1 if you want to validate the phone number, or 0 if you want to skip it.
question Required: No
Type: boolean
This option decides if the end-users asked for security questions or not. Give value 1 if you want to validate security questions, or 0 if you want to skip it.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents email address of the end-user.
Note: During SignUp email is optional but will necessary in the later registration process.
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays a screen to collect consent from end-user before the verification process starts. If the value is set 1, the screen will be displayed to end-user. If the value is set 0, the consent screen will not be displayed. Under the GDPR, we are bound to get user’s consent therefore the default value is 1 but you can set it to 0 if you’ve already acquired the user’s consent for this biometric verification.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve another alternative mechanism in place.
Register Request

For the register request, pass the value “enroll” in the request_type parameter.

Register Request Example

{
    "webhook_url"   : "https://example.com/",
    "reference"     : "rAnd0mStr1ng",
    "request_type"  : "enroll",
    "language"      : "EN",
    "document"      : 1,
    "phone"         : 1,
    "question"      : 1,
    "email"         : ""
}
<?php

$clientID = 'YOUR CLIENT ID';
$clientSecret = 'YOUR CLIENT SECRET';
$basic_auth = base64_encode ( $clientID . ":" . $clientSecret );

$verification_request = [
"webhook_url" => "http://www.example.com",
"request_type" => "enroll",
"language" => "EN",
"reference" => "134abc123",
"document" => 1,
"phone" => 1,
"question" => 1,
"email" => ""
];
$post_data = json_encode($verification_request);

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.shuftipro.com/biometric/auth",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $post_data,
  CURLOPT_HTTPHEADER => array(
    "Authorization: Basic " . $basic_auth,
    "Content-Type: application/json",
  )
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

?>


var payload = {
  "async": true,
  "crossDomain": true,
  "url": "https://api.shuftipro.com/biometric/auth",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Basic WU9VUiBDTElFTlQgSUQ6WU9VUiBDTElFTlQgU0VDUkVU",
    "cache-control": "no-cache",
  },
  "processData": false,
  "data": {
          "webhook_url": "http://www.example.com",
          "request_type": "enroll",
          "language"    : "EN",
          "email"      : "",
          "reference": "123abc123",
          "document": 1,
          "phone": 1,
          "question": 1
      }
}

$.ajax(payload).done(function (response) {
  console.log(response);
});


require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/biometric/auth")
# Your Shufti Pro account Client ID
CLIENT_ID  = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY = "YOUR-SECRET-KEY"
post_data = { 
     webhook_url: "http://www.example.com",
     reference: "123abc123",
     language: "EN",
     request_type: "enroll",
     email: "",
     document: 1,
     phone: 1,
     question: 1
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body             = post_data.to_json

response = http.request(request)
response_data    = JSON.parse(response.read_body)

puts response_data


import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/'

# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'

# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'

auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()

url = "https://api.shuftipro.com/biometric/auth"
verification_request = {
'webhook_url'  : 'http://www.example.com',
'language'     :  'EN',
'request_type' :   'enroll',
'email'        :   '',
'reference'    :   '123abc123',
'document'     :   1,
'phone'        :   1,
'question'     :   1
}
headers = {
    'Content-Type': "application/json",
    'Authorization': "Basic %s" % b64Val
    }

response = requests.request("POST", url, headers=headers, data=json.dumps(verification_request))

print(json.loads(response.text))

Login Request

For the login request, pass the value “authenticate” in the request_type parameter.

Login Request Example

{
   "webhook_url"   : "https://example.com/",
   "reference"     : "rAnd0mStr1ng",
   "request_type"  : "authenticate",
   "language"      : "EN",
   "document"      : 1,
   "phone"         : 1,
   "question"      : 1,
   "email"         : ""
}

<?php

$clientID = 'YOUR CLIENT ID';
$clientSecret = 'YOUR CLIENT SECRET';
$basic_auth = base64_encode ( $clientID . ":" . $clientSecret );

$verification_request = [
"webhook_url" => "http://www.example.com",
"request_type" => "authenticate",
"language" => "EN",
"reference" => "134abc123",
"document" => 1,
"phone" => 1,
"question" => 1,
"email" => ""
];
$post_data = json_encode($verification_request);

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.shuftipro.com/biometric/auth",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $post_data,
  CURLOPT_HTTPHEADER => array(
    "Authorization: Basic " . $basic_auth,
    "Content-Type: application/json",
  )
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

?>


import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/'

# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'

# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'

auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()

url = "https://api.shuftipro.com/biometric/auth"

verification_request = {
'webhook_url'  : 'http://www.example.com',
'language'     :  'EN',
'request_type' :   'authenticate',
'email'        :   '',
'reference'    :   '123abc123',
'document'     :   1,
'phone'        :   1,
'question'     :   1
}

headers = {
    'Content-Type': "application/json",
    'Authorization': "Basic %s" % b64Val
    }

response = requests.request("POST", url, headers=headers, data=json.dumps(verification_request))

print(json.loads(response.text))


var payload = {
  "async": true,
  "crossDomain": true,
  "url": "https://api.shuftipro.com/biometric/auth",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Basic WU9VUiBDTElFTlQgSUQ6WU9VUiBDTElFTlQgU0VDUkVU",
    "cache-control": "no-cache",
  },
  "processData": false,
  "data": {
          "webhook_url": "http://www.example.com",
          "request_type": "authenticate",
          "language"    : "EN",
          "email"      : "",
          "reference": "123abc123",
          "document": 1,
          "phone": 1,
          "question": 1
      }
}

$.ajax(payload).done(function (response) {
  console.log(response);
});


require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/biometric/auth")
# Your Shufti Pro account Client ID
CLIENT_ID  = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY = "YOUR-SECRET-KEY"
post_data = { 
     webhook_url: "http://www.example.com",
     reference: "123abc123",
     language: "EN",
     request_type: "authenticate",
     email: "",
     document: 1,
     phone: 1,
     question: 1
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body             = post_data.to_json

response = http.request(request)
response_data    = JSON.parse(response.read_body)

puts response_data

Loading the SDK

The Shufti Pro SDK for JavaScript doesn’t have any standalone files that need to be downloaded or installed. You simply need to include a short piece of regular JavaScript in your HTML that will asynchronously load SDK on pages. The async loading does not block any other elements of your page.

The following snippet of code will give the basic version of the SDK where the options are set to the most common defaults.

You can use one of the two methods below to load the SDK asynchronously. Put the following code in the HTML of pages where you want to load the SDK.

  1. Script Tag
    Insert this directly after the opening body tag on every page where you want to load it.
    <script async defer src="https://app.shuftipro.com/biometric/sdk/shuftipro.min.js"></script>

  2. Function Call
    <script> ( function ( d, s, id ) { if ( d.getElementById ( id ) ) return; let js, fjs = d.getElementsByTagName ( s )[ 0 ]; js = d.createElement ( s ); js.id = id; js.src = "https://app.shuftipro.com/biometric/sdk/shuftipro.min.js"; fjs.parentNode.insertBefore ( js, fjs ); } ( document, 'script', 'shuftipro-jssdk' ) ); </script>

Custom Iframe

SDK will append & launch an iframe. If you want to customize the iframe for your website or application then include it according to your requirements. If no iframe is provided in the HTML then Shufti Pro will render default from the SDK.
Note: The ID of the custom iFrame must be "shuftipro-iframe".

<iframe src="" id="shuftipro-iframe" allow="camera" frameborder="0"></iframe>

Initializing the SDK

After getting the access_token from the server, put it in SP's init method to initialize the SDK.

SP.init ( callback, access_token );

With above mentioned command, SDK will initialize and will be ready to get the SignUp and Login requests.

Request Parameters

Parameters Description
callback method Required: Yes
Type: Function
The Client will pass the callback function. Shufti Pro will use this to return response data of verification.
access_token Required: Yes
Type: string
Please put the access token you received from server to server call.

Full Example

Full Code Example


//POST /biometric/auth HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic 961551694eef2a4dc24e6367184d8e9f1191e6d

{
    "webhook_url"   : "https://example.com/",
    "reference"     : "rAnd0mStr1ng",
    "request_type"  : "enroll",
    "language"      : "EN",
    "document"      : 1,
    "phone"         : 1,
    "question"      : 1,
    "email"         : "abc@xyz.com"
}


<?php

$clientID = 'YOUR CLIENT ID';
$clientSecret = 'YOUR CLIENT SECRET';
$basic_auth = base64_encode ( $clientID . ":" . $clientSecret );

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.shuftipro.com/biometric/auth",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\n    \"webhook_url\": \"http://www.example.com\",\n    \"request_type\" : \"enroll\",\n    \"language\" : \"EN\",\n    \"reference\": \"123abc123\",\n    \"document\": 1,\n    \"phone\": 1,\n    \"question\": 1,\n        \"email\" : \"\"\n }",
  CURLOPT_HTTPHEADER => array(
    "Authorization: Basic " . $basic_auth,
    "Content-Type: application/json",
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

?>


import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/'

# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'

# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'

auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()

url = "https://api.shuftipro.com/biometric/auth"

payload = "{\n    \"webhook_url\": \"http://www.example.com\",\n    \"request_type\" : \"enroll\",\n    \"language\" : \"EN\",\n    \"email\" : \"\",\n    \"reference\": \"123abc123\",\n    \"document\": 1,\n    \"phone\": 1,\n    \"question\": 1,\n }"
headers = {
    'Content-Type': "application/json",
    'Authorization': "Basic %s" % b64Val
    }

response = requests.request("POST", url, headers=headers)

print(json.loads(response.text))


//We will be using two common practises for send Api calls
//Dispatch request via Jquery Ajax API
var payload = {
  "async": true,
  "crossDomain": true,
  "url": "https://api.shuftipro.com/biometric/auth",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Basic WU9VUiBDTElFTlQgSUQ6WU9VUiBDTElFTlQgU0VDUkVU",
    "cache-control": "no-cache",
  },
  "processData": false,
  "data": {
          "webhook_url": "http://www.example.com",
          "request_type": "enroll",
          "language"     : "EN",
          "email": "",
          "reference": "123abc123",
          "document": 1,
          "phone": 1,
          "question": 1
      }
}

$.ajax(payload).done(function (response) {
  console.log(response);
});


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BiometricSDK Setup Example</title>
</head>
<body>

<input id="email" placeholder="Email..." type="email">
<label>
    <input name="request_type" type="radio" value="enroll">
    Enroll
</label>
<label>
    <input name="request_type" type="radio" value="authenticate" checked>
    Authenticate
</label>
<button onclick="spInit()">Init</button>
<br>
<iframe src="" id="shuftipro-iframe" allow="camera" frameborder="0"></iframe>

<script>
     // Load the SDK asynchronously
     ( function ( d, s, id ) {
         if ( d.getElementById ( id ) ) return;
         let js, fjs = d.getElementsByTagName ( s )[ 0 ];
         js = d.createElement ( s );
         js.id = id;
         js.src = "https://app.shuftipro.com/biometric/sdk/shuftipro.min.js";
         fjs.parentNode.insertBefore ( js, fjs );
     } ( document, 'script', 'shuftipro-jssdk' ) );


    spInit = function () {
        let email = document.getElementById ( 'email' ).value;
        let request_type = document.querySelector ( 'input[name="request_type"]:checked' ).value;

        fetch ( 'https://api.shuftipro.com/biometric/auth', {
            headers : {
                'Authorization' : `Basic ${ btoa ( '22f1d49c01e52ddb7875b4b:E08UVMDwFnCiqtu338JH' ) }`,
                'Accept' : 'application/json',
                'Content-Type' : 'application/json'
            },
            body : JSON.stringify ( {
                "webhook_url" : "https://api.shuftipro.com/biometric/test",
                "reference" : Math.random ().toString ( 36 ).substring ( 4 ),
                "request_type" : request_type,
                "language"     : "EN",
                "document" : 1,
                "phone" : 1,
                "question" : 1,
                "email" : email
            } ),
            mode : 'cors',
            method : "POST"
        } )
        .then ( res => res.json () ).then ( data => {

            if ( data.error !== "" ) {
                alert ( data.error.message );
                return;
            }

            let callback = function (response) { 
                console.log ( response ) 
            };

            SP.init ( callback, data.access_token )

        } );
    }

</script>
</body>
</html>

This code will load and initialize the JavaScript SDK in your HTML page. It is advised and a best practice to not put the Client Credentials in your javascript code. Make a server to server request to get the access_token. The JavaScript Fetch method is used to request the Shufti Pro server, and then make server to server requests to get the SDK access_token. Use the example on the right for guidance.

Example

In order to initialize the SDK, we use these tags:

<input id="email" placeholder = "Email..." type = "email"> <label> <input name="request_type" type="radio" value="enroll"> Enroll </label> <label> <input name="request_type" type="radio" value="authenticate" checked> Authenticate </label> <button onclick="spInit()">Init</button> <iframe src="" id="shuftipro-iframe" allow= "camera" frameborder ="0"></iframe>

And a script tag to load the SDK asynchronously with a call to SP's server for access token and Initialize the SDK with the access token.

Services

Shufti Pro is providing a variety of authentication services for its customers. Our diverse services suite allows us to validate the identity of users through:

  1. Face Service
  2. Documents Service
  3. Phone Serice
  4. Security Questions Service

Face Service

Shufti Pro Biometric SDK authenticates users with Facial Authentication and checks their liveness. This service is used as a default authentication service and can not be disabled.

Request Parameters

Parameters Description
webhook_url Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
A number of server-to-server calls are made to the client to keep them updated about verification status. This allows them to keep the request updated on their end, even if the end-user is lost midway through the process.
language Required: No
Type: string
Length: 2 characters
If the client wants their preferred language to appear on the authentication screens they may provide the 2-characters long language code of their preferred language. The list of Supported Languages can be consulted for reference. If this key is missing in the request the system will select the default language as English.
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
Each request has a unique Reference ID that is sent back to the client against each response. The client can use Reference ID to check the status of each verification.
request_type Required: Yes
Type: string
This parameter decides the type of verification you want to perform.
Note: If you want end-users to sign-up, use "enroll" as the value for request_type, or use "authenticate" if you want them to sign-in.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents the email address of end-user.
Note: Providing email is optional during sign-up but necessary later in the registration process.
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays a screen to collect consent from end-user before the verification process starts. If the value is set 1, the screen will be displayed to end-user. If the value is set 0, the consent screen will not be displayed. Under the GDPR, we are bound to get user’s consent therefore the default value is 1 but you can set it to 0 if you’ve already acquired the user’s consent for this biometric verification.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve another alternative mechanism in place.
Document Service

Shufti Pro Biometric SDK provides document verification through ID document. It gives an option to end-users to verify their data from ID document.

Request Parameters

Parameters Description
webhook_url Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
A number of server-to-server calls are made to the client to keep them updated about verification status. This allows them to keep the request updated on their end, even if the end-user is lost midway through the process.
language Required: No
Type: string
Length: 2 characters
If the client wants their preferred language to appear on the authentication screens they may provide the 2-characters long language code of their preferred language. The list of Supported Languages can be consulted for reference. If this key is missing in the request the system will select the default language as English.
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
Each request has a unique Reference ID that is sent back to the client against each response. The client can use Reference ID to check the status of each verification.
request_type Required: Yes
Type: string
This parameter decides the type of verification you want to perform.
Note: If you want end-users to sign-up, use "enroll" as the value for request_type, or use "authenticate" if you want them to sign-in.
document Required: No
Type: boolean
This option decides if End-User’s ID document is validated or not. Give value 1 if you want to validate the ID document, or 0 if you want to skip it.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents the email address of end-user.
Note: Providing email is optional during sign-up but necessary later in the registration process.
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays a screen to collect consent from end-user before the verification process starts. If the value is set 1, the screen will be displayed to end-user. If the value is set 0, the consent screen will not be displayed. Under the GDPR, we are bound to get user’s consent therefore the default value is 1 but you can set it to 0 if you’ve already acquired the user’s consent for this biometric verification.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve another alternative mechanism in place.
Phone Service

Shufti Pro Biometric SDK provides phone number verification. Shufti Pro Biometric SDK verifies the phone number of end-users by sending a random code to their number from Shufti Pro. Once the sent code is entered into the provided field by end-user, phone number will stand verified. Shufti Pro will be responsible only to send the message along with verification code to the end-user and verify the code entered by the end-user.
Verification is declined if a user enters the wrong code consecutively for five times.
If the user is unable to receive code then, user is provide with Code not received option if user clicks the “Code not received” option the verification will be declined automatically (because either the phone number was wrong or unreachable).

Request Parameters

Parameters Description
webhook_url Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
A number of server-to-server calls are made to the client to keep them updated about verification status. This allows them to keep the request updated on their end, even if the end-user is lost midway through the process.
language Required: No
Type: string
Length: 2 characters
If the client wants their preferred language to appear on the authentication screens they may provide the 2-characters long language code of their preferred language. The list of Supported Languages can be consulted for reference. If this key is missing in the request the system will select the default language as English.
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
Each request has a unique Reference ID that is sent back to the client against each response. The client can use Reference ID to check the status of each verification.
request_type Required: Yes
Type: string
This parameter decides the type of verification you want to perform.
Note: If you want end-users to sign-up, use "enroll" as the value for request_type, or use "authenticate" if you want them to sign-in.
phone Required: No
Type: boolean
This option decides if End-User’s phone number is validated or not. Give value 1 if you want to validate the phone number, or 0 if you want to skip it.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents the email address of end-user.
Note: Providing email is optional during sign-up but necessary later in the registration process.
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays a screen to collect consent from end-user before the verification process starts. If the value is set 1, the screen will be displayed to end-user. If the value is set 0, the consent screen will not be displayed. Under the GDPR, we are bound to get user’s consent therefore the default value is 1 but you can set it to 0 if you’ve already acquired the user’s consent for this biometric verification.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve another alternative mechanism in place.
Question Service

Shufti Pro Biometric SDK provides security questions verification for authentication. It takes the answers of the security question at the time of enrollment from the end-user. Once the end-user is successfully enrolled, it asks end-users to answer again on authentication to verify their answers.

Request Parameters

Parameters Description
webhook_url Required: Yes
Type: string
This allows the Client to receive response of request, either success or fail.
language Required: No
Type: string
Length: 2 characters
If the Shufti Pro client wants their preferred language to appear on the authentication screens they may provide the 2-character long language code of their preferred language. The list of Supported Languages can be consulted for the language codes. If this key is missing in the request the system will select the default language as English.
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 64 characters
Each request has a unique Reference ID which is sent back to Client against each response. The Client can use the Reference ID to check status of each verification.
request_type Required: Yes
Type: string
This parameter decides the type of verification you want to perform.
Note: Use "enroll" as the value for request_type if you want end-user to sign-up, or "authenticate" if you want end-user to sign-in.
question Required: No
Type: boolean
This option decides if the end-users asked for security questions or not. Give value 1 if you want to validate security questions, or 0 if you want to skip it.
email Required: No
Type: string
Minimum: 6 characters
Maximum: 128 characters
This field represents email address of the end-user.
Note: During SignUp email is optional but will necessary in the later registration process.
show_consent Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays a screen to collect consent from end-user before the verification process starts. If the value is set 1, the screen will be displayed to end-user. If the value is set 0, the consent screen will not be displayed. Under the GDPR, we are bound to get user’s consent therefore the default value is 1 but you can set it to 0 if you’ve already acquired the user’s consent for this biometric verification.
show_privacy_policy Required: No
Type: string
Accepted Values: 0, 1
Default Value: 1
This parameter displays data privacy policy to end-user after the verification process is completed. If the value is set 1, the data privacy policy will be displayed to end-user. If the value is set 0, the data privacy policy will not be displayed. Under the GDPR, we acknowledge the end-users right to request for data deletion therefore the default value is 1 but you can set it to 0 if you’ve another alternative mechanism in place.

To read full API Documentation about Biometric Service and see the full example, click here.

Phone (2FA)

Phone service sample object

{
  "phone" : {
      "phone_number"    : "+44127873938323",
      "random_code"     : "55667",
      "text"            : "Your verification code is 55667"
  }
}

Verify the phone number of end-users by sending a random code to their number from Shufti Pro. Once the sent code is entered into the provided field by the end-user, the phone number will stand verified. It is primarily an on-site verification and you have to provide the phone number of the end-user to us, in addition to the verification code and the message that is to be forwarded to the end-user. Shufti Pro will be responsible only to send the message along with the verification code to the end-user and verify the code entered by the end-user.
Verification is declined if a user enters the wrong code consecutively five times.
If the user is unable to receive the code then, the user is provided with a “Code not received” option if a user clicks the “Code not received” option the verification will be declined automatically (because either the phone number was wrong or unreachable).

Parameters Description
phone_number Required: No
Type: string
Minimum: 6 characters
Maximum: 64 characters
Allowed Characters: numbers and plus sign at the beginning. Provide a valid customer’s phone number with country code. Shufti Pro will directly ask the end-user for phone number if this field is missing or empty.
random_code Required: No
Type: string
Minimum: 2 characters
Maximum: 10 characters
Provide a random code. If this field is missing or empty. Shufti Pro will generate a random code.
text Required: No
Type: string
Minimum: 2 characters
Maximum: 100 characters
Provide a short description and random code in this field. This message will be sent to customers. This field should contain random_code. If random_code field is empty then Shufti Pro will generate a random code and append the code with this message at the end.

AML / Background Checks

For Individuals

Background Checks service sample

{
  "background_checks" : {
    "name" : {
             "first_name"  : "John",
             "middle_name" : "Carter",
             "last_name"   : "Doe"
    },
    "dob"  : "1995-10-10"
  }
}
{
  "background_checks" : {
    "name" : {
             "full_name"  : "John Carter Doe"         
    },
    "dob"  : "1995-10-10"
  }
}
{
  "background_checks" : {
    "name" : {
             "first_name"  : "John",
             "middle_name" : "Carter",
             "last_name"   : "Doe"
    }
  }
}

It is a verification process that will require you to send us the full name of the end-user in addition to the date of birth. Shufti Pro will perform AML based background checks based on this information. Please note that the name and dob keys will be extracted from the document service if these keys are empty.

Parameters Description
dob Required: No
Type: string
Format: yyyy-mm-dd
Provide a valid date.
Example: 1990-12-31
Note: It is recommended to send dob for more accurate results.
name Required: No
Type: object
In name object used in background checks service, first_name required and other fields are optional. Parameters for name are listed here:
Example 1: { "first_name" : "John", "last_name" : "Doe" }
Example 2: { "first_name" : "John", "middle_name" : "Carter", "last_name" : "Doe"}
Example 3: { "full_name" : "John Carter Doe"}
Note: If full name is provided with first and last name priority will be given to full name.
ongoing Required: No
Accepted values: 0, 1
Default: 0
This Parameter is used for Ongoing AML Screening, and is allowed only on Production Accounts. If Shufti Pro detects a change in AML statuses, then we will send you a webhook with event verification.status.changed. The new AML status can be checked using get status endpoint, or from the back-office. Use fuzzy_match = 1 in the name object for better results for Ongoing AML Screening.

For Businesses

AML for Businesses service sample object

{
  "aml_for_businesses" : {
        "business_name"     : "Shufti Pro Ltd",
        "business_incorporation_date"     : "2016-01-01",
        "ongoing" : "1"
    }
}

Anti-money laundering checks for businesses by Shufti Pro help to identify companies involved in money laundering (ML) or terror financing (TF) in real-time. Shufti Pro verifies if the business has been blacklisted. Eliminate the risk of penalties, financial loss, and fraud in real-time through in-depth AML screening of your prospect.

Parameters Description
business_name Required: Yes
Type: string
Max: 255 Characters
This parameter receives the business name to run it against the AML list.
Example: Shufti Pro Ltd
business_incorporation_date Required: No
Type: string
Format: yyyy-mm-dd
This parameter receives the incorporation date of the business to run it against the AML list.
Example: 2016-01-01
ongoing Required: No
Accepted values: 0, 1
Default: 0
This Parameter is used for Ongoing AML Screening, and is allowed only on Production Accounts. If Shufti Pro detects a change in AML statuses, then we will send you a webhook with event verification.status.changed. The new AML status can be checked using get status endpoint, or from the back-office.

Know Your Business

Know Your Business service sample object

{
  "kyb" : {
        "company_registration_number"     : "12345678",
        "company_jurisdiction_code"     : "ae_az"
    }
}
<?php
$url = 'https://api.shuftipro.com/';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
];

//Use this key if you want to perform kyb service
$verification_request['kyb'] =[
    'company_registration_number' => '123456',
    'company_jurisdiction_code'   => 'ae_az'
];

$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization: Bearer ' . $access_token); 
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];

if(in_array($event_name, ['verification.accepted', 'verification.declined', 'request.received']) ){
    if($sp_signature == $calculate_signature){
        echo $event_name." :" . $response_data;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>
 let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    country           : "GB",
    language          : "EN"
}
//Use this key if you want to perform document verification with OCR
payload['kyb'] = {
  company_registration_number  : '12345',
  company_jurisdiction_code    : 'ae_az'
}
//BASIC AUTH TOKEN
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR-CLIENT-ID:YOUR-SECRET-KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
    if (data.event && data.event === 'verification.accepted') {
          console.log(data);
        }
});

import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   'https://yourdomain.com/profile/notifyCallback'
}
# Use this key if you want to perform document verification with OCR
verification_request['kyb'] = {
    'company_registration_number'  :   '123456',
    'company_jurisdiction_code'    :   'ae_az'
}

# Calling Shufti Pro request API using python  requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')
# Convert json string to json object
json_response = json.loads(response.content)
# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'verification.accepted':
    if sp_signature == calculated_signature:
        print ('Verification Response: {}'.format(response.content))
    else:
        print ('Invalid signature: {}'.format(response.content))
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN"
}
# Use this key if you want to perform document verification with OCR
verification_request["kyb"] = {
  company_registration_number: '12345',
  company_jurisdiction_code: 'ae_az'
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json
response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY
if sp_signature == calculated_signature
  puts response_data
else
  puts "Invalid signature"
end

Know Your Business service sample object

{
  "kyb" : {
        "company_name"     : "SHUFTI PRO LIMITED"
    }
}
<?php
$url = 'https://api.shuftipro.com/';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
];

//Use this key if you want to perform kyb service
$verification_request['kyb'] =[
    'company_name' => 'SHUFTI PRO LIMITED'
];

$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization: Bearer ' . $access_token); 
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];

if(in_array($event_name, ['verification.accepted', 'verification.declined']) ){
    if($sp_signature == $calculate_signature){
        echo $event_name." :" . $response_data;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>


 let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    country           : "GB",
    language          : "EN"
}
//Use this key if you want to perform document verification with OCR
payload['kyb'] = {
  'company_name'  :   'SHUFTI PRO LIMITED'
}
//BASIC AUTH TOKEN
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR-CLIENT-ID:YOUR-SECRET-KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
    if (data.event && data.event === 'verification.accepted') {
          console.log(data);
        }
});

import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   'https://yourdomain.com/profile/notifyCallback'
}
# Use this key if you want to perform document verification with OCR
verification_request['kyb'] = {
    'company_name'  :   'SHUFTI PRO LIMITED'
}

# Calling Shufti Pro request API using python  requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')
# Convert json string to json object
json_response = json.loads(response.content)
# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'verification.accepted':
    if sp_signature == calculated_signature:
        print ('Verification Response: {}'.format(response.content))
    else:
        print ('Invalid signature: {}'.format(response.content))
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN"
}
# Use this key if you want to perform document verification with OCR
verification_request["kyb"] = {
  company_name: 'SHUFTI PRO LIMITED'
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json
response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY
if sp_signature == calculated_signature
  puts response_data
else
  puts "Invalid signature"
end

Shufti Pro verifies millions of businesses in real-time through its KYB services. The KYB verification includes an in-depth screening of Ultimate Beneficial Owners (UBOs) and company registration documents. Develop trustworthy business relationships through in-depth screening of your prospects.

Parameters Description
company_registration_number Required: Yes
Type: string
This parameter receives the company registration number to collect and verify the company information reports.
Example: 12345678
company_jurisdiction_code Required: Yes
Type: string
This parameter receives the company jurisdiction code to collect and verify the company information.
Supported types are listed here
Example: ae_az
company_name Required: No
Type: string
This parameter receives the company name to collect all the companies information whose name matches the given company name.
Example: 'SHUFTI PRO LIMITED'

Response Parameters

Know Your Business response sample object

{
    "reference": "sp-bc-demo-U3cl95qO",
    "event": "verification.accepted",
    "email": null,
    "country": null,
    "verification_data": {
        "kyb":
        {
            "company_number": "11039567",
            "company_type": "Private Limited Company",
            "company_source": {
                "publisher": "UK Companies House",
                "url": "http://xmlgw.companieshouse.gov.uk/",
                "terms": "UK Crown Copyright",
                "retrieved_at": "2019-10-31T08:50:01+00:00"
            },
            "native_company_number": null,
            "company_industry_codes": [
                {
                    "code": "62.01/2",
                    "description": "Business and domestic software development",
                    "code_scheme_id": "uk_sic_2007",
                    "code_scheme_name": "UK SIC Classification 2007"
                },
                {
                    "code": "63.11",
                    "description": "Data processing, hosting and related activities",
                    "code_scheme_id": "uk_sic_2007",
                    "code_scheme_name": "UK SIC Classification 2007"
                },
                {
                    "code": "62.01",
                    "description": "Computer programming activities",
                    "code_scheme_id": "eu_nace_2",
                    "code_scheme_name": "European Community NACE Rev 2"
                },
                {
                    "code": "6201",
                    "description": "Computer programming activities",
                    "code_scheme_id": "isic_4",
                    "code_scheme_name": "UN ISIC Rev 4"
                },
                {
                    "code": "63.11",
                    "description": "Data processing, hosting and related activities",
                    "code_scheme_id": "eu_nace_2",
                    "code_scheme_name": "European Community NACE Rev 2"
                },
                {
                    "code": "6311",
                    "description": "Data processing, hosting and related activities",
                    "code_scheme_id": "isic_4",
                    "code_scheme_name": "UN ISIC Rev 4"
                }
            ],
            "company_trademark_registrations": [],
            "company_corporate_groupings": [],
            "company_data": [],
            "home_company": null,
            "company_ultimate_beneficial_owners": [
                {
                    "name": "Mr. Carl Victor Gregor Fredung Neschko"
                }
            ],
            "company_filings": [
                {
                    "title": "Confirmation Statement",
                    "date": "2019-10-30",
                    "reference_url": "https://opencorporates.com/statements/705738001"
                },
                {
                    "title": "Annual Accounts",
                    "date": "2019-07-19",
                    "reference_url": "https://opencorporates.com/statements/656789159"
                },
                {
                    "title": "Change of registered office address",
                    "date": "2019-06-04",
                    "reference_url": "https://opencorporates.com/statements/635021777"
                },
                {
                    "title": "Change of registered office address",
                    "date": "2019-04-02",
                    "reference_url": "https://opencorporates.com/statements/610263028"
                },
                {
                    "title": "Change of secretary's details",
                    "date": "2018-11-26",
                    "reference_url": "https://opencorporates.com/statements/593461364"
                },
                {
                    "title": "Give notice of individual person with significant control",
                    "date": "2018-11-13",
                    "reference_url": "https://opencorporates.com/statements/579687687"
                },
                {
                    "title": "Give notice of update to PSC statements",
                    "date": "2018-11-13",
                    "reference_url": "https://opencorporates.com/statements/579687688"
                },
                {
                    "title": "Confirmation Statement",
                    "date": "2018-11-12",
                    "reference_url": "https://opencorporates.com/statements/579687689"
                },
                {
                    "title": "Termination of appointment of director ",
                    "date": "2018-11-12",
                    "reference_url": "https://opencorporates.com/statements/579687690"
                },
                {
                    "title": "Appointment of director",
                    "date": "2018-11-12",
                    "reference_url": "https://opencorporates.com/statements/579687691"
                },
                {
                    "title": "Return of allotment of shares",
                    "date": "2018-11-03",
                    "reference_url": "https://opencorporates.com/statements/579336389"
                },
                {
                    "title": "Appointment of secretary",
                    "date": "2018-10-26",
                    "reference_url": "https://opencorporates.com/statements/579336390"
                },
                {
                    "title": "New incorporation documents",
                    "date": "2017-10-31",
                    "reference_url": "https://opencorporates.com/statements/512335712"
                }
            ],
            "company_officers": [
                {
                    "name": "RICHARD MARLEY FISHER",
                    "position": "director",
                    "start_date": "2017-10-31",
                    "end_date": "2018-11-02",
                    "occupation": "COMPANY DIRECTOR",
                    "inactive": true,
                    "current_status": null,
                    "address": null
                },
                {
                    "name": "MUAZ AHMAD JABAL",
                    "position": "secretary",
                    "start_date": "2018-10-25",
                    "end_date": null,
                    "occupation": null,
                    "inactive": false,
                    "current_status": null,
                    "address": null
                },
                {
                    "name": "CARL VICTOR GREGOR FREDUNG NESCHKO",
                    "position": "director",
                    "start_date": "2018-10-30",
                    "end_date": null,
                    "occupation": "BUSINESSMAN",
                    "inactive": false,
                    "current_status": null,
                    "address": null
                }
            ],
            "company_name": "SHUFTI PRO LIMITED",
            "company_jurisdiction_code": "gb",
            "company_incorporation_date": "2017-10-31",
            "company_dissolution_date": null,
            "company_registry_url": "https://beta.companieshouse.gov.uk/company/11039567",
            "company_branch": null,
            "company_branch_status": null,
            "company_registered_address_in_full": "35 Little Russell Street, Holborn, London, WC1A 2HH",
            "company_inactive": false,
            "company_current_status": "Active",
            "company_agent_name": null,
            "company_agent_address": null,
            "company_alternative_names": [],
            "company_previous_names": [],
            "company_number_of_employees": null,
            "company_alternate_registration_entities": [],
            "company_previous_registration_entities": [],
            "company_subsequent_registration_entities": [],
            "company_identifiers": [],
            "company_registered_address": {
                "street_address": "35 Little Russell Street, Holborn",
                "locality": "London",
                "region": null,
                "postal_code": "WC1A 2HH",
                "country": "England"
            },
            "company_financial_summary": null,
            "company_controlling_entity": null
        }
    },
    "verification_result": {
        "kyb_service": null
    },
    "info": {
        "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_4"
        },
        "geolocation": {
            "host": "172.18.0.1",
            "ip": "172.18.0.1",
            "rdns": "172.18.0.1",
            "asn": "",
            "isp": "",
            "country_name": "",
            "country_code": "",
            "region_name": "",
            "region_code": "",
            "city": "",
            "postal_code": "",
            "continent_name": "",
            "continent_code": "",
            "latitude": "",
            "longitude": "",
            "metro_code": "",
            "timezone": ""
        }
    }
}

Kyb search company name response sample object

{
    "reference": "sp-bc-demo-U3cl95qO",
    "event": "verification.accepted",
    "email": null,
    "country": null,
    "verification_data": {
            "kyb": [
            {
                "company_number": "11039567",
                "company_type": "Private Limited Company",
                "company_source": {
                    "publisher": "UK Companies House",
                    "url": "http://xmlgw.companieshouse.gov.uk/",
                    "terms": "UK Crown Copyright",
                    "retrieved_at": "2019-10-31T08:50:01+00:00"
                },
                "native_company_number": null,
                "company_industry_codes": [
                    {
                        "code": "62.01/2",
                        "description": "Business and domestic software development",
                        "code_scheme_id": "uk_sic_2007",
                        "code_scheme_name": "UK SIC Classification 2007"
                    },
                    {
                        "code": "63.11",
                        "description": "Data processing, hosting and related activities",
                        "code_scheme_id": "uk_sic_2007",
                        "code_scheme_name": "UK SIC Classification 2007"
                    },
                    {
                        "code": "62.01",
                        "description": "Computer programming activities",
                        "code_scheme_id": "eu_nace_2",
                        "code_scheme_name": "European Community NACE Rev 2"
                    },
                    {
                        "code": "6201",
                        "description": "Computer programming activities",
                        "code_scheme_id": "isic_4",
                        "code_scheme_name": "UN ISIC Rev 4"
                    },
                    {
                        "code": "63.11",
                        "description": "Data processing, hosting and related activities",
                        "code_scheme_id": "eu_nace_2",
                        "code_scheme_name": "European Community NACE Rev 2"
                    },
                    {
                        "code": "6311",
                        "description": "Data processing, hosting and related activities",
                        "code_scheme_id": "isic_4",
                        "code_scheme_name": "UN ISIC Rev 4"
                    }
                ],
                "company_trademark_registrations": [],
                "company_corporate_groupings": [],
                "company_data": [],
                "home_company": null,
                "company_ultimate_beneficial_owners": [
                    {
                        "name": "Mr. Carl Victor Gregor Fredung Neschko"
                    }
                ],
                "company_filings": [
                    {
                        "title": "Confirmation Statement",
                        "date": "2019-10-30",
                        "reference_url": "https://opencorporates.com/statements/705738001"
                    },
                    {
                        "title": "Annual Accounts",
                        "date": "2019-07-19",
                        "reference_url": "https://opencorporates.com/statements/656789159"
                    },
                    {
                        "title": "Change of registered office address",
                        "date": "2019-06-04",
                        "reference_url": "https://opencorporates.com/statements/635021777"
                    },
                    {
                        "title": "Change of registered office address",
                        "date": "2019-04-02",
                        "reference_url": "https://opencorporates.com/statements/610263028"
                    },
                    {
                        "title": "Change of secretary's details",
                        "date": "2018-11-26",
                        "reference_url": "https://opencorporates.com/statements/593461364"
                    },
                    {
                        "title": "Give notice of individual person with significant control",
                        "date": "2018-11-13",
                        "reference_url": "https://opencorporates.com/statements/579687687"
                    },
                    {
                        "title": "Give notice of update to PSC statements",
                        "date": "2018-11-13",
                        "reference_url": "https://opencorporates.com/statements/579687688"
                    },
                    {
                        "title": "Confirmation Statement",
                        "date": "2018-11-12",
                        "reference_url": "https://opencorporates.com/statements/579687689"
                    },
                    {
                        "title": "Termination of appointment of director ",
                        "date": "2018-11-12",
                        "reference_url": "https://opencorporates.com/statements/579687690"
                    },
                    {
                        "title": "Appointment of director",
                        "date": "2018-11-12",
                        "reference_url": "https://opencorporates.com/statements/579687691"
                    },
                    {
                        "title": "Return of allotment of shares",
                        "date": "2018-11-03",
                        "reference_url": "https://opencorporates.com/statements/579336389"
                    },
                    {
                        "title": "Appointment of secretary",
                        "date": "2018-10-26",
                        "reference_url": "https://opencorporates.com/statements/579336390"
                    },
                    {
                        "title": "New incorporation documents",
                        "date": "2017-10-31",
                        "reference_url": "https://opencorporates.com/statements/512335712"
                    }
                ],
                "company_officers": [
                    {
                        "name": "RICHARD MARLEY FISHER",
                        "position": "director",
                        "start_date": "2017-10-31",
                        "end_date": "2018-11-02",
                        "occupation": "COMPANY DIRECTOR",
                        "inactive": true,
                        "current_status": null,
                        "address": null
                    },
                    {
                        "name": "MUAZ AHMAD JABAL",
                        "position": "secretary",
                        "start_date": "2018-10-25",
                        "end_date": null,
                        "occupation": null,
                        "inactive": false,
                        "current_status": null,
                        "address": null
                    },
                    {
                        "name": "CARL VICTOR GREGOR FREDUNG NESCHKO",
                        "position": "director",
                        "start_date": "2018-10-30",
                        "end_date": null,
                        "occupation": "BUSINESSMAN",
                        "inactive": false,
                        "current_status": null,
                        "address": null
                    }
                ],
                "company_name": "SHUFTI PRO LIMITED",
                "company_jurisdiction_code": "gb",
                "company_incorporation_date": "2017-10-31",
                "company_dissolution_date": null,
                "company_registry_url": "https://beta.companieshouse.gov.uk/company/11039567",
                "company_branch": null,
                "company_branch_status": null,
                "company_registered_address_in_full": "35 Little Russell Street, Holborn, London, WC1A 2HH",
                "company_inactive": false,
                "company_current_status": "Active",
                "company_agent_name": null,
                "company_agent_address": null,
                "company_alternative_names": [],
                "company_previous_names": [],
                "company_number_of_employees": null,
                "company_alternate_registration_entities": [],
                "company_previous_registration_entities": [],
                "company_subsequent_registration_entities": [],
                "company_identifiers": [],
                "company_registered_address": {
                    "street_address": "35 Little Russell Street, Holborn",
                    "locality": "London",
                    "region": null,
                    "postal_code": "WC1A 2HH",
                    "country": "England"
                },
                "company_financial_summary": null,
                "company_controlling_entity": null
            },
            {
                "company_number": "11039567",
                "company_type": "Private Limited Company",
                "company_source": {
                    "publisher": "UK Companies House",
                    "url": "http://xmlgw.companieshouse.gov.uk/",
                    "terms": "UK Crown Copyright",
                    "retrieved_at": "2019-10-31T08:50:01+00:00"
                },
                "native_company_number": null,
                "company_industry_codes": [
                    {
                        "code": "62.01/2",
                        "description": "Business and domestic software development",
                        "code_scheme_id": "uk_sic_2007",
                        "code_scheme_name": "UK SIC Classification 2007"
                    },
                    {
                        "code": "63.11",
                        "description": "Data processing, hosting and related activities",
                        "code_scheme_id": "uk_sic_2007",
                        "code_scheme_name": "UK SIC Classification 2007"
                    },
                    {
                        "code": "62.01",
                        "description": "Computer programming activities",
                        "code_scheme_id": "eu_nace_2",
                        "code_scheme_name": "European Community NACE Rev 2"
                    },
                    {
                        "code": "6201",
                        "description": "Computer programming activities",
                        "code_scheme_id": "isic_4",
                        "code_scheme_name": "UN ISIC Rev 4"
                    },
                    {
                        "code": "63.11",
                        "description": "Data processing, hosting and related activities",
                        "code_scheme_id": "eu_nace_2",
                        "code_scheme_name": "European Community NACE Rev 2"
                    },
                    {
                        "code": "6311",
                        "description": "Data processing, hosting and related activities",
                        "code_scheme_id": "isic_4",
                        "code_scheme_name": "UN ISIC Rev 4"
                    }
                ],
                "company_trademark_registrations": [],
                "company_corporate_groupings": [],
                "company_data": [],
                "home_company": null,
                "company_ultimate_beneficial_owners": [
                    {
                        "name": "Mr. Carl Victor Gregor Fredung Neschko"
                    }
                ],
                "company_filings": [
                    {
                        "title": "Confirmation Statement",
                        "date": "2019-10-30",
                        "reference_url": "https://opencorporates.com/statements/705738001"
                    },
                    {
                        "title": "Annual Accounts",
                        "date": "2019-07-19",
                        "reference_url": "https://opencorporates.com/statements/656789159"
                    },
                    {
                        "title": "Change of registered office address",
                        "date": "2019-06-04",
                        "reference_url": "https://opencorporates.com/statements/635021777"
                    },
                    {
                        "title": "Change of registered office address",
                        "date": "2019-04-02",
                        "reference_url": "https://opencorporates.com/statements/610263028"
                    },
                    {
                        "title": "Change of secretary's details",
                        "date": "2018-11-26",
                        "reference_url": "https://opencorporates.com/statements/593461364"
                    },
                    {
                        "title": "Give notice of individual person with significant control",
                        "date": "2018-11-13",
                        "reference_url": "https://opencorporates.com/statements/579687687"
                    },
                    {
                        "title": "Give notice of update to PSC statements",
                        "date": "2018-11-13",
                        "reference_url": "https://opencorporates.com/statements/579687688"
                    },
                    {
                        "title": "Confirmation Statement",
                        "date": "2018-11-12",
                        "reference_url": "https://opencorporates.com/statements/579687689"
                    },
                    {
                        "title": "Termination of appointment of director ",
                        "date": "2018-11-12",
                        "reference_url": "https://opencorporates.com/statements/579687690"
                    },
                    {
                        "title": "Appointment of director",
                        "date": "2018-11-12",
                        "reference_url": "https://opencorporates.com/statements/579687691"
                    },
                    {
                        "title": "Return of allotment of shares",
                        "date": "2018-11-03",
                        "reference_url": "https://opencorporates.com/statements/579336389"
                    },
                    {
                        "title": "Appointment of secretary",
                        "date": "2018-10-26",
                        "reference_url": "https://opencorporates.com/statements/579336390"
                    },
                    {
                        "title": "New incorporation documents",
                        "date": "2017-10-31",
                        "reference_url": "https://opencorporates.com/statements/512335712"
                    }
                ],
                "company_officers": [
                    {
                        "name": "RICHARD MARLEY FISHER",
                        "position": "director",
                        "start_date": "2017-10-31",
                        "end_date": "2018-11-02",
                        "occupation": "COMPANY DIRECTOR",
                        "inactive": true,
                        "current_status": null,
                        "address": null
                    },
                    {
                        "name": "MUAZ AHMAD JABAL",
                        "position": "secretary",
                        "start_date": "2018-10-25",
                        "end_date": null,
                        "occupation": null,
                        "inactive": false,
                        "current_status": null,
                        "address": null
                    },
                    {
                        "name": "CARL VICTOR GREGOR FREDUNG NESCHKO",
                        "position": "director",
                        "start_date": "2018-10-30",
                        "end_date": null,
                        "occupation": "BUSINESSMAN",
                        "inactive": false,
                        "current_status": null,
                        "address": null
                    }
                ],
                "company_name": "SHUFTI PRO LIMITED",
                "company_jurisdiction_code": "gb",
                "company_incorporation_date": "2017-10-31",
                "company_dissolution_date": null,
                "company_registry_url": "https://beta.companieshouse.gov.uk/company/11039567",
                "company_branch": null,
                "company_branch_status": null,
                "company_registered_address_in_full": "35 Little Russell Street, Holborn, London, WC1A 2HH",
                "company_inactive": false,
                "company_current_status": "Active",
                "company_agent_name": null,
                "company_agent_address": null,
                "company_alternative_names": [],
                "company_previous_names": [],
                "company_number_of_employees": null,
                "company_alternate_registration_entities": [],
                "company_previous_registration_entities": [],
                "company_subsequent_registration_entities": [],
                "company_identifiers": [],
                "company_registered_address": {
                    "street_address": "35 Little Russell Street, Holborn",
                    "locality": "London",
                    "region": null,
                    "postal_code": "WC1A 2HH",
                    "country": "England"
                },
                "company_financial_summary": null,
                "company_controlling_entity": null
            }
        ]
    },
    "verification_result": {
        "kyb_service": null
    },
    "info": {
        "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_4"
        },
        "geolocation": {
            "host": "172.18.0.1",
            "ip": "172.18.0.1",
            "rdns": "172.18.0.1",
            "asn": "",
            "isp": "",
            "country_name": "",
            "country_code": "",
            "region_name": "",
            "region_code": "",
            "city": "",
            "postal_code": "",
            "continent_name": "",
            "continent_code": "",
            "latitude": "",
            "longitude": "",
            "metro_code": "",
            "timezone": ""
        }
    }
}
Parameters Description
company_name Type: string
The legal name of the Company
company_number Type: string
The identifier is given to the company by the company register
company_jurisdiction_code Type: string
The code for the jurisdiction in which the company is incorporated
company_incorporation_date Type: string
The date the company was incorporated on
company_dissolution_date Type: string
The date the company was dissolved (if so)
company_type Type: string
The type of company (e.g. LLC, Private Limited Company, GBMH)
company_registry_url Type: string
The URL of the company page in the company register. Note, not all company registers provide persistent URLs for the companies in the register
company_branch Type: string
A flag to indicate if a company is a 'branch'. If the flag is 'F' it indicates that the entry in the company register relates to an out-of-jurisdiction company (sometimes called a 'foreign corporation' in the US). If it is 'L' it is a local office of a company (few company registers collect this information). If it is a null value, it means either the company is not a branch, or the company register does not make the information available
company_branch_status Type: string
A descriptive text version of the 'branch' flag
company_inactive Type: boolean
Filter by inactive status (boolean). This replaces the exclude_inactive filter from previous versions. If ‘true’ is supplied, it will be restricted to inactive companies. If ‘false’ is supplied, it will exclude inactive companies. If no value is supplied it will not filter by inactive status.
company_current_status Type: string
The current status of the company, as defined by the company register.
company_source Type: object
The source(s) from which we gather company data.
Parameters: publisher, url, terms and retrieved_at.
company_agent_name Type: string
The name of the individual who manages the company affairs on behalf of the company.
company_agent_address Type: string
Specific person’s address
company_alternative_names Type: array
Other operating name(s) of the company if any.
Parameters: company_name, type and language.
company_previous_names Type: array
Old name of that firm/company (if any)
company_number_of_employees Type: string
No of employees working for the company
native_company_number Type: string
Country number (Similar to ID number)
company_alternate_registration_entities Type: array
Other areas of registration (includes partnership types)
company_previous_registration_entities Type: array
Previous registration entity type (e.g. partnership, sole traders etc.)
company_subsequent_registration_entities Type: array
If closed then further or new entity type of partnership
company_registered_address_in_full Type: string
Address where the company is registered
company_industry_codes Type: array
Type of industry it is working in (Tech, Manufacturing, etc.)
Parameters: code, description, code_scheme_id and code_scheme_name.
company_identifiers Type: array
This is similar to company registration number
company_trademark_registrations Type: array
Any patent or trademark registered or filled by company
company_registered_address Type: object
Address where company is registered.
Parameters: street_address, locality, region, postal_code and country.
company_corporate_groupings Type: array
Corporate umbrella(Parent company to child company tree
company_data Type: array
Information related company filled or posted.
Parameters: title, data_type and description.
company_financial_summary Type: string
Statement of Financial position
home_company Type: object
Main parent company or Ultimate parent company.
Parameters: name, jurisdiction_code, company_number and reference_url.
company_controlling_entity Type: object
Owner, Beneficiary ,CEO or anyone with decision making powers.
Parameters: name, jurisdiction_code, company_number and reference_url.
company_ultimate_beneficial_owners Type: array
Owner, Beneficiary or anyone benefiting from revenues of company
company_filings Type: array
Parameters: title, date and reference_url.
company_officers Type: array
Any significant officers such as agent, director, CEO, CTO.
Parameters: name, position, start_date, end_date, occupation, inactive, current_status and address.

OCR For Business

OCR For Business service sample object

{
    "business_ocr" : {
            "model_name" : "invoice_sales",
            "proof":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAALCAYAAABCm8wlAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QoPAxIb88htFgAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAACxSURBVBjTdY6xasJgGEXP/RvoonvAd8hDyD84+BZBEMSxL9GtQ8Fis7i6BkGI4DP4CA4dnQON3g6WNjb2wLd8nAsHWsR3D7JXt18kALFwz2dGmPVhJt0IcenUDVsgu91eCRZ9IOMfAnBvSCz8I3QYL0yV6zfyL+VUxKWfMJuOEFd+dE3pC1Finwj0HfGBeKGmblcFTIN4U2C4m+hZAaTrASSGox6YV7k+ARAp4gIIOH0BmuY1E5TjCIUAAAAASUVORK5CYII="
    }
}
<?php
$url = 'https://api.shuftipro.com/';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$verification_request = [
    'reference'    => 'ref-'.rand(4,444).rand(4,444),
    'country'      => 'GB',
    'language'     => 'EN',
    'email'        => 'example@email.com',
    'callback_url' =>  'https://yourdomain.com/profile/notifyCallback',
];

//Use this key if you want to perform OCR For business service
$verification_request['business_ocr'] =[
    'model_name' => 'invoice_sales',
    'proof'   => base64_encode(file_get_contents('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg'))
];

$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization: Bearer ' . $access_token); 
$post_data = json_encode($verification_request);
//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);
$decoded_response = json_decode($response_data,true);
$event_name = $decoded_response['event'];

if($event_name == 'request.received'){
    if($sp_signature == $calculate_signature){
        echo "Response :" . $response_data;
    }else{
        echo "Invalid signature :" . $response_data;
    }
}else{
    echo "Error :" . $response_data;
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    $html_response = curl_exec($ch);
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $headers = substr($html_response, 0, $header_size);
    $body = substr($html_response, $header_size);
    curl_close($ch);
    return ['headers' => $headers,'body' => $body];     
}
?>
 let payload = {
    reference         : `SP_REQUEST_${Math.random()}`,
    callback_url      : "https://yourdomain.com/profile/sp-notify-callback",
    country           : "GB",
    language          : "EN"
}

//get proof base64
convertImgToBase64URL('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').then(response=>{

//Use this key if you want to perform document verification with OCR
payload['business_ocr'] = {
    model_name    : 'invoice_sales',
    proof         : response
}


//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     console.log(data)
     return data;
});

})

/*METHOD USED TO Get image BASE 64 string*/
function convertImgToBase64URL(url){
  return new Promise(function(resolve, reject) {
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        var canvas = document.createElement('CANVAS'),
        ctx = canvas.getContext('2d'), dataURL;
        canvas.height = img.height;
        canvas.width = img.width;
        ctx.drawImage(img, 0, 0);
        dataURL = canvas.toDataURL('image/jpeg');
        resolve(dataURL);
        canvas = null; 
    };
    img.src = url;
  })
}


import requests, base64, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''
url = 'https://api.shuftipro.com/'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

verification_request = {
    'reference'         :   'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
    'country'           :   'GB', 
    'language'          :   'EN',
    'email'             :   'test@test.com',
    'callback_url'      :   'https://yourdomain.com/profile/notifyCallback'
}
# Use this key if you want to perform OCR For Business service
verification_request['business_ocr'] = {
    'model_name'  :   'invoice_sales',
    'proof'    :   base64.b64encode(urllib2.urlopen('https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg').read()).decode(),
}

# Calling Shufti Pro request API using python  requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
                headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
                data=json.dumps(verification_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
# Get Shufti Pro Signature
sp_signature = response.headers.get('Signature','')
# Convert json string to json object
json_response = json.loads(response.content)
# Get event returned
event_name = json_response['event']
print (json_response)
if event_name == 'request.received':
    if sp_signature == calculated_signature:
        print ('Verification Response: {}'.format(response.content))
    else:
        print ('Invalid signature: {}'.format(response.content))
require 'uri'
require 'net/http'
require 'base64'
require 'json'
require 'open-uri'

url = URI("https://api.shuftipro.com/")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"


SAMPLE_DOCUMENT_IMAGE =  "https://raw.githubusercontent.com/shuftipro/RESTful-API-v1.3/master/assets/real-id-card.jpg"

verification_request = { 
    reference:          "Ref-"+ (0...8).map { (65 + rand(26)).chr }.join,
    callback_url:       "https://yourdomain.com/profile/notifyCallback",
    email:              "johndoe@example.com",
    country:            "GB",
    language:           "EN"
}
# Use this key if you want to perform OCR For Business service
verification_request["business_ocr"] = {
  model_name:    'invoice_sales',
  proof:         Base64.encode64(open(SAMPLE_DOCUMENT_IMAGE).read),
}
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = verification_request.to_json
response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY
if sp_signature == calculated_signature
  puts response_data
else
  puts "Invalid signature"
end

OCR For Business response sample object

{
    "reference": "17374217",
    "event": "request.received",
    "email": "johndoe@example.com",
    "country": "UK"
}

OCR For Business callback response sample object

//Content-Type: application/json
//Signature: NmI4NmIyNzNmZjM0ZmNl

{
    "reference": "17374217",
    "event": "verification.accepted",
    "email": "johndoe@example.com",
    "country"   : "GB",
    "verification_result": {},
    "verification_data": {
        "business_ocr": {
            "last_name": "Doe",
            "first_name": "John",
            "issue_date": "2018-01-31",
            "expiry_date": "2028-01-30",
            "nationality": "BRITSH CITIZEN",
            "gender": "M",
            "place_of_birth": "BRISTOL",
            "document_number": "GB1234567",
        }
    },
    "info": {
        "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_0"
        },
        "geolocation": {
            "host": "212.103.50.243",
            "ip": "212.103.50.243",
            "rdns": "212.103.50.243",
            "asn": "9009",
            "isp": "M247 Ltd",
            "country_name": "Germany",
            "country_code": "DE",
            "region_name": "Hesse",
            "region_code": "HE",
            "city": "Frankfurt am Main",
            "postal_code": "60326",
            "continent_name": "Europe",
            "continent_code": "EU",
            "latitude": "50.1049",
            "longitude": "8.6295",
            "metro_code": "",
            "timezone": "Europe/Berlin"
        }
    },
}

AI-powered OCR technology by Shufti Pro helps businesses save operational costs by extracting relevant information from documents in real-time with an accuracy of up to 90%. The instant image-to-text OCR supports multilingual documents and offers global coverage. Shufti Pro’s intelligent OCR services provide businesses with optimized data extraction.

Ocr for Business includes two parts:
1. Training of the Model
2. Data extraction using Trained models

1. Training of the Model

For training of the model client needs to follow these steps in backoffice under section OCR FOR BUSINESS:
- Upload sample document(s) to train the model.
- Select and name the data fields that the client wishes to extract from that document.
- Provide a name to the model and train it.

Note: Once the model is trained the client can start data extraction right away or test the trained model in the backoffice .

2. Data extraction using Trained models

For data extraction clients need to send the API request to the server with the following parameters:

Parameters Description
model_name Required: Yes
Type: string
A valid model name provided by the client during the model training phase.
Example: (invoice_sales)
proof Required: Yes
Type: string
Image Format: JPG, JPEG, PNG, PDF
Maximum image size: 16 MB

In response to API call client will receive JSON response with event of request.received and Shuftipro will extract required data and send the extracted data to provided callback url (The data is also updated in the client’s backoffice. The client can access that data anytime).

Request

Status Request

Status Request Sample

//POST /status HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"

{ 
    "reference" : "17374217"
}

<?php
$url = 'https://api.shuftipro.com/status';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$status_request = [
  "reference" => "your_request_reference",
];

$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization : Bearer ' . $access_token);
$post_data = json_encode($status_request);

//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token

//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}
//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);

if($sp_signature == $calculate_signature){

  echo "Response : $response_data";
}else{
  echo "Invalid signature :  $response_data";
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
  $html_response = curl_exec($ch);
  $curl_info = curl_getinfo($ch);
  $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $headers = substr($html_response, 0, $header_size);
  $body = substr($html_response, $header_size);
  curl_close($ch);
  return ['headers' => $headers,'body' => $body];     
}
?>
var payload = {
    reference : 'your_request_reference'
}

//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/status', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     return data;
});
import base64, requests, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/status'

# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

status_request = {
  "reference" : "your_request_reference"
}

# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
        headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
        data=json.dumps(status_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()

# Convert json string to json object
json_response = json.loads(response.content)
sp_signature = response.headers.get('Signature','')

if sp_signature == calculated_signature:
    print ('Response : {}'.format(json_response))
else:
  print ('Invalid Signature: {}'.format(json_response)) 
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/status")

# Your Shufti Pro account Client ID
CLIENT_ID  = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

post_data = { 
     reference: "your_request_reference" 
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body             = post_data.to_json

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = JSON.parse(response.read_body)

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY

if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

Once a verification request is completed, you may request at the status endpoint to get the verification status. You’ll have to provide the reference ID for the status request and you will be promptly informed about the status of that verification.

Run in Postman

Parameter Description
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
This is the unique reference ID of request, which we will send you back with each response, so you can verify the request.

Delete Request

Sample Delete Request

//POST /delete HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
//replace "Basic" with "Bearer in case of Access Token"

{ 
    "reference" : "17374217",
    "comment"   : "Customer asked to delete his/her data"
}

<?php
$url = 'https://api.shuftipro.com/delete';

//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';

$delete_request = [
  "reference" => "your_request_reference",
  "comment"   => "Customer asked to delete his/her data"
];

$auth = $client_id . ":" . $secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization : Bearer ' . $access_token);
$post_data = json_encode($delete_request);

//Calling Shufti Pro request API using curl
$response = send_curl($url, $post_data, $headers, $auth); // remove $auth in case of Access Token

//Get Shufti Pro API Response
$response_data    = $response['body'];

//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);

if($sp_signature == $calculate_signature){
  echo "Response : $response_data";
}else{
  echo "Invalid signature :  $response_data";
}

function send_curl($url, $post_data, $headers, $auth){ // remove $auth in case of Access Token
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
  $html_response = curl_exec($ch);
  $curl_info = curl_getinfo($ch);
  $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $headers = substr($html_response, 0, $header_size);
  $body = substr($html_response, $header_size);
  curl_close($ch);
  return ['headers' => $headers, 'body' => $body];     
}
?>
var payload = {
    reference : 'your_request_reference',
    comment   : 'Customer asked to delete his/het data'
}

//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/delete', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  },
  body: JSON.stringify(payload)
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     return data;
});
import base64, requests, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/delete'

# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

delete_request = {
  "reference" : "your_request_reference",
  "comment"   : "Customer asked to delete his/her data"
}

# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.post(url, 
        headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"},
        data=json.dumps(delete_request))

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()

# Convert json string to json object
json_response = json.loads(response.content)
sp_signature = response.headers.get('Signature','')

if sp_signature == calculated_signature:
    print ('Response : {}'.format(json_response))
else:
    print ('Invalid Signature: {}'.format(json_response))
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/delete")

# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

post_data = { 
     reference: "your_request_reference",
     comment: "Customer asked to delete his/her data"
}

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token
request.body = post_data.to_json

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = JSON.parse(response.read_body)

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY

if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

Once a verification request is completed, you may request at the delete request endpoint to delete the verification data. You’ll have to provide the reference ID for that request and you will be promptly informed about the deletion of the request.

Run in Postman

Parameter Description
reference Required: Yes
Type: string
Minimum: 6 characters
Maximum: 250 characters
This is the unique reference ID of request which needs to be deleted.
comment Required: Yes
Type: string
Minimum: 5 characters
Maximum: 200 characters
Add a comment why the request is deleted for your future reference

Account Info Request

Sample Account Info Request

//GET /account/info/ HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 

//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/account/info/', 
{
  method : 'get',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  }
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     return data;
});
<?php
$url = 'https://api.shuftipro.com/account/info/';
//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';
$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization: Bearer ' . $access_token);

//Calling Shufti Pro request API using curl
$response = send_curl($url, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}
//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);

if($sp_signature == $calculate_signature){

  echo "Response :" . $response_data;
  }else{
    echo "Invalid signature :" .  $response_data;
  }

function send_curl($url, $headers, $auth){ // remove $auth in case of Access Token
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
  $html_response = curl_exec($ch);
  $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $headers = substr($html_response, 0, $header_size);
  $body = substr($html_response, $header_size);
  curl_close($ch);
  return ['headers' => $headers,'body' => $body];     
}
?>
import base64, requests, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/account/info/'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.get(url, 
        headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"})

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()

# Convert json string to json object
json_response = json.loads(response.content)
sp_signature = response.headers.get('Signature','')

if sp_signature == calculated_signature:
    print ('Response : {}'.format(json_response))
else:
  print ('Invalid Signature: {}'.format(json_response))
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/account/info/")

# Your Shufti Pro account Client ID
CLIENT_ID  = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = JSON.parse(response.read_body)

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY

if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

Sample Account Info Response

{
    "account": {
        "name": "your account name",
        "status": "production",
        "balance": {
            "amount": "99.85",
            "currency": "USD"
        }
    }
}
{
    "account": {
        "name": "your account name",
        "status": "production",
        "balance": {
            "amount": "99.85",
            "currency": "USD"
        },
        "subscription_plan_details": {
            "kyc": [
                {
                    "total_requests": 100,
                    "used_requests": 0,
                    "remaining_requests": 100,
                    "start_date": "2020-05-03",
                    "end_date": "2020-05-18"
                },
                {
                    "total_requests": 100,
                    "used_requests": 0,
                    "remaining_requests": 100,
                    "start_date": "2020-05-18",
                    "end_date": "2020-05-30"
                }
            ],
            "aml": [
                {
                    "total_requests": 500,
                    "used_requests": 0,
                    "remaining_requests": 500,
                    "start_date": "2020-05-01",
                    "end_date": "2020-05-30"
                },
                {
                    "total_requests": 200,
                    "used_requests": 0,
                    "remaining_requests": 200,
                    "start_date": "2020-05-30",
                    "end_date": "2020-06-27"
                }
            ],
            "kyb": [
                {
                    "total_requests": 3000,
                    "used_requests": 0,
                    "remaining_requests": 3000,
                    "start_date": "2020-05-08",
                    "end_date": "2020-05-30"
                }
            ]
        }
    }
}
{
    "account": {
        "name": "your account name",
        "status": "trial",
        "balance": {
            "amount": "99.85",
            "currency": "USD"
        }
    }
}

This end-point provides account information to the customer such as account status, balance, and type (production mode or trial mode).

Run in Postman

Access Token Request

Sample Access Token Request

//POST https://api.shuftipro.com/get/access/token HTTP/1.1
//Host: api.shuftipro.com
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 

<?php
$url = 'https://api.shuftipro.com/get/access/token';
//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';

$auth = $client_id . ":" . $secret_key;
$headers = ['Content-Type: application/json'];
//Calling Shufti Pro request API using curl
$response = send_curl($url, $headers, $auth);
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}

//Calculating signature for verification
$calculate_signature  = hash('sha256',$response_data.$secret_key);

if($sp_signature == $calculate_signature){
  echo "Response :" . $response_data;
}else{
  echo "Invalid signature :" . $response_data;
}

function send_curl($url, $headers, $auth){
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_USERPWD, $auth);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, 1);
  $html_response = curl_exec($ch);
  $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $headers = substr($html_response, 0, $header_size);
  $body = substr($html_response, $header_size);
  curl_close($ch);
  return ['headers' => $headers, 'body' => $body];     
}
?>
//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN

//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/get/access/token', 
{
  method : 'post',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token
  }
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     return data;
});
import base64, requests, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/get/access/token'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'

# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
response = requests.post(url, 
        headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"})

# Calculating signature for verification
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()

# Convert json string to json object
json_response = json.loads(response.content)
sp_signature = response.headers.get('Signature','')

if sp_signature == calculated_signature:
    print ('Response : {}'.format(json_response))
else:
    print ('Invalid Signature: {}'.format(json_response))
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/get/access/token")
# Your Shufti Pro account Client ID
CLIENT_ID   = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY  = "YOUR-SECRET-KEY"

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = JSON.parse(response.read_body)

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY

if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

Sample Access Token Response

{
    "access_token": "NzA4N2I2YjAwZjQyYmUyNDc1YTUxZmZiMzJjMTQ4M2IxOTY2ZTFmMg=="
}

This end-point is used to generate an access_token which is used to authorize API requests. The access token will be applicable only for 10 minutes per request to the API.

Responses

Sample Response

//Content-Type: application/json
//Signature: NmI4NmIyNzNmZjM0ZmNl

{
    "reference":"17374217",
    "event":"request.pending",
    "verification_url":"https://app.shuftipro.com/process/verification/RPQ8hwPE3cdHKho2wjK7CVQJCQxNx5Rwmb81k3ediXLSWhQM5QibGBWOSgCVjZJd"
}

The Shufti Pro Verification API will send you two types of responses if a request for verification is made. First is the HTTP response sent against your request, and the second is the callback response. Both HTTP and callback responses will be in JSON format with a header. application/json The response header also includes a Key Signature. This key is used for validating the source of the response. Be sure to validate the request by generating signature and matching it with the Signature value from the response header.

Verification Response

Responses will contain the following parameters:

Parameters Description
reference Your unique request reference, which you provided us at the time of request, so that you can identify the response in relation to the request made.
events This is the request event which shows status of request. Event is changed in every response. Please consult Events for more information.
error Whenever there is an error in your request, this parameter will have the details of that error.
token This is the unique request token of the request.
verification_url A URL is generated for your customer to verify there documents. It is only generated in case of on-site request.
verification_result It is only returned in case of a valid verification. This includes results of each verification.
1 means accepted
0 means declined
null means not processed
Check verification.accepted and verification.declined responses in Events section for a sample response.
verification_data It is only returned in case of a valid verification. This object will include the all the gathered data in a request process. Check verification.accepted and verification.declined responses in Events section for a sample response. For more info Click Here.
info This object will be returned in case of verification.accepted or verification.declined. It contains the following keys:
Agent provides information about the device and browser of the end-user.
Geolocation provides information about the geographical location of the end-user.
For Details on info object go to INFO
additional_data This object will be returned in case of verification.accepted or verification.declined. This object contains the additional data extracted by Shuftipro on the document.
For Details on additional_data object go to Additional Data
declined_reason This parameter will have the reason due to which a verification has been declined, and is only returned in this case in the callback URL.
For more info Click Here
declined_codes This array contains status codes of all declined verification reasons. It will return only for verification.declined.
For more info Click Here
services_declined_codes This object contains status codes of declined reasons for each service separately. Each service object will contain an array of status codes for declined reasons specific to that service. It will return only for verification. declined.
For more info Click Here

Status Response

Sample Response

//Content-Type: application/json
//Signature: NmI4NmIyNzNmZjM0ZmNl

{
    "reference" : "17374217",
    "event"     : "verification.accepted",
    "country"   : "GB",
    "proofs"     : {
        "face": {
            "proof": "https://api.shuftipro.com/storage/aZa8mncOFLrbtxXk7Ka/face/proof.png?access_token=1a6c9985e88051092b31d62d043"
        },
        "document": {
            "proof": "https://api.shuftipro.com/storage/aZa8mncOFLrbtxXk7Ka/document/proof.png?access_token=1a6c9985e88051092b31d62d043"
        },
        "documenttwo": {
            "proof": "https://api.shuftipro.com/storage/aZa8mncOFLrbtxXk7Ka/documenttwo/proof.png?access_token=1a6c9985e88051092b31d62d043"
        },
        "address": {
            "proof": "https://api.shuftipro.com/storage/aZa8mncOFLrbtxXk7Ka/address/proof.png?access_token=1a6c9985e88051092b31d62d043"
        },
        "consent": {
            "proof": "https://api.shuftipro.com/storage/aZa8mncOFLrbtxXk7Ka/consent/proof.png?access_token=1a6c9985e88051092b31d62d043"
        },
        "verification_video" : "https://api.shuftipro.com/storage/aZa8mncOFLrbtxXk7Ka/video/video.mp4?access_token=3242f486e3346db90f442c9ac06a4ad1771ead3c" 
    },
    "verification_data": {
        "document": {
            "issue_date": "1990-01-01",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "passport",
                "driving_license",
                "credit_or_debit_card"
            ],
            "face_match_confidence": 70
        },
        "document_two": {
            "dob": "1990-01-01",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "passport",
                "driving_license",
                "credit_or_debit_card"
            ]
        },
        "address": {
            "full_address": "Candyland Avenue",
            "selected_type": [
                "utility_bill"
            ],
            "supported_types": [
                "utility_bill",
                "driving_license",
                "bank_statement",
                "envelope",
                "id_card",
                "passport",
                "rent_agreement",
                "employer_letter",
                "insurance_agreement",
                "tax_bill"
            ]
        },
        "consent": {
            "text": "My name is John Doe and I authorise this transaction of $100/- Date: July 15, 2020",
            "selected_type": [
                "handwritten"
            ],
            "supported_types": [
                "handwritten",
                "printed"
            ]
        },
        "background_checks": {
            "dob": "1990-01-01",
            "name": {
                "last_name": "John",
                "first_name": "Doe"
            }
        },
      "aml_for_business": {
        "business_name": "Company Name",
        "business_incorporation_date": "1975-07-01",
        "aml_data": {
            "filters": [
                "sanction",
                "warning",
                "fitness-probity",
                "pep",
                "pep-class-1",
                "pep-class-2",
                "pep-class-3",
                "pep-class-4"
            ],
            "hits": [
                {
                    "name": "Company Name",
                    "entity_type": "organisation",
                    "score": 24.911245,
                    "match_types": [
                        "name_exact"
                    ],
                    "alternative_names": [
                        "Company Name"
                    ],
                    "assets": [
                        {
                            "public_url": "http://example.s3.amazonaws.com/834refjadfkjhq4-ahfdkddfa8a.pdf",
                            "source": "us-securities-exchange-commission-litigation-releases",
                            "type": "pdf"
                        }
                    ],
                    "associates": [],
                    "fields": {
                        "Activation Date": [
                            {
                                "value": "Jul. 17, 2019",
                                "source": "united-states-securities-and-exchange-commission-administrative-proceedings-organisation",
                                "tag": ""
                            }
                        ],
                        "Adverse Media Subtypes": [
                            {
                                "value": "antitrust, corporate-fraud, corruption, fines, insider-trading, litigation, money-laundering, other-crime, security, tax-evasion",
                                "source": "company-am",
                                "tag": ""
                            }
                        ],
                        "Date": [
                            {
                                "value": "2002-08-03",
                                "source": "us-securities-exchange-commission-litigation-releases",
                                "tag": ""
                            }
                        ],
                        "Enforcement Agency": [
                            {
                                "value": "United States Securities and Exchange Commission",
                                "source": "united-states-securities-and-exchange-commission-administrative-proceedings-organisation",
                                "tag": ""
                            }
                        ],
                        "Related URL": [
                            {
                                "value": "http://www.sec.gov/litigation/link423.shtml",
                                "source": "us-securities-exchange-commission-litigation-releases",
                                "tag": "related_url"
                            },
                            {
                                "value": "https://www.sec.gov/litigation/admin/2019/34-72891heq89.pdf",
                                "source": "united-states-securities-and-exchange-commission-administrative-proceedings-organisation",
                                "tag": "related_url"
                            }
                        ],
                        "Release": [
                            {
                                "value": "Release information about company...",
                                "source": "us-securities-exchange-commission-litigation-releases",
                                "tag": ""
                            }
                        ],
                        "Release Number": [
                            {
                                "value": "34-46017",
                                "source": "us-securities-exchange-commission-litigation-releases",
                                "tag": ""
                            }
                        ],
                        "Related Url": [
                            {
                                "value": "http://www.sec.gov/litigation/admin/34-234324.htm",
                                "source": "us-securities-exchange-commission-litigation-releases",
                                "tag": "related_url"
                            }
                        ]
                    },
                    "media": [
                        {
                            "date": "2019-09-15T00:00:00Z",
                            "snippet": "The NYPD said 12 men and 75 women were charged with obstructing traffic after blocking cars outside the company's flagship shop on 5th Avenue between 53rd and 54th streets on Satur day",
                            "title": "Dozens of ICE Protesters Arrested in Midtown - American Renaissance",
                            "url": "https://www.amren.com/news/2019/23/dozens-of-ice-protesters-arrtedaddsa-in-midtown/"
                        },
                        {
                            "date": "2019-09-15T00:00:00Z",
                            "snippet": "The NYPD said 12 men and 75 women were charged with obstructing traffic after blocking cars outside the company's flagship shop on 5th Avenue between 53rd and 54th streets on Satur day",
                            "title": "Dozens of ICE protesters arrested in Midtown",
                            "url": "https://nypost.com/2019/10/23/dozens-of-ice-asdf-asdfd-in-midtown/"
                        }
                    ],
                    "source_notes": {
                        "company-am": {
                            "aml_types": [
                                "adverse-media",
                                "adverse-media-financial-crime",
                                "adverse-media-fraud",
                                "adverse-media-general"
                            ],
                            "name": "company AM"
                        },
                        "united-states-securities-and-exchange-commission-administrative-proceedings-organisation": {
                            "aml_types": [
                                "warning"
                            ],
                            "listing_started_utc": "2019-07-25T00:00:00Z",
                            "name": "United States Securities and Exchange Commission Administrative Proceedings - organisation",
                            "url": "https://www.sec.gov/litigation/asddfa.shtml"
                        },
                        "us-securities-exchange-commission-litigation-releases": {
                            "aml_types": [
                                "warning"
                            ],
                            "listing_ended_utc": "2016-12-22T00:00:00Z",
                            "name": "Warnings USA SEC Litigation Releases",
                            "url": "http://www.sec.gov/litigation/asdfasdf.shtml"
                        }
                    },
                    "sources": [
                        "company-am",
                        "united-states-securities-and-exchange-commission-administrative-proceedings-organisation",
                        "us-securities-exchange-commission-litigation-releases"
                    ],
                    "types": [
                        "adverse-media",
                        "adverse-media-financial-crime",
                        "adverse-media-fraud",
                        "adverse-media-general",
                        "warning"
                    ]
                }
            ]
        }
     }
    },
    "verification_result": {
        "background_checks": 1,
        "consent": {
            "consent": 1,
            "selected_type": 1
        },
        "address": {
            "partial_address_match_with_id_and_utility_bill": 1,
            "full_address": 1,
            "address_document_visibility": 1,
            "address_document_must_not_be_expired": 1,
            "address_document": 1,
            "address_document_country": 1,
            "selected_type": 1
        },
        "document": {
            "issue_date": 1,
            "document_visibility": 1,
            "document_must_not_be_expired": 1,
            "document": 1,
            "document_country": 1,
            "selected_type": 1
        },
        "document_two": {
            "dob": 1,
            "document_visibility": 1,
            "document_must_not_be_expired": 1,
            "document": 1,
            "document_country": 1,
            "selected_type": 1
        },
        "face": 1
    },
    "info": {
        "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_0"
        },
        "geolocation": {
            "host": "212.103.50.243",
            "ip": "212.103.50.243",
            "rdns": "212.103.50.243",
            "asn": "9009",
            "isp": "M247 Ltd",
            "country_name": "Germany",
            "country_code": "DE",
            "region_name": "Hesse",
            "region_code": "HE",
            "city": "Frankfurt am Main",
            "postal_code": "60326",
            "continent_name": "Europe",
            "continent_code": "EU",
            "latitude": "50.1049",
            "longitude": "8.6295",
            "metro_code": "",
            "timezone": "Europe/Berlin"
        }
    },
    "additional_data": {
        "document": {
            "proof": {
                "gender": "M",
                "height": "183",
                "country": "United Kingdom",
                "authority": "HMPO",
                "last_name": "Doe",
                "first_name": "John",
                "issue_date": "2018-01-31",
                "expiry_date": "2028-01-30",
                "nationality": "BRITSH CITIZEN",
                "country_code": "GBR",
                "document_type": "P",
                "place_of_birth": "BRISTOL",
                "document_number": "GB1234567",
                "personal_number": "12345678910",
                "dob": "1978-03-13",
                "issue_date": "2015-10-10",
                "expiry_date": "2025-12-31",
            }
        }
    }
}

The Shufti Pro Verification API will send a JSON response if a status request is made. Make sure to validate the request by generating signature and matching it with the Signature value from the response header.

Parameters Description
reference Your unique request reference, which you provided us at the time of request, so that you can identify the response in relation to the request made.
event This is the request event which shows status of request. Event is changed in every response.
Please consult Events for more information.
country This contains country code sent by the merchant at the time of request. Country code in the format of ISO 3166-1 alpha-2. Please consult Supported Countries for country codes.
Type: string
Example: DE
null if not provided by merchant.
proofs This contains all the proofs that were used to verify data. The Proof URLs returned are temporary and valid for 15 minutes only.
Note: verification_video It contains the video URL and will be returned only for the video recorded on-site.
verification_data This contains all the data used for verification. This will only be returned in case of verification.accepted or verification.declined. For more info Click Here.
verification_result This is the complete result of the verification. 1 stands for verified, 0 for not verified and null for no verification performed. This will only be returned in case of verification.accepted or verification.declined.
info This object will be returned in case of verification.accepted or verification.declined. It contains the following keys:
Agent provides information about the device and browser of the end-user.
Geolocation provides information about the geographical location of the end-user.
For Details on info object go to INFO
additional_data This object will be returned in case of verification.accepted or verification.declined. This object contains the additional data extracted by Shuftipro on the document.
For Details on additional_data object go to Additional Data
declined_reason This key will only be returned when event is verification.declined. This will contain the reason why verification was declined.
declined_codes This array contains status codes of all declined verification reasons. It will return only for verification.declined.
services_declined_codes This object contains status codes of declined reasons for each service separately. Each service object will contain an array of status codes for declined reasons specific to that service. It will return only for verification. declined.

Delete Request Response

Sample Response

//Content-Type: application/json
//Signature: NmI4NmIyNzNmZjM0ZmNl

{
    "reference": "17374217",
    "event": "request.deleted"
}

The Shufti Pro Verification API will send a JSON response if a delete request is made. Make sure to validate the request by generating signature and matching it with the Signature value from the response header

Parameters Description
reference Your unique request reference, which you provided us at the time of request, so that you can identify the response in relation to the request made.
event This is the request event which shows status of request. Event is changed in every response.

Please consult Events for more information.

Response Signature

Every HTTP and Callback response will be in application/JSON with a key Signature in the header. It can be used to validate the source of the request. Make a signature using the following procedure:

  1. Concatenate Secret Key at the end of the raw response string. (i.e. response + secret_key).
  2. Take SHA256 of concatenated string.
  3. Match the SHA256 string with Signature value from the header of the response.

In short, make signature as hash('sha256', response . your_secret_key) and match it with the signature provided in the header in Signature key.

Technical Appendix

Enhanced Data Extraction

Shufti Pro provides its customers with the facility of extracting enhanced data features using OCR technology. Now, instead of extracting just personal information input fields, Shufti Pro can fetch all the additional information comprising more than 100 data points from the official ID documents supporting 150 languages. For example height, place_of_birth, nationality, marital_status, weight, etc. Shufti Pro is the first digital identity verification service that can fetch a huge bunch of information efficiently in mere seconds.
Note: Additional charges are applicable for this feature.

This feature can be used with document and document_two services.

{
    "fetch_enhanced_data" :"1"
}
Parameters Description
fetch_enhanced_data Required: No
Type: string
Value Accepted: 1
Provide 1 for enabling enhanced data extraction for the document. Extracted data will be returned in object under the key additional_data in case of verification.accepted or verification.declined.
For Details on additional_data object go to Additional Data

Name

name is an object and contains the following parameters

Name sample object

{
    "name" : {
        "first_name"  : "John",
        "middle_name" : "Carter",
        "last_name"   : "Doe",
        "fuzzy_match" : "1"
    }
}
{
    "name" : {
        "full_name"   : "John Carter Doe",
        "fuzzy_match" : "1"
    }
}
Parameters Description
first_name Required: No
Type: string
Minimum: 1 character
Maximum: 32 characters
Allowed Characters are alphabets, - (dash), comma, apostrophe, space, dot and single quotation mark.
Example: John'O Harra
middle_name Required: No
Type: string
Minimum: 1 character
Maximum: 32 characters
Allowed Characters are alphabets, - (dash), comma, apostrophe, space, dot and single quotation mark.
Example: Carter-Joe
last_name Required: No
Type: string
Minimum: 1 character
Maximum: 32 characters
Allowed Characters are alphabets, - (dash), comma, apostrophe, space, dot and single quotation mark.
Example: John, Huricane Jr.
fuzzy_match Required: No
Type: string
Value Accepted: 1
Provide 1 for enabling a fuzzy match of the name. Enabling fuzzy matching attempts to find a match which is not a 100% accurate.
full_name Required: No
Type: string
Minimum: 1 character
Maximum: 64 characters
Some countries don't have the identity document holder name as their first, middle or last name instead its written in full. In such cases, you may provide the full name.

Age

Shufti Pro provides its clients with an option to configure the Age verification from within the API request. This service allows the acceptance of users within the specified age limits according to their DOB. The client can specify lower and upper limits and according to that, the user's age will be verified. In case, minimum and maximum values are not set, Shufti Pro will calculate and return Age according to the DOB. If DOB is not present on the document, the verification will decline as Age will not be verified
Age is an object or integer that can be used to set the lower and upper limit for the Age of the user according to DOB. It contains the following parameters. min is used to specify the lower limit whereas max is used to specify the upper limit.

Age sample object

//Passing the value “18” in the age parameter means that, end-users of age 18 will stand verified.
{
    "age" : 18    
}
{
    "age" : {
        "min"   : "17",
        "max" : "165"
    }
}
Parameters Description
age Required: No
Type: integer/array
Allowed values are integers or array.
Example: 18
min Required: No
Type: integer
Minimum Value: 1
Allowed values are integers or array.
Example: 17
max Required: No
Type: integer
Maximum Value: 170
Allowed values are integers or array.
Example: 165

Verification Data Parameters

Verification Data will contain the following services:

Face Service

Face service object will contain the following parameters:

Parameters Description
duplicate_account_detected This key object contains information about the duplication status. It can be either 1 (duplication detected), 0 (no duplication), or null (invalid picture).

Document Service

Document service object will contain the following parameters:

Parameters Description
name This key object contains name information extracted from the document.
name.first_name This key contains the first name of the end-user extracted from the document proof.
name.middle_name This key contains the end user’s middle name written on the document.
name.last_name This key contains the end user’s last name written on the document.
dob This key contains the end user’s date of birth written on the document.
age This key contains the age of end user for age verification.
issue_date This key contains the issue date of the document proof.
expiry_date This key contains the expiry date of the document proof.
document_number Contains the document number extracted from the document proof provided by the end-user.
selected_type This key contains the type of document proof selected by the end-user.
supported_types This key contains all types of supported document proofs.
gender This key contains the gender of the end-user listed on the document proof.
face_match_confidence This key contains a confidence score based on how accurately the end user’s face matches with their photo on the document proof.
The value of this key will be between 0 to 100.
Examples: 30, 40, 50, 60, 70

Address Service

Address service object will contain the following parameters:

Parameters Description
name This key contains all the details related to the end user’s name.
name.first_name This key contains the end user’s first name.
name.middle_name This key contains the end user’s middle name.
name.last_name This key contains the end user’s last name.
full_address This key contains of the end user’s full address written on the document.
selected_type This key contains the document proof selected by the user such as driving licence, passport or a government-issued ID, etc.
supported_types This key contains all types of supported documents.

Consent service object will contain the following parameters:

Parameters Description
text This key contains consent text written on the proof presented by the user.
selected_type This key contains the document proof selected by the user such as driving licence, passport or a government-issued ID, etc.
supported_types This key contains all types of supported documents.

Background Checks Service

Background Checks service object will contain the following parameters:

Parameters Description
dob This key contains the date of birth of the person/entity on whom background checks are performed.
name This key contains the first, last and middle name of the person/entity on whom background checks are performed.
name.first_name This key contains the first name of the person/entity on whom background checks are performed.
name.middle_name This key contains the middle name of the person/entity on whom background checks are performed.
name.last_name This key contains the last name of the person/entity on whom background checks are performed.

HTTP Status Codes and Events

Instant Capture & Verification API uses conventional HTTP response codes to indicate the success or failure of an API request. Every response is generated in JSON with a specific HTTP code. Go to Status Codes for a complete list of status codes. Events are sent in responses that show the status of the request. These events are sent in both HTTP and callback responses. Please consult Events for a complete list of events.

Status Codes

Shufti Pro Verification API uses conventional HTTP response codes to indicate the success or failure of an API request. Every response is generated in JSON with a specific HTTP code.

HTTP Codes

Following is a list of HTTP codes that are generated in responses by Shufti Pro Verification API.

HTTP code HTTP message Message
200 OK success
400 Bad Request bad request: one or more parameter is invalid or missing
401 Unauthorized unauthorized: invalid signature key provided in the request
402 Request Failed invalid request data: missing required parameters
403 Forbidden forbidden: service not allowed
404 Not Found resource not found
409 Conflict conflicting data: already exists
500 Server Error internal server error
429 Too Many Requests Too Many Attempts.

Response Events

Events are sent in responses that show the status of the request. These events are sent in both HTTP and callback responses.

request.pending

{
    "reference": "17374217",
    "event": "request.pending",
    "verification_url": "https://app.shuftipro.com/process/verification/RPQ8hwPE3cdHKho2wjK7CVQJCQxNx5Rwmb81k3ediXLSWhQM5QibGBWOSgCVjZJd",
    "email": "johndoe@example.com",
    "country": "GB"
}

request.invalid

{
    "reference": "17374217",
    "event": "request.invalid",
    "error": {
        "service": "document",
        "key": "dob",
        "message": "The dob does not match the format Y-m-d."
    },
    "email": null,
    "country": null
}

verification.cancelled

{
    "reference": "17374217",
    "event": "verification.cancelled",
    "country": "GB",
    "proofs": {}
}

request.timeout

{
    "reference": "17374217",
    "event": "request.timeout",
    "country": "GB",
    "proofs": {}
}

request.unauthorized

{
    "reference": "",
    "event": "request.unauthorized",
    "error": {
        "service": "",
        "key": "",
        "message": "Authorization keys are missing/invalid."
    },
    "email": null,
    "country": null"
}

verification.accepted

{
    "reference": "17374217",
    "event": "verification.accepted",
    "verification_result": {
        "face": {
            "face": 1
        },
        "document": {
            "name": 1,
            "dob": 1,
            "age": 1,
            "expiry_date": 1,
            "issue_date": 1,
            "document_number": 1,
            "document": 1,
            "gender"  : ""
        },
        "address": {
            "name": 1,
            "full_address": 1
        }
    },
    "verification_data": {
        "face" : {
            "duplicate_account_detected" : "0"
        },
        "document": {
            "name": {
                "first_name": "John",
                "middle_name": "Carter",
                "last_name": "Doe"
            },
            "dob": "1978-03-13",
            "age":  18,
            "issue_date": "2015-10-10",
            "expiry_date": "2025-12-31",
            "document_number": "1456-0989-5567-0909",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "driving_license",
                "passport"
            ],
            "gender"    :  "M"
        },
        "address": {
            "name": {
                "first_name": "John",
                "middle_name": "Carter",
                "last_name": "Doe"
            },
            "full_address": "3339 Maryland Avenue, Largo, Florida",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "bank_statement"
            ]
        }
    },
    "info": {
        "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_0"
        },
        "geolocation": {
            "host": "212.103.50.243",
            "ip": "212.103.50.243",
            "rdns": "212.103.50.243",
            "asn": "9009",
            "isp": "M247 Ltd",
            "country_name": "Germany",
            "country_code": "DE",
            "region_name": "Hesse",
            "region_code": "HE",
            "city": "Frankfurt am Main",
            "postal_code": "60326",
            "continent_name": "Europe",
            "continent_code": "EU",
            "latitude": "50.1049",
            "longitude": "8.6295",
            "metro_code": "",
            "timezone": "Europe/Berlin"
        }
    },
    "additional_data": {
        "document": {
            "proof": {
                "height": "183",
                "country": "United Kingdom",
                "authority": "HMPO",
                "last_name": "Doe",
                "first_name": "John",
                "issue_date": "2018-01-31",
                "expiry_date": "2028-01-30",
                "nationality": "BRITSH CITIZEN",
                "country_code": "GBR",
                "document_type": "P",
                "place_of_birth": "BRISTOL",
                "document_number": "GB1234567",
                "personal_number": "12345678910",
                "dob": "1978-03-13",
                "age":  18,
                "gender"     :  ""
            }
        }
    }
}

verification.declined

{
    "reference": "95156124",
    "event": "verification.declined",
    "verification_result": {
        "document": {
            "name": 0,
            "dob": 1,
            "age": 1,
            "expiry_date": 1,
            "issue_date": 1,
            "document_number": 1,
            "document": null
        },
        "address": {
            "name": null,
            "full_address": null
        }
    },
    "verification_data": {
        "document": {
            "name": {
                "first_name": "John",
                "middle_name": "Carter",
                "last_name": "Doe"
            },
            "dob": "1978-03-13",
            "age":  18,
            "issue_date": "2015-10-10",
            "expiry_date": "2025-12-31",
            "gender"   :  "M"
            "document_number": "1456-0989-5567-0909",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "driving_license",
                "passport"
            ]
        },
        "address": {
            "name": {
                "first_name": "John",
                "middle_name": "Carter",
                "last_name": "Doe"
            },
            "full_address": "3339 Maryland Avenue, Largo, Florida",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "bank_statement"
            ]
        }
    },
    "info": {
        "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_0"
        },
        "geolocation": {
            "host": "212.103.50.243",
            "ip": "212.103.50.243",
            "rdns": "212.103.50.243",
            "asn": "9009",
            "isp": "M247 Ltd",
            "country_name": "Germany",
            "country_code": "DE",
            "region_name": "Hesse",
            "region_code": "HE",
            "city": "Frankfurt am Main",
            "postal_code": "60326",
            "continent_name": "Europe",
            "continent_code": "EU",
            "latitude": "50.1049",
            "longitude": "8.6295",
            "metro_code": "",
            "timezone": "Europe/Berlin"
        }
    },
    "declined_reason": "Name on the document doesn't match",
    "declined_codes":[
         "SPDR07",
         "SPDR06",
         "SPDR23"
    ],
    "additional_data": {
        "document": {
            "proof": {
                "height": "183",
                "country": "United Kingdom",
                "authority": "HMPO",
                "last_name": "Doe",
                "first_name": "John",
                "issue_date": "2018-01-31",
                "expiry_date": "2028-01-30",
                "nationality": "BRITSH CITIZEN",
                "country_code": "GBR",
                "document_type": "P",
                "place_of_birth": "BRISTOL",
                "document_number": "GB1234567",
                "personal_number": "12345678910",
                "dob": "1978-03-13",
                "age":  18,
                "gender"     :  "M"
            }
        }
    },
    "services_declined_codes": {
        "document": [
            "SPDR13",
            "SPDR12"
        ],
        "address": [
            "SPDR22",
            "SPDR26"
        ],
        "face": [
            "SPDR01"
        ]
    }
}

verification.status.changed

{
    "reference": "17374217",
    "event": "verification.status.changed"
}

request.deleted

{
    "reference": "17374217",
    "event": "request.deleted"
}

request.received

{
    "reference": "17374217",
    "event": "request.received",
    "email": "johndoe@example.com",
    "country": "UK"
}

review.pending

{
    "reference": "95156124",
    "event": "review.pending",
    "verification_result": {
        "document": {
            "name": 0,
            "dob": 1,
            "age": 1,
            "expiry_date": 1,
            "issue_date": 1,
            "document_number": 1,
            "document": null
        },
        "address": {
            "name": null,
            "full_address": null
        }
    },
    "verification_data": {
        "document": {
            "name": {
                "first_name": "John",
                "middle_name": "Carter",
                "last_name": "Doe"
            },
            "dob": "1978-03-13",
            "age":  18,
            "issue_date": "2015-10-10",
            "expiry_date": "2025-12-31",
            "gender"   :  "M"
            "document_number": "1456-0989-5567-0909",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "driving_license",
                "passport"
            ]
        },
        "address": {
            "name": {
                "first_name": "John",
                "middle_name": "Carter",
                "last_name": "Doe"
            },
            "full_address": "3339 Maryland Avenue, Largo, Florida",
            "selected_type": [
                "id_card"
            ],
            "supported_types": [
                "id_card",
                "bank_statement"
            ]
        }
    },
    "info": {
        "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_0"
        },
        "geolocation": {
            "host": "212.103.50.243",
            "ip": "212.103.50.243",
            "rdns": "212.103.50.243",
            "asn": "9009",
            "isp": "M247 Ltd",
            "country_name": "Germany",
            "country_code": "DE",
            "region_name": "Hesse",
            "region_code": "HE",
            "city": "Frankfurt am Main",
            "postal_code": "60326",
            "continent_name": "Europe",
            "continent_code": "EU",
            "latitude": "50.1049",
            "longitude": "8.6295",
            "metro_code": "",
            "timezone": "Europe/Berlin"
        }
    },
    "declined_reason": "Name on the document doesn't match",
    "declined_codes":[
         "SPDR07",
         "SPDR06",
         "SPDR23"
    ],
    "additional_data": {
        "document": {
            "proof": {
                "height": "183",
                "country": "United Kingdom",
                "authority": "HMPO",
                "last_name": "Doe",
                "first_name": "John",
                "issue_date": "2018-01-31",
                "expiry_date": "2028-01-30",
                "nationality": "BRITSH CITIZEN",
                "country_code": "GBR",
                "document_type": "P",
                "place_of_birth": "BRISTOL",
                "document_number": "GB1234567",
                "personal_number": "12345678910",
                "dob": "1978-03-13",
                "age":  18,
                "gender"     :  "M"
            }
        }
    },
    "services_declined_codes": {
        "document": [
            "SPDR13",
            "SPDR12"
        ],
        "address": [
            "SPDR22",
            "SPDR26"
        ],
        "face": [
            "SPDR01"
        ]
    }
}
Event description HTTP Response Callback Response
request.pending Request parameters are valid and verification url is generated in case of on-site verification. Yes Yes
request.invalid Request parameters provided in request are invalid. Yes No
verification.cancelled Request is cancelled by the user. This event occurs when end-user disagrees to terms and conditions before starting verifications. Yes Yes
request.timeout Request has timed out after a specific period of time.
The onsite request will Time Out after 60 minutes.
No Yes
request.unauthorized Request is unauthorized. The information provided in authorization header is invalid. Yes No
verification.accepted Request was valid and accepted after verification. Yes Yes
verification.declined Request was valid and declined after verification. Yes Yes
verification.status.changed Request status has been updated. No Yes
request.deleted Request has been deleted. Yes Yes
request.received Request has been received. Yes Yes
review.pending Documents are collected and request is pending for client to review and Accept/Decline. Yes Yes

Instructions Parameters

Instruction Parameters

{
    "document":{
        "proof":"",
        "supported_types":["id_card","driving_license","passport"],
    "verification_instructions" : {
        "allow_paper_based" : "1",
        "allow_photocopy"   : "1",
        "allow_laminated"   : "1",
        "allow_screenshot" : "1",
        "allow_cropped" : "1",
        "allow_scanned" : "1"
    }
  }
}

Instruction Parameters

{
    "document_two":{
        "proof":"",
        "supported_types":["id_card","driving_license","passport"],
    "verification_instructions" : {
        "allow_paper_based" : "1",
        "allow_photocopy"   : "1",
        "allow_laminated"   : "1",
        "allow_screenshot" : "1",
        "allow_cropped" : "1",
        "allow_scanned" : "1"
    }
  }
}

Instruction Parameters

{
    "address":{
        "proof":"",
        "supported_types":["id_card","driving_license","passport"],
    "verification_instructions" : {
        "allow_paper_based" : "1",
        "allow_photocopy"   : "1",
        "allow_laminated"   : "1",
        "allow_screenshot" : "1",
        "allow_cropped" : "1",
        "allow_scanned" : "1"
    }
  }
}

These parameters can be used with Document, Document Two and Address Service.

Parameters Description
allow_paper_based Required: No
Type: string
Value Accepted: 0, 1
Default Value: 0
If this string is assigned value “1” then Shufti Pro will accept paper-backed documents for verification.
allow_photocopy Required: No
Type: string
Value Accepted: 0, 1
Default Value: 0
If this string is assigned value “1” then Shufti Pro will accept photocopied documents for verification.
allow_laminated Required: No
Type: string
Value Accepted: 0, 1
Default Value: 0
If this string is assigned value “1” then Shufti Pro will accept laminated documents for verification.
allow_screenshot Required: No
Type: string
Value Accepted: 0, 1
Default Value: 0
If this string is assigned value “1” then Shufti Pro will accept screenshot documents for verification.
allow_cropped Required: No
Type: string
Value Accepted: 0, 1
Default Value: 0
If this string is assigned value “1” then Shufti Pro will accept cropped documents for verification.
allow_scanned Required: No
Type: string
Value Accepted: 0, 1
Default Value: 0
If this string is assigned value “1” then Shufti Pro will accept scanned documents for verification.

Supported Types

Shufti Pro supports different types of ID and address documents, along with various consent notes. All the supported types are mentioned below.

Document Supported Types

All document supported types are listed below.

Supported Types
1. passport
2. id_card
3. driving_license
4. credit_or_debit_card

Address Supported Types

All address supported types are listed below.

Supported Types
1. id_card
2. passport
3. driving_license
4. utility_bill
5. bank_statement
6. rent_agreement
7. employer_letter
8. insurance_agreement
9. tax_bill
10. envelope
11. cpr_smart_card_reader_copy
12. property_tax
13. lease_agreement
14. insurance_card
15. permanent_residence_permit
16. credit_card_statement
17. insurance_policy
18. e_commerce_receipt
19. bank_letter_receipt
20. birth_certificate
21. salary_slip
22. any
Note: The "any" supported type allows the acceptance of all address document types if it has the user's Name and Address on it.

All consent supported types are listed below.

Supported Types
1. handwritten
2. printed

Rate Limiting

Shufti Pro has induced request limits for the Production and Trial accounts. The limits for both types of accounts are mentioned below.

Production Account

For the production account, Shufti Pro allows 60 requests per min. This limit is per IP.

Trial Account

For the trial account, Shufti Pro allows 3 requests per minute. This limit is per account.

Info

This object will be returned in case of verification.accepted or verification.declined. It contains the following keys:
The Agent provides information about the device and browser of the end-user.
Geolocation provides information about the geographical location of the end-user.

Agent

agent is an object and contains the following parameters

Agent sample object

{
    "agent": {
            "is_desktop": true,
            "is_phone": false,
            "useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
            "device_name": "Macintosh",
            "browser_name": "",
            "platform_name": "OS X - 10_14_0"
        }

}
Parameters Description
is_desktop Type: Boolean
Example: true
Shows empty string “” if not detected.
is_phone Type: Boolean
Example: false
Shows empty string “” if not detected.
useragent Type: string
Example: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Shows empty string “” if not detected.
device_name Type: string
Example: Macintosh
Shows empty string “” if not detected.
browser_name Type: string
Example: Chrome - 70.0.3538.80
Shows empty string “” if not detected.
platform_name Type: string
Example: OS X - 10_14_0
Shows empty string “” if not detected.

Geo location

geolocation is an object and contains the following parameters

geolocation sample object

{

    "geolocation": {
            "host": "212.103.50.243",
            "ip": "212.103.50.243",
            "rdns": "212.103.50.243",
            "asn": "9009",
            "isp": "M247 Ltd",
            "country_name": "Germany",
            "country_code": "DE",
            "region_name": "Hesse",
            "region_code": "HE",
            "city": "Frankfurt am Main",
            "postal_code": "60326",
            "continent_name": "Europe",
            "continent_code": "EU",
            "latitude": "50.1049",
            "longitude": "8.6295",
            "metro_code": "",
            "timezone": "Europe/Berlin"
        }

}
Parameters Description
host Type: string
Example: 212.103.50.243
Shows empty string “” if not detected.
ip Type: string**
Example: 212.103.50.243
Shows empty string “” if not detected.
rdns Type: string
Example: 212.103.50.243
Shows empty string “” if not detected.
asn Type: string
Example: 9009
Shows empty string “” if not detected.
isp Type: string
Example: M247 Ltd
Shows empty string “” if not detected.
country_name Type: string
Example: Germany
Shows empty string “” if not detected.
country_code Type: string
Example: DE
Shows empty string “” if not detected.
region_name Type: string
Example: Hesse
Shows empty string “” if not detected.
region_code Type: string
Example: HE
Shows empty string “” if not detected.
city Type: string
Example: Frankfurt am Main
Shows empty string “” if not detected.
postal_code Type: string
Example: 60326
Shows empty string “” if not detected.
continent_name Type: string
Example: Europe
Shows empty string “” if not detected.
continent_code Type: string
Example: EU
Shows empty string “” if not detected.
latitude Type: string
Example: 50.1049
Shows empty string “” if not detected.
longitude Type: string
Example: 50.1049
Shows empty string “” if not detected.
metro_code Type: string
Example: 501
Shows empty string “” if not detected.
timezone Type: string
Example: Europe/Berlin
Shows empty string “” if not detected.

Additional Data

Additional Data object

{
    "additional_data": {
        "document": {
            "proof": {
                "gender": "M",
                "height": "183",
                "country": "United Kingdom",
                "authority": "HMPO",
                "last_name": "Doe",
                "first_name": "John",
                "issue_date": "2018-01-31",
                "expiry_date": "2028-01-30",
                "nationality": "BRITSH CITIZEN",
                "country_code": "GBR",
                "document_type": "P",
                "place_of_birth": "BRISTOL",
                "document_number": "GB1234567",
                "personal_number": "12345678910",
                "dob": "1978-03-13",
                "age":  18,
                "issue_date": "2015-10-10",
                "expiry_date": "2025-12-31",
                "signature": "335,300,435,400",
            }
        }
    }

}

This object will be returned in case of verification.accepted or verification.declined. This object contains the additional data extracted by Shuftipro. For example height, place_of_birth, nationality, marital_status, weight. The values in the object will be in string format. For keys ('face', 'finger_print', 'signature') comma-separated string will be returned, which will contain coordinates x1,y1,x2,y2 (top-left and bottom-right).

Note: keys in this object may change based on data extracted from the document.

Declined Reasons

Face

Description
1. Face could not be verified
2. Face could not be detected in image, please upload image again with your face clearly visible
3. Image is altered or photoshopped
4. Copy of the image found on web
5. Face in the image is with wearing glasses
6. Face proof is from another screen
7. Face proof is taken from the web
8. More than one face in one image
9. Face proof is a screenshot
10. Face doesn't match the face image uploaded at the time of signup
11. Document doesn’t match the document uploaded at the time of signup
12. Camera is not accessible for verification

Document & Document Two

Description
1. Image of the face not found on the document
2. Document originality could not be verified
3. Name on the document doesn't match
4. DOB on the document doesn't match
5. The expiry date of the document does not match the record, please upload a document with valid expiry date
6. Issue date on the document doesn't match
7. Date on the document doesn't match
8. Number on the document doesn't match
9. The issuing country of document is not supported, please upload a valid document
10. Document doesn't match the provided options
11. You are not eligible because you don't fall in the provided age range
12. Face on the document doesn't match with camera image
13. The document is expired, please upload a new document which is not expired
14. The uploaded image of the document is blur, please provide a clear photo of document
15. Face could not be detected in image, please upload image again with your face clearly visible
16. Image is altered or photoshopped
17. Copy of the image found on web
18. Proof and Additional Proof are of different documents
19. Front and backside images of the document did not match, please upload images of the same document
20. Document proof is a screenshot
21. Document proof is altered/edited
22. Document proof is paper based which is not accepted
23. Document proof is punched/broken
24. Document proof is from another screen
25. Hologram is missing on the document
26. Document proof is not fully displayed.
27. Document is blur
28. Information on the document proof is not visible
29. Information on the document is edited
30. Information on the document is hidden
31. Document should be from the provided country
32. Issue date does not match with the provided one
33. Expiry date does not match with the provided one
34. Submitted document is expired
35. Issue date on the document is not clearly visible
36. Expiry date on the document is not clearly visible
37. Date of Birth on the document does not match with the provided one
38. Date of Birth on the document is not clearly visible
39. Name on the document does not match with the provided one
40. Name on the document is not clearly visible
41. Document number does not match with the provided one
42. Document number is not clearly visible
43. Original document number could not be authenticated
44. Front and backside images are not of the same document
45. Proof and additional proof does not belong to the same person
46. Address proof and document proof does not match
47. Both documents should belong to the same person
48. Document doesn’t match the document uploaded at the time of signup
49. Camera is not accessible for verification
50. Gender could not be verified
51. Place of issue could not be verified
52. The provided document is broken
53. The provided document is photocopy(color or black & white)
54. The provided document is edited
55. The provided document is scanned
56. The provided document is punched
57. The provided document is cracked
58. The provided document is cropped
59. The provided document is handwritten

Address

Description
1. Image of the face not found on the document
2. Document originality could not be verified
3. Name on the Address Document doesn't match
4. Address did not match the record, please provide a document with valid address.
5. Document type is different from the provided options
6. Country on the address document could not be verified
7. Addresses on the Identity Document and Utility Bill do not match
8. The address document is expired, please upload a document which is not expired
9. The uploaded image of the document is blur, please provide a clear photo of address document
10. Document doesn't match the provided options
11. Issue date on the address document doesn't match
12. Image is altered or photoshopped
13. Copy of the image found on web
14. Proof and Additional Proof are of different documents
15. Address proof and document proof are of different persons
16. Front and backside images of the document did not match, please upload images of the same document
17. Document proof is a screenshot
18. Document proof is altered/edited
19. Document proof is paper based which is not accepted
20. Document proof is punched/broken
21. Document proof is from another screen
22. Hologram is missing on the document
23. Document proof is not fully displayed.
24. Document is blur
25. Information on the document proof is not visible
26. Information on the document is edited
27. Information on the document is hidden
28. Document should be from the provided country
29. Issue date does not match with the provided one
30. Expiry date does not match with the provided one
31. Submitted document is expired
32. Issue date on the document is not clearly visible
33. Expiry date on the document is not clearly visible
34. Date of Birth on the document does not match with the provided one
35. Date of Birth on the document is not clearly visible
36. Name on the document does not match with the provided one
37. Name on the document is not clearly visible
38. Document number does not match with the provided one
39. Document number is not clearly visible
40. Original document number could not be authenticated
41. Address proof and document proof does not match
42. Both documents should belong to the same person
43. Address on the document does not match with the provided one
44. Address provided is invalid
45. Address on the document is not clearly visible
46. Address could not be validated
47. You are not eligible because you doesn't fall in the provided age range
48. Camera is not accessible for verification
49. Same ID Document can not be submitted as proof of address
50. The provided document is broken
51. The provided document is photocopy(color or black & white)
52. The provided document is edited
53. The provided document is scanned
54. The provided document is punched
55. The provided document is cracked
56. The provided document is cropped
57. The provided document is handwritten
Description
1. Image of the face not found on the document
2. Consent note information is not correct, please upload a note with valid information
3. Consent type is different from provided options
4. Image is altered or photoshopped
5. Copy of the image found on web
6. Camera is not accessible for verification

Background Checks

Description
1. AML screening failed
2. AML screening failed. User found in Sanction lists
3. AML screening failed. User found in Warning lists
4. AML screening failed. User found in Fitness-Probity lists
5. AML screening failed. User found in PEP lists
6. AML screening failed. User found in Adverse-Media lists

AML For Businesses

Description
1. AML screening failed
2. AML screening failed. Business found in Sanction lists
3. AML screening failed. Business found in Warning lists
4. AML screening failed. Business found in Fitness-Probity lists
5. AML screening failed. Business found in PEP lists
6. AML screening failed. Business found in Adverse-Media lists

Phone Number

Note:
Verification is declined if a user enters the wrong code consecutively for five times.
If the user is unable to receive code then, user is provide with Code not received option if user clicks the “Code not received” option the verification will be declined automatically (because either the phone number was wrong or unreachable).

Description
1. Your phone number did not match the record, please provide a valid phone number
2. Phone number not verified because end-user entered the wrong code multiple times
3. Phone number not verified because the provided number was unreachable

Declined Status Code

Run in Postman

Sample Decline Reasons Request

//GET /decline/reasons/ HTTP/1.1
//Host: api.shuftipro.com/
//Content-Type: application/json
//Authorization: Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw== 
// replace "Basic" with "Bearer in case of Access Token"

//Use your Shufti Pro account client id and secret key
var token = btoa("YOUR_CLIENT_ID:YOUR_SECRET_KEY"); //BASIC AUTH TOKEN
// if Access Token
//var token = "YOUR_ACCESS_TOKEN";
//Dispatch request via fetch API or with whatever else which best suits for you
fetch('https://api.shuftipro.com/decline/reasons', 
{
  method : 'get',
  headers : {
    'Accept'        : 'application/json',
    'Content-Type'  : 'application/json',
    'Authorization' : 'Basic ' +token       // if access token then replace "Basic" with "Bearer"
  }
})
.then(function(response) {
     return response.json();
}).then(function(data) {
     return data;
});
<?php
$url = 'https://api.shuftipro.com/decline/reasons';
//Your Shufti Pro account Client ID
$client_id  = 'YOUR-CLIENT-ID';
//Your Shufti Pro account Secret Key
$secret_key = 'YOUR-SECRET-KEY';
//OR Access Token
//$access_token = 'YOUR-ACCESS-TOKEN';
$auth = $client_id.":".$secret_key; // remove this in case of Access Token
$headers = ['Content-Type: application/json'];
// if using Access Token then add it into headers as mentioned below otherwise remove access token
// array_push($headers, 'Authorization: Bearer ' . $access_token);

//Calling Shufti Pro request API using curl
$response = send_curl($url, $headers, $auth); // remove $auth in case of Access Token
//Get Shufti Pro API Response
$response_data    = $response['body'];
//Get Shufti Pro Signature
$exploded = explode("\n", $response['headers']);
// Get Signature Key from Hearders
$sp_signature = null;
foreach ($exploded as $key => $value) {
  if (strpos($value, 'signature: ') !== false || strpos($value, 'Signature: ') !== false) {
    $sp_signature=trim(explode(':', $exploded[$key])[1]);
    break;
  }
}
//Calculating signature for verification
// calculated signature functionality cannot be implement in case of access token
$calculate_signature  = hash('sha256',$response_data.$secret_key);

if($sp_signature == $calculate_signature){

  echo "Response :" . $response_data;
  }else{
    echo "Invalid signature :" .  $response_data;
  }

function send_curl($url, $headers, $auth){ // remove $auth in case of Access Token
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_USERPWD, $auth); // remove this in case of Access Token
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // remove this in case of Access Token
  $html_response = curl_exec($ch);
  $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  $headers = substr($html_response, 0, $header_size);
  $body = substr($html_response, $header_size);
  curl_close($ch);
  return ['headers' => $headers,'body' => $body];     
}
?>
import base64, requests, json, hashlib
from random import randint

'''
Python 2
--------
import urllib2

Python 3
--------
import urllib.request
urllib.request.urlopen(url).read()
'''

url = 'https://api.shuftipro.com/decline/reasons'
# Your Shufti Pro account Client ID
client_id  = 'YOUR-CLIENT-ID'
# Your Shufti Pro account Secret Key
secret_key = 'YOUR-SECRET-KEY'
# OR Access Token
# access_token = 'YOUR-ACCESS-TOKEN';

# Calling Shufti Pro request API using python requests
auth = '{}:{}'.format(client_id, secret_key)
b64Val = base64.b64encode(auth.encode()).decode()
# if access token 
# b64Val = access_token
# replace "Basic with "Bearer" in case of Access Token
response = requests.get(url, 
        headers={"Authorization": "Basic %s" % b64Val, "Content-Type": "application/json"})

# Calculating signature for verification
# calculated signature functionality cannot be implement in case of access token
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()

# Convert json string to json object
json_response = json.loads(response.content)
sp_signature = response.headers.get('Signature','')

if sp_signature == calculated_signature:
    print ('Response : {}'.format(json_response))
else:
  print ('Invalid Signature: {}'.format(json_response))
require 'uri'
require 'net/http'
require 'base64'
require 'json'

url = URI("https://api.shuftipro.com/decline/reasons")

# Your Shufti Pro account Client ID
CLIENT_ID  = "YOUR-CLIENT-ID"
# Your Shufti Pro account Secret Key
SECRET_KEY = "YOUR-SECRET-KEY"
# if access token
# ACCESS_TOKEN = "YOUR-ACCESS-TOKEN"

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)

header_auth = Base64.strict_encode64("#{CLIENT_ID}:#{SECRET_KEY}")
# if Access Token
# header_auth = ACCESS_TOKEN
request["Content-Type"]  = "application/json"
request["Authorization"] = "Basic #{header_auth}"   # replace "Basic" with "Bearer" in case of access token

response = http.request(request)
response_headers =  response.instance_variable_get("@header")
response_data    = response.read_body

sp_signature     = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
# calculated signature functionality cannot be implement in case of access token
calculated_signature = Digest::SHA256.hexdigest response_data + SECRET_KEY

if sp_signature == calculated_signature
   puts response_data
else
   puts "Invalid signature"
end

Sample Decline Reason Response

{
    "decline_reasons": [
        {
            "status_code": "SPDR01",
            "description": "Face could not be verified"
        },
        {
            "status_code": "SPDR02",
            "description": "Image of the face not found on the document"
        }
    ]
}

This end-point returns verification decline reasons with their status codes and descriptions.

Face Status Codes

Status Code Description
SPDR01 Face could not be verified
SPDR19 Face could not be detected in image, please upload image again with your face clearly visible
SPDR03 Image is altered or photoshopped
SPDR04 Copy of the image found on web
SPDR58 Face in the image is with wearing glasses
SPDR59 Face proof is from another screen
SPDR60 Face proof is taken from the web
SPDR61 More than one face in one image
SPDR62 Face proof is a screenshot
SPDR38 Face doesn't match the face image uploaded at the time of signup
SPDR39 Document doesn’t match the document uploaded at the time of signup
SPDR43 Camera is not accessible for verification

Document & Document Two Status Code

Status Code Description
SPDR02 Image of the face not found on the document
SPDR05 Names on both the documents do not match
SPDR06 Document originality could not be verified
SPDR07 Name on the document doesn't match
SPDR08 DOB on the document doesn't match
SPDR14 Age could not be verified
SPDR16 The expiry date of the document does not match the record, please upload a document with valid expiry date
SPDR10 Issue date on the document doesn't match
SPDR09 Date on the document doesn't match
SPDR11 Number on the document doesn't match
SPDR12 The issuing country of document is not supported, please upload a valid document
SPDR13 Document doesn't match the provided options
SPDR14 You are not eligible because you doesn't fall in the provided age range
SPDR15 Face on the document doesn't match with camera image
SPDR17 The document is expired, please upload a new document which is not expired
SPDR18 The uploaded image of the document is blur, please provide a clear photo of document
SPDR19 Face could not be detected in image, please upload image again with your face clearly visible
SPDR03 Image is altered or photoshopped
SPDR04 Copy of the image found on web
SPDR21 Proof and Additional Proof are of different documents
SPDR36 Both Documents do not belong to the same person
SPDR42 Front and backside images of the document did not match, please upload images of the same document
SPDR47 Document proof is a screenshot
SPDR48 Document proof is altered/edited
SPDR49 Document proof is paper based which is not accepted
SPDR50 Document proof is punched/broken
SPDR51 Document proof is from another screen
SPDR52 Hologram is missing on the document
SPDR53 Document proof is not fully displayed.
SPDR54 Document is blur
SPDR55 Information on the document proof is not visible
SPDR56 Information on the document is edited
SPDR57 Information on the document is hidden
SPDR67 Document should be from the provided country
SPDR68 Issue date does not match with the provided one
SPDR69 Expiry date does not match with the provided one
SPDR70 Submitted document is expired
SPDR71 Issue date on the document is not clearly visible
SPDR72 Expiry date on the document is not clearly visible
SPDR73 Date of Birth on the document does not match with the provided one
SPDR74 Date of Birth on the document is not clearly visible
SPDR75 Name on the document does not match with the provided one
SPDR76 Name on the document is not clearly visible
SPDR77 Document number does not match with the provided one
SPDR78 Document number is not clearly visible
SPDR79 Original document number could not be authenticated
SPDR63 Front and backside images are not of the same document
SPDR64 Proof and additional proof does not belong to the same person
SPDR65 Address proof and document proof does not match
SPDR66 Both documents should belong to the same person
SPDR39 Document doesn’t match the document uploaded at the time of signup
SPDR43 Camera is not accessible for verification
SPDR44 Gender could not be verified
SPDR45 Place of issue could not be verified
SPDR45 Place of issue could not be verified
SPDR86 E-document data does not match with provided document proof
SPDR87 Face on the E-document does not match with selfie
SPDR88 Uploaded document is Black and White
SPDR89 Uploaded image of the document is edited or cropped
SPDR90 Uploaded image is found on the internet
SPDR91 Document is laminated
SPDR92 Document is scanned or colored copy
SPDR93 Document is paper-based or laminated
SPDR94 Uploaded document is a test card
SPDR187 Nationality could not be verified.
SPDR190 The provided document is broken
SPDR193 The provided document is photocopy(color or black & white)
SPDR194 The provided document is edited.
SPDR197 The provided document is scanned
SPDR200 The provided document is punched
SPDR201 The provided document is cracked
SPDR202 The provided document is cropped
SPDR203 The provided document is handwritten
SPDR204 Document does not belong to GCC countries
SPDR205 Document type is not supported.
SPDR206 Document type is not allowed.
SPDR207 MRZ not detected on the document
SPDR208 The provided document is blank
SPDR209 Student card is not acceptable
SPDR210 Dual cards detected
SPDR211 The uploaded document is not supported.

Address Status Code

Status Code Description
SPDR02 Image of the face not found on the document
SPDR06 Document originality could not be verified
SPDR14 Age could not be verified
SPDR22 Name on the Address Document doesn't match
SPDR23 Address did not match the record, please provide a document with valid address.
SPDR24 Document type is different from the provided options
SPDR25 Country on the address document could not be verified
SPDR26 Addresses on the Identity Document and Utility Bill do not match
SPDR27 The address document is expired, please upload a document which is not expired
SPDR28 The uploaded image of the document is blur, please provide a clear photo of address document
SPDR13 Document doesn't match the provided options
SPDR30 Issue date on the address document doesn't match
SPDR03 Image is altered or photoshopped
SPDR04 Copy of the image found on web
SPDR21 Proof and Additional Proof are of different documents
SPDR31 Address proof and document proof are of different persons
SPDR42 Front and backside images of the document did not match, please upload images of the same document
SPDR47 Document proof is a screenshot
SPDR48 Document proof is altered/edited
SPDR49 Document proof is paper based which is not accepted
SPDR50 Document proof is punched/broken
SPDR51 Document proof is from another screen
SPDR52 Hologram is missing on the document
SPDR53 Document proof is not fully displayed.
SPDR54 Document is blur
SPDR55 Information on the document proof is not visible
SPDR56 Information on the document is edited
SPDR57 Information on the document is hidden
SPDR67 Document should be from the provided country
SPDR68 Issue date does not match with the provided one
SPDR69 Expiry date does not match with the provided one
SPDR70 Submitted document is expired
SPDR71 Issue date on the document is not clearly visible
SPDR72 Expiry date on the document is not clearly visible
SPDR73 Date of Birth on the document does not match with the provided one
SPDR74 Date of Birth on the document is not clearly visible
SPDR75 Name on the document does not match with the provided one
SPDR76 Name on the document is not clearly visible
SPDR77 Document number does not match with the provided one
SPDR78 Document number is not clearly visible
SPDR79 Original document number could not be authenticated
SPDR65 Address proof and document proof does not match
SPDR66 Both documents should belong to the same person
SPDR80 Address on the document does not match with the provided one
SPDR81 Address provided is invalid
SPDR82 Address on the document is not clearly visible
SPDR83 Address could not be validated
SPDR14 You are not eligible because you doesn't fall in the provided age range
SPDR43 Camera is not accessible for verification
SPDR46 Same ID Document can not be submitted as proof of address
SPDR88 Uploaded document is Black and White
SPDR89 Uploaded image of the document is edited or cropped
SPDR90 Uploaded image is found on the internet
SPDR91 Document is laminated
SPDR92 Document is scanned or colored copy
SPDR93 Document is paper-based or laminated
SPDR94 Uploaded document is a test card
SPDR112 Country on the address document could not verified
SPDR188 Bank Transfer Number could not be verified
SPDR189 Tax Identity Number could not be verified
SPDR190 The provided document is broken
SPDR193 The provided document is photocopy(color or black & white)
SPDR194 The provided document is edited.
SPDR197 The provided document is scanned
SPDR200 The provided document is punched
SPDR201 The provided document is cracked
SPDR202 The provided document is cropped
SPDR203 The provided document is handwritten
Status Code Description
SPDR02 Image of the face not found on the document
SPDR32 Consent note information is not correct, please upload a note with valid information
SPDR33 Consent type is different from provided options
SPDR03 Image is altered or photoshopped
SPDR04 Copy of the image found on web
SPDR43 Camera is not accessible for verification

Background Checks Status Code

Status Code Description
SPDR34 AML screening failed
SPDR160 AML screening failed. User found in Sanction lists
SPDR161 AML screening failed. User found in Warning lists
SPDR162 AML screening failed. User found in Fitness-Probity lists
SPDR163 AML screening failed. User found in PEP lists
SPDR164 AML screening failed. User found in Adverse-Media lists

AML For Businesses Status Code

Status Code Description
SPDR34 AML screening failed
SPDR182 AML screening failed. Business found in Sanction lists
SPDR183 AML screening failed. Business found in Warning lists
SPDR184 AML screening failed. Business found in Fitness-Probity lists
SPDR185 AML screening failed. Business found in PEP lists
SPDR186 AML screening failed. Business found in Adverse-Media lists

Phone Number Status Code

Note:
Verification is declined if a user enters the wrong code consecutively for five times.
If the user is unable to receive code then, user is provide with Code not received option if user clicks the “Code not received” option the verification will be declined automatically (because either the phone number was wrong or unreachable).

Status Code Description
SPDR35 Your phone number did not match the record, please provide a valid phone number
SPDR84 Phone number not verified because end-user entered the wrong code multiple times
SPDR85 Phone number not verified because the provided number was unreachable

Supported Countries

Shufti Pro provides support for all countries. The country code for each country of the world is stated below. Make sure to use them accordingly.

Country Name Country Code
1. Afghanistan AF
2. Aland Islands AX
3. Albania AL
4. Algeria DZ
5. American Samoa AS
6. Andorra AD
7. Angola AO
8. Anguilla AI
9. Antarctica AQ
10. Antigua and Barbuda AG
11. Argentina AR
12. Armenia AM
13. Aruba AW
14. Australia AU
15. Austria AT
16. Azerbaijan AZ
17. Bahamas BS
18. Bahrain BH
19. Bangladesh BD
20. Barbados BB
21. Belarus BY
22. Belgium BE
23. Belize BZ
24. Benin BJ
25. Bermuda BM
26. Bhutan BT
27. Bolivia BO
28. Bosnia and Herzegovina BA
29. Botswana BW
30. Bouvet Island BV
31. Brazil BR
32. British Indian Ocean Territory IO
33. Brunei BN
34. Bulgaria BG
35. Burkina Faso BF
36. Burma (Myanmar) MM
37. Burundi BI
38. Cambodia KH
39. Cameroon CM
40. Canada CA
41. Cape Verde CV
42. Cayman Islands KY
43. Central African Republic CF
44. Chad TD
45. Chile CL
46. China CN
47. Christmas Island CX
48. Cocos (Keeling) Islands CC
49. Colombia CO
50. Comoros KM
51. Congo, Dem. Republic CD
52. Congo, Republic CG
53. Cook Islands CK
54. Costa Rica CR
55. Croatia HR
56. Cuba CU
57. Cyprus CY
58. Czech Republic CZ
59. Denmark DK
60. Djibouti DJ
61. Dominica DM
62. Dominican Republic DO
63. East Timor TL
64. Ecuador EC
65. Egypt EG
66. El Salvador SV
67. Equatorial Guinea GQ
68. Eritrea ER
69. Estonia EE
70. Ethiopia ET
71. Falkland Islands FK
72. Faroe Islands FO
73. Fiji FJ
74. Finland FI
75. France FR
76. French Guiana GF
77. French Polynesia PF
78. French Southern Territories TF
79. Gabon GA
80. Gambia GM
81. Georgia GE
82. Germany DE
83. Ghana GH
84. Gibraltar GI
85. Greece GR
86. Greenland GL
87. Grenada GD
88. Guadeloupe GP
89. Guam GU
90. Guatemala GT
91. Guernsey GG
92. Guinea GN
93. Guinea-Bissau GW
94. Guyana GY
95. Haiti HT
96. Heard Island and McDonald Islands HM
97. Honduras HN
98. HongKong HK
99. Hungary HU
100. Iceland IS
101. India IN
102. Indonesia ID
103. Iran IR
104. Iraq IQ
105. Ireland IE
106. Israel IL
107. Italy IT
108. Ivory Coast CI
109. Jamaica JM
110. Japan JP
111. Jersey JE
112. Jordan JO
113. Kazakhstan KZ
114. Kenya KE
115. Kiribati KI
116. Korea, Dem. Republic of KP
117. Kuwait KW
118. Kyrgyzstan KG
119. Laos LA
120. Latvia LV
121. Lebanon LB
122. Lesotho LS
123. Liberia LR
124. Libya LY
125. Liechtenstein LI
126. Lithuania LT
127. Luxemburg LU
128. Macau MO
129. Macedonia MK
130. Madagascar MG
131. Malawi MW
132. Malaysia MY
133. Maldives MV
134. Mali ML
135. Malta MT
136. Man Island IM
137. Marshall Islands MH
138. Martinique MQ
139. Mauritania MR
140. Mauritius MU
141. Mayotte YT
142. Mexico MX
143. Micronesia FM
144. Moldova MD
145. Monaco MC
146. Mongolia MN
147. Montenegro ME
148. Montserrat MS
149. Morocco MA
150. Mozambique MZ
151. Namibia NA
152. Nauru NR
153. Nepal NP
154. Netherlands NL
155. Netherlands Antilles AN
156. New Caledonia NC
157. New Zealand NZ
158. Nicaragua NI
159. Niger NE
160. Nigeria NG
161. Niue NU
162. Norfolk Island NF
163. Northern Mariana Islands MP
164. Norway NO
165. Oman OM
166. Pakistan PK
167. Palau PW
168. Palestinian Territories PS
169. Panama PA
170. Papua New Guinea PG
171. Paraguay PY
172. Peru PE
173. Philippines PH
174. Pitcairn PN
175. Poland PL
176. Portugal PT
177. Puerto Rico PR
178. Qatar QA
179. Reunion Island RE
180. Romania RO
181. Russian Federation RU
182. Rwanda RW
183. Republic of Kosovo XK
184. Saint Barthelemy BL
185. Saint Kitts and Nevis KN
186. Saint Lucia LC
187. Saint Martin MF
188. Saint Pierre and Miquelon PM
189. Saint Vincent and the Grenadines VC
190. Samoa WS
191. San Marino SM
192. Saudi Arabia SA
193. Senegal SN
194. Serbia RS
195. Seychelles SC
196. Sierra Leone SL
197. Singapore SG
198. Slovakia SK
199. Slovenia SI
200. Solomon Islands SB
201. Somalia SO
202. South Africa ZA
203. South Georgia and the South Sandwich Islands GS
204. South Korea KR
205. Spain ES
206. Sri Lanka LK
207. Sudan SD
208. Suriname SR
209. Svalbard and Jan Mayen SJ
210. Swaziland SZ
211. Sweden SE
212. Switzerland CH
213. Syria SY
214. São Tomé and Príncipe ST
215. Taiwan TW
216. Tajikistan TJ
217. Tanzania TZ
218. Thailand TH
219. Togo TG
220. Tokelau TK
221. Tonga TO
222. Trinidad and Tobago TT
223. Tunisia TN
224. Turkey TR
225. Turkmenistan TM
226. Turks and Caicos Islands TC
227. Tuvalu TV
228. Uganda UG
229. Ukraine UA
230. United Arab Emirates AE
231. United Kingdom GB
232. United States US
233. United States Minor Outlying Islands UM
234. Uruguay UY
235. Uzbekistan UZ
236. Vanuatu VU
237. Vatican City State VA
238. Venezuela VE
239. Vietnam VN
240. Virgin Islands (British) VG
241. Virgin Islands (U.S.) VI
242. Wallis and Futuna WF
243. Western Sahara EH
244. Yemen YE
245. Zambia ZM
246. Zimbabwe ZW

Supported Languages

Shufti Pro offers worldwide language coverage. Use the appropriate language code from the list given below.

Languages Language Code
1. Afrikaans AF
2. Albanian SQ
3. Amharic AM
4. Arabic AR
5. Armenian HY
6. Azerbaijani AZ
7. Basque EU
8. Belarusian BE
9. Bengali BN
10. Bosnian BS
11. Bulgarian BG
12. Burmese MY
13. Catalan CA
14. Chichewa NY
15. Chinese ZH
16. Corsican CO
17. Croatian HR
18. Czech CS
19. Danish DA
20. Dutch NL
21. English EN
22. Esperanto EO
23. Estonian ET
24. Filipino TL
25. Finnish FI
26. French FR
27. Frisian FY
28. Galician GL
29. Georgian KA
30. German DE
31. Greek (modern) EL
32. Gujarati GU
33. Haitian, Haitian Creole HT
34. Hausa HA
35. Hebrew (modern) HE
36. Hindi HI
37. Hungarian HU
38. Indonesian ID
39. Irish GA
40. Igbo IG
41. Icelandic IS
42. Italian IT
43. Japanese JA
44. Javanese JV
45. Kannada KN
46. Kazakh KK
47. Khmer KM
48. Kirghiz, Kyrgyz KY
49. Korean KO
50. Kurdish KU
51. Latin LA
52. Luxembourgish, Letzeburgesch LB
53. Lao LO
54. Lithuanian LT
55. Latvian LV
56. Macedonian MK
57. Malagasy MG
58. Malay MS
59. Malayalam ML
60. Maltese MT
61. Maori MI
62. Marathi MR
63. Mongolian MN
64. Nepali NE
65. Norwegian NO
66. Punjabi PA
67. Persian FA
68. Polish PL
69. Pashto PS
70. Portuguese PT
71. Romanian RO
72. Russian RU
73. Sindhi SD
74. Samoan SM
75. Serbian SR
76. Scottish Gaelic GD
77. Shona SN
78. Sinhala SI
79. Slovak SK
80. Slovenian SL
81. Somali SO
82. Sesotho ST
83. Spanish ES
84. Sundanese SU
85. Swahili SW
86. Swedish SV
87. Tamil TA
88. Telugu TE
89. Tajik TG
90. Thai TH
91. Turkish TR
92. Ukrainian UK
93. Urdu UR
94. Uzbek UZ
95. Vietnamese VI
96. Welsh CY
97. Xhosa XH
98. Yiddish YI
99. Yoruba YO
100. Zulu ZU

Jurisdiction Codes

Shufti Pro provides support for the following jurisdiction codes.

Jurisdiction Name Code
1. Abu Dhabi (UAE) ae_az
2. Alabama (US) us_al
3. Alaska (US) us_ak
4. Albania al
5. Arizona (US) us_az
6. Arkansas (US) us_ar
7. Aruba aw
8. Australia au
9. Bahamas bs
10. Bahrain bh
11. Bangladesh bd
12. Barbados bb
13. Belarus by
14. Belgium be
15. Belize bz
16. Bermuda bm
17. Bolivia bo
18. Brazil br
19. Bulgaria bg
20. California (US) us_ca
21. Cambodia kh
22. Canada ca
23. Colorado (US) us_co
24. Connecticut (US) us_ct
25. Croatia hr
26. Curaçao cw
27. Cyprus cy
28. Delaware (US) us_de
29. Denmark dk
30. District of Columbia (US) us_dc
31. Dominican Republic do
32. Dubai (UAE) ae_du
33. Finland fi
34. Florida (US) us_fl
35. France fr
36. French Guiana gf
37. Georgia (US) us_ga
38. Germany de
39. Gibraltar gi
40. Greece gr
41. Greenland gl
42. Guadeloupe gp
43. Guernsey gg
44. Hawaii (US) us_hi
45. Hong Kong hk
46. Iceland is
47. Idaho (US) us_id
48. India in
49. Indiana (US) us_in
50. Iowa (US) us_ia
51. Iran ir
52. Ireland ie
53. Isle of Man im
54. Israel il
55. Jamaica jm
56. Japan jp
57. Jersey je
58. Kansas (US) us_ks
59. Kentucky (US) us_ky
60. Latvia lv
61. Liechtenstein li
62. Louisiana (US) us_la
63. Luxembourg lu
64. Maine (US) us_me
65. Malaysia my
66. Malta mt
67. Martinique mq
68. Maryland (US) us_md
69. Massachusetts (US) us_ma
70. Mauritius mu
71. Mayotte yt
72. Mexico mx
73. Michigan (US) us_mi
74. Minnesota (US) us_mn
75. Mississippi (US) us_ms
76. Missouri (US) us_mo
77. Moldova md
78. Montana (US) us_mt
79. Montenegro me
80. Myanmar mm
81. Nebraska (US) us_ne
82. Netherlands nl
83. Nevada (US) us_nv
84. New Brunswick (Canada) ca_nb
85. New Hampshire (US) us_nh
86. New Jersey (US) us_nj
87. New Mexico (US) us_nm
88. New York (US) us_ny
89. New Zealand nz
90. Newfoundland and Labrador (Canada) ca_nl
91. North Carolina (US) us_nc
92. North Dakota us_nd
93. Norway no
94. Nova Scotia (Canada) ca_ns
95. Ohio (US) us_oh
96. Oklahoma (US) us_ok
97. Oregon (US) us_or
98. Pakistan pk
99. Panama pa
100. Pennsylvania (US) us_pa
101. Poland pl
102. Prince Edward Island (Canada) ca_pe
103. Puerto Rico pr
104. Quebec (Canada) ca_qc
105. Rhode Island (US) us_ri
106. Romania ro
107. Rwanda rw
108. Réunion re
109. Saint Barthélemy bl
110. Saint Martin (French part) mf
111. Saint Pierre and Miquelon pm
112. Singapore sg
113. Slovakia sk
114. Slovenia si
115. South Africa za
116. South Carolina (US) us_sc
117. South Dakota (US) us_sd
118. Spain es
119. Sweden se
120. Switzerland ch
121. Tajikistan tj
122. Tanzania tz
123. Tennessee (US) us_tn
124. Texas us_tx
125. Thailand th
126. Tonga to
127. Tunisia tn
128. Uganda ug
129. Ukraine ua
130. United Kingdom gb
131. Utah (US) us_ut
132. Vanuatu vu
133. Vermont (US) us_vt
134. Viet Nam vn
135. Virginia (US) us_va
136. Washington (US) us_wa
137. West Virginia (US) us_wv
138. Wisconsin (US) us_wi
139. Wyoming (US) us_wy

Supported Browsers and Devices

In case of on-site verification, a verify iframe is shown to users. This iframe is supported on the following list of browsers.

Browsers Minimum Version/SDK
1. Chrome (Recommended) 65
2. Firefox (Recommended) 58
3. Safari 8
4. Opera 52
5. Internet Explorer 11
6. Edge 16

Here a list of supported operating systems on mobile devices.

Mobile OS Minimum Version/SDK
1. Android 6.0 (Marshmallow)
2. iOS 10

Test ID Samples

The below-provided Test ID Samples for different services can be used either during the testing or the integration process. This facilitates the technical teams to use dummy documents in order to test out the requests, responses, callbacks, etc without having them upload/provide their real identity documents.



Face Test ID Samples

Document/Document Two Test ID Samples








Address Document Test ID Samples



















Revision History

Date Description
14 Sep 2022 Added new Parameter check_duplicate_request inside face service in verification request.
02 Nov 2021 Added new Parameter manual_review in verification request.
21 Oct 2021 Added new Parameter show_ocr_form in document, document_two and address service.
18 Oct 2021 Introduced new service Age Verification.
13 Oct 2021 Added New Supported types property_tax, lease_agreement, insurance_card, credit_card_statement, insurance_policy, e_commerce_receipt, bank_letter_receipt, birth_certificate, salary_slip, permanent_residence_permit and any for Address service.
28 Sep 2021 Added New Parameter in verification_instructions object for document, document_two and address service.
24 Sep 2021 Added declined_codes in Background Checks & AML For Businesses. Note: This Feature is currently available for trial accounts and will be available for production accounts from "27 Sep 2021"
13 July 2021 Updated php sample code.
03 June 2021 dob key in Background Checks Service made optional.
29 Mar 2021 face_match_confidence key is now available.
24 Mar 2021 Added new endpoint to get all verification decline reasons.
11 Mar 2021 Added new key face_match_confidence under the verification_data object in verification response. Note: This Key will be available from "29 MARCH 2021"
01 Jan 2021 Introduced new type Others in Gender.
11 Dec 2020 Introduced new service OCR For Business.
20 Nov 2020 Added New key services_declined_codes in Verification Response.
04 Nov 2020 Updated declined reasons.
04 Nov 2020 Added New Parameter verification_instructions in document, document_two and address service.
21 Sep 2020 Added allow_retry in verification request.
18 Sep 2020 Added allow_na_ocr_inputs in verification request.
08 Sep 2020 Added ttl in verification request.
20 Jul 2020 consent service sample object and test IDs updated.
14 Jul 2020 callback_url parameter made optional.
16 June 2020 Added New Supported type cpr_smart_card_reader_copy for Address service.
15 June 2020 Added full_name key to name object for background checks service.
11 June 2020 Added decline_on_single_step in verification request.
10 June 2020 Added gender key for document and document_two service.
19 May 2020 Added subscription plan details to account info Response.
08 May 2020 Added Country Key to Status Responses.
05 May 2020 Increased max length of AML for Business Name from 64 to 255.
16 Apr 2020 business_incorporation_date in AML for Businesses service made optional.
08 Apr 2020 Added video KYC documentation.
07 Apr 2020 Added backside_proof_required parameter.
27 Mar 2020 Updated Api urls.
26 Mar 2020 Added Api flow charts.
04 Mar 2020 Temporary access token introduced.
31 Dec 2019 Added allow_online in verification request.
31 Dec 2019 Biometric SDK documentation added.
24 Dec 2019 Added "fetch_enhanced_data" key from Enhanced data extraction for document and document_two service.
24 Dec 2019 Removed "allowed_offline" key from address service request object.
24 Dec 2019 Updated declined reasons.
25 Nov 2019 Added verification_video in status response end-point, inside proof key. Returned only if on-site video is recorded.
25 Nov 2019 Added KYC Request Instructions for onsite and offisite verification
18 Nov 2019 HTTP status code updated.
14 Nov 2019 Request status response sample updated.
11 Nov 2019 updated KYB request response
31 Oct 2019 Introduced new service Know Your business (KYB).
24 Oct 2019 Introduced new service for Businesses AML checks(AML for Businesses).
10 Oct 2019 Updated Onsite verification javascript code.
09 Oct 2019 Added the show_feedback_form in verification request.
24 Sep 2019 Added declined_codes in verification response, for all accounts.
11 Sep 2019 Old declined reason added in appendix.
09 Sep 2019 Added declined_codes in verification response. Note: This Feature is currently available for trial accounts and will be available for production accounts from "24 Sep 2019"
09 Sep 2019 Declined reasons description updated and added status code for each reason.
27 Aug 2019 Added full_name key to name object.
20 Jul 2019 Updated declined reasons.
20 Jul 2019 Added request time out time.
16 Jul 2019 Added Ongoing in Background checks.
15 Jul 2019 Added info object key in responses date has been extended to 18 Jul 2019.
04 Jul 2019 Added info object key in responses just in API documentation. (Shufti Pro API will send this object in response from 15 Jul 2019 )
04 Jul 2019 Added declined reasons for document, document two and address services.
02 Jul 2019 Added Rate Limiting for requests.
12 June 2019 Added Document Two Service for verification.
24 May 2019 Update declined reason.
22 May 2019 Added with_face key in consent service.
03 May 2019 Added Declined Reasons of verificatiton Request.
16 Apr 2019 Added Fuzzy match in Background checks.
09 Apr 2019 Added a new endpoint /api/account/info/ to get account info.
05 Apr 2019 country key updated.
11 Mar 2019 1. Added new params verification_data, verification_result and declined_reason in verification status endpoint.
2. Added a new event request.received
07 Mar 2019 Added issue_date key in address service request parameters.
20 Feb 2019 Added selected_type key in address, document, consent services webhook/callback response.
19 Feb 2019 1. Added show_consent and show_privacy_policy parameters in verification request.
2. Added address_fuzzy_match parameter in address service.
3. Added allow_offline parameter in face, document, address and consent services.
18 Feb 2019 Signature key added into SP Http, Callback headers for signature validation.
28 Jan 2019 1. Added a new endpoint /api/delete to delete a request data.
2. Added a new event request.deleted which is returned whenever a request is deleted.
3. Status response now returns proofs also.
4. Added show_results key in request which allows end-users to see verification results.
24 Jan 2019 Added a new callback with event verification.status.changed. It is sent to clients whenever a verification status is updated.
21 Dec 2018 Corrected the get status request url.
20 Dec 2018 Corrected verification.cancelled event name from events listing.
06 Dec 2018 Minimum characters limit is set to 1 for first, middle and last name.
29 Nov 2018 Updated POSTMAN collection link, removed format key and added supported_types key for consent service in POSTMAN collection.
26 Nov 2018 Added allow_offline key in request parameters.
29 Oct 2018 Allowed PDF documents as proofs in image_only and any verification modes.
29 Oct 2018 Changed format key to Supported_types in consent Service.
22 Oct 2018 Added declined reason key in response.
17 Oct 2018 Updated Test IDs for demo/test verifications.
09 Oct 2018 1. Last name field made optional in all name objects.
2. Added signature in response headers to validate the source of responses.