Onsite Integration
With On-site verification, Shufti Pro directly interacts with the end-user, managing data collection to facilitate document signing. Document status updates are exclusively communicated to the Shufti Pro customer via the dedicated Shufti Pro Back Office.
The e-Signature service is available for Onsite only and before passing the esign object in the API, please make sure that you have copied the correct template_hash_id from the e-Signature Templates listed in Products Section.
Parameters and Descriptions
The parameters mentioned below apply to onsite verifications specifically for e-Signature payloads. Universal parameters integral to every verification request processed by Shufti Pro are listed in the General Parameters section.
Parameters | Description |
---|---|
contract_title | Required: Yes Type: string Maximum: 60 Example: (contract_title: Partnership Agreement) This parameter allows you to specify a suitable title for the e-Signature contract. |
template_hash_id | Required: Yes Type: string Example: (template_hash_id: 1234abcd9iun) The Template Hash Id is a unique identifier assigned to each template within the e-Signature service. This parameter is used to reference the template for execution. |
recipients_data | Required: Yes Type: array Maximum: 15 This parameter is an array containing an objects of recipient information. Each recipient object within the array specifies details about a single signer for the e-Signature contract. These recipient objects typically include: Role, Name, Email and Action. |
role | Required: No Type: string Maximum: 25 Example: (role: Director) This optional parameter allows you to specify the recipient's role within the e-Signature contract. |
name | Required: Yes Type: string Maximum: 50 Example: (name: John Doe) This parameter allows you to specify the recipient's full name for the e-Signature contract. |
Required: Yes Type: string Maximum: 70 Allowed Characters: Kindly ensure that email addresses adhere to the standard conventions, including valid characters such as letters, numbers, and symbols like '@' and '.'. Example: (email: [email protected]) This parameter specifies the email address of the recipient who will be signing the e-Signature contract. | |
action | Required: Yes Type: string Value: needs_to_sign or receives_a_copy This parameter allows you to specify a specific action for the recipient within the e-Signature contract. The action would be either needs_to_sign or receives_a_copy. Needs to Sign: This action indicates that the recipient needs to electronically sign the document. Receives a Copy: This action indicates that the recipient should only receive a copy of the signed document |
expiry_days | Required: Yes Type: number Minimum: 1 (day) Maximum: 999 (days) Default: 7 (days) This parameter allows you to specify the number of days for which the e-Signature request will remain valid for recipients. After this period, the signing link will expire, and recipients will no longer be able to access and sign the document. |
- Http
- Javascript
- PHP
- Python
- Ruby
- Java
- C#
- Go
//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" : "[email protected]",
"country" : "GB",
"language" : "EN",
"redirect_url": "http://www.example.com",
"ttl" : 60,
"verification_mode" : "any",
"esign" : {
"contract_title": "contract_title",
"template_hash_id": "12345678abcdefg12345678",
"recipients_data": [
{
"role": "role_title",
"name": "John Doe",
"email": "[email protected]",
"action": "needs_to_sign"
},
{
"role": "role_title_2",
"name": "John Doe",
"email": "[email protected]",
"action": "needs_to_sign"
},
{
"role": "role_title_3",
"name": "John Doe",
"email": "[email protected]",
"action": "receives_a_copy"
}
],
"expiry_days": 7,
}
}
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,
}
payload['esign']: {
contract_title: 'contract_title',
template_hash_id: '12345678abcdefg12345678',
recipients_data: [
{
role: 'role_title',
name: 'John Doe',
email: '[email protected]',
action: 'needs_to_sign',
},
{
role: 'role_title_2',
name: 'John Doe',
email: '[email protected]',
action: 'needs_to_sign',
},
{
role: 'role_title_3',
name: 'John Doe',
email: '[email protected]',
action: 'receives_a_copy',
},
],
"expiry_days": 7,
},
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) {
if (data.event && data.event === 'request.pending') {
createIframe(data.verification_url)
}
});
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);
}
<?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),
'country' => 'GB',
'language' => 'EN',
'email' => '[email protected]',
'callback_url' => 'https://yourdomain.com/profile/notifyCallback',
'verification_mode' => 'any',
'ttl' => 60,
];
$verification_request['esign'] =[
'contract_title' => 'contract_title',
'template_hash_id' => '12345678abcdefg12345678',
'recipients_data' => array(
array(
'role' => 'role_title',
'name' => 'John Doe',
'email' => '[email protected]',
'action' => 'needs_to_sign',
),
array(
'role' => 'role_title_2',
'name' => 'John Doe',
'email' => '[email protected]',
'action' => 'needs_to_sign',
),
array(
'role' => 'role_title_3',
'name' => 'John Doe',
'email' => '[email protected]',
'action' => 'receives_a_copy',
),
),
"expiry_days": 7,
];
$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;
$headers = ['Content-Type: application/json'];
$post_data = json_encode($verification_request);
$response = send_curl($url, $post_data, $headers, $auth);
$response_data = $response['body'];
$exploded = explode("\n", $response['headers']);
$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;
}
}
$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){
$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 ['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/'
client_id = 'YOUR-CLIENT-ID'
secret_key = 'YOUR-SECRET-KEY'
verification_request = {
'reference' : 'ref-{}{}'.format(randint(1000, 9999), randint(1000, 9999)),
'country' : 'GB',
'language' : 'EN',
'email' : '[email protected]',
'callback_url' : 'https://yourdomain.com/profile/notifyCallback',
'verification_mode' : 'any',
'ttl' : 60,
}
verification_request['esign'] = {
"contract_title": "contract_title",
"template_hash_id": "12345678abcdefg12345678",
"recipients_data": [
{
"role": "role_title",
"name": "John Doe",
"email": "[email protected]",
"action": "needs_to_sign"
},
{
"role": "role_title_2",
"name": "John Doe",
"email": "[email protected]",
"action": "needs_to_sign"
},
{
"role": "role_title_3",
"name": "John Doe",
"email": "[email protected]",
"action": "receives_a_copy"
},
"expiry_days": 7,
]
}
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))
calculated_signature = hashlib.sha256('{}{}'.format(response.content.decode(), secret_key).encode()).hexdigest()
sp_signature = response.headers.get('Signature','')
json_response = json.loads(response.content)
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))
require 'uri'
require 'net/http'
require 'base64'
require 'json'
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: "[email protected]",
country: "GB",
language: "EN",
redirect_url: "http://www.example.com",
verification_mode: "any",
ttl: 60,
esign: {
contract_title: 'contract_title',
template_hash_id: '12345678abcdefg12345678',
recipients_data: [
{
role: 'role_title',
name: 'John Doe',
email: '[email protected]',
action: 'needs_to_sign',
},
{
role: 'role_title_2',
name: 'John Doe',
email: '[email protected]',
action: 'needs_to_sign',
},
{
role: 'role_title_3',
name: 'John Doe',
email: '[email protected]',
action: 'receives_a_copy',
},
],
"expiry_days": 7,
},
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)
response_headers = response.instance_variable_get("@header")
response_data = response.read_body
sp_signature = !(response_headers['signature'].nil?) ? response_headers['signature'].join(',') : ""
calculated_signature = Digest::SHA256.hexdigest response_data + (Digest::SHA256.hexdigest SECRET_KEY)
if sp_signature == calculated_signature
puts response_data
else
puts "Invalid signature"
end
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.net.ssl.HttpsURLConnection;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.shuftipro.com/";
String CLIENT_ID = "CLIENT_ID";
String SECRET_KEY = "SECRET_KEY";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
String basicAuth = "Basic " + Base64.getEncoder().encodeToString((CLIENT_ID + ":" + SECRET_KEY).getBytes(StandardCharsets.UTF_8));
con.setRequestProperty("Authorization", basicAuth);
String requestBody = "{" +
"\"reference\": \"1234567\"," +
"\"callback_url\": \"http://www.example.com/\"," +
"\"email\": \"[email protected]\"," +
"\"country\": \"GB\"," +
"\"language\": \"EN\"," +
"\"redirect_url\": \"http://www.example.com\"," +
"\"ttl\": 60," +
"\"verification_mode\": \"any\"," +
"\"esign\": {" +
"\"contract_title\": \"contract_title\"," +
"\"template_hash_id\": \"12345678abcdefg12345678\"," +
"\"recipients_data\": [" +
"{" +
"\"role\": \"role_title\"," +
"\"name\": \"John Doe\"," +
"\"email\": \"[email protected]\"," +
"\"action\": \"needs_to_sign\"" +
"}," +
"{" +
"\"role\": \"role_title_2\"," +
"\"name\": \"John Doe\"," +
"\"email\": \"[email protected]\"," +
"\"action\": \"needs_to_sign\"" +
"}," +
"{" +
"\"role\": \"role_title_3\"," +
"\"name\": \"John Doe\"," +
"\"email\": \"[email protected]\"," +
"\"action\": \"receives_a_copy\"" +
"}" +
"]" +
"expiry_days": 7, +
"}" +
"}";
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(payload);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Payload : " + payload);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
System.out.println(in.toString());
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
}
}
var client = new RestClient("https://api.shuftipro.com");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw==");
var body =
{
""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"",
""esign"": {
""contract_title"": ""contract_title"",
""template_hash_id"": ""12345678abcdefg12345678"",
""recipients_data"": [
{
""role"": ""role_title"",
""name"": ""John Doe"",
""email"": ""john.doe@email.com"",
""action"": ""needs_to_sign""
},
{
""role"": ""role_title_2"",
""name"": ""John Doe"",
""email"": ""john.doe@email.com"",
""action"": ""needs_to_sign""
},
{
""role"": ""role_title_3"",
""name"": ""John Doe"",
""email"": ""john.doe@email.com"",
""action"": ""receives_a_copy""
}
],
""expiry_days"": 7
}
}";
request.AddParameter("application/json", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.shuftipro.com"
method := "POST"
payload := strings.NewReader(`{
"reference": "1234567",
"callback_url": "http://www.example.com/",
"email": "[email protected]",
"country": "GB",
"language": "EN",
"redirect_url": "http://www.example.com",
"ttl": 60,
"verification_mode": "any",
"esign": {
"contract_title": "contract_title",
"template_hash_id": "12345678abcdefg12345678",
"recipients_data": [
{
"role": "role_title",
"name": "John Doe",
"email": "[email protected]",
"action": "needs_to_sign"
},
{
"role": "role_title_2",
"name": "John Doe",
"email": "[email protected]",
"action": "needs_to_sign"
},
{
"role": "role_title_3",
"name": "John Doe",
"email": "[email protected]",
"action": "receives_a_copy"
}
],
"expiry_days": 7,
}
}`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Basic NmI4NmIyNzNmZjM0ZmNlMTlkNmI4WJRTUxINTJHUw==")
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}
e-Signature Single Recipient Sample Object
{
"esign": {
"contract_title": "unique_title",
"template_hash_id": "string_hashed_id",
"recipients_data": [
{
"role": "admin",
"action": "needs_to_sign",
"both": false,
"name": "John Doe",
"email": "[email protected]"
}
],
"expiry_days": 7,
}
}
e-Signature Multiple Recipients Sample Object
{
"esign": {
"contract_title": "unique_title",
"template_hash_id": "string_hashed_id",
"recipients_data": [
{
"role": "admin",
"action": "needs_to_sign",
"both": false,
"name": "John Doe",
"email": "[email protected]"
},
{
"role": "employee",
"action": "needs_to_sign",
"both": false,
"name": "John Doe",
"email": "[email protected]"
},
{
"role": "HR",
"action": "receives_a_copy",
"both": false,
"name": "John Doe",
"email": "[email protected]"
}
],
"expiry_days": 7,
}
}
e-Signature with Signer IDV Sample Object
{
"esign": {
"contract_title": "unique_title",
"template_hash_id": "string_hashed_id",
"recipients_data": [
{
"role": "admin",
"action": "needs_to_sign",
"both": false,
"name": "John Doe",
"email": "[email protected]"
},
{
"role": "HR",
"action": "receives_a_copy",
"both": false,
"name": "John Doe",
"email": "[email protected]"
}
],
"expiry_days": 7,
},
"face": {
"proof": "",
"check_duplicate_request": 0
},
"document": {
"proof": "",
"additional_proof": "",
"supported_types": ["id_card", "driving_license", "passport"],
"name": {
"first_name": "",
"last_name": ""
},
"dob": "",
"age": "",
"issue_date": "",
"expiry_date": "",
"document_number": "",
"allow_offline": "1",
"fetch_enhanced_data": "1",
"backside_proof_required": "0",
"verification_mode": "any",
"gender": ""
},
"phone": {
"phone_number": "",
"random_code": null,
"text": "Hi, Your code for verification is"
},
"background_checks": {
"name": {
"fuzzy_match": "1"
},
"dob": "",
"ongoing": "0",
"filters": [
"sanction",
"warning",
"fitness-probity",
"pep",
"pep-class-1",
"pep-class-2",
"pep-class-3",
"pep-class-4"
]
}
}
You can only use Face, Document, 2FA, and Background Screening services for identity verification with e-Signature, either separately or in combination.