NAV Navbar
json csharp shell ruby python javascript swift

Introduction

Welcome to the Veriff API documentation

Getting started with Veriff

Signing up

To sign up to use or even test our service, please contact our Sales team at sales@veriff.com. We'll introduce our service to you and help find the best product fit.

Logging in

An e-mail with instructions on how to log in has been sent to you when your account was created. Veriff’s environment can be accessed by going to https://office.veriff.me.

We use two factor authentication for logins. You will need to download and install the Google Authenticator app on your mobile device. Please find it in the Apple App Store Apple App Store or in the Google Play Store

Once you have set up your password, you will be presented with a QR code to set up the Authenticator application. Open the app, select the "+" icon and scan the QR code on the screen. Use the generated PIN-code to log in.

New users for your colleagues can be created by an administrative account in https://office.veriff.me/users -> New User

Please keep in mind that a unique PIN-code will need to be entered each time when logging in.

Testing the verification flow

To try out the end-user facing verification flow, simply navigate to Management -> Vendor -> Try Veriff. This will start the verification flow in your browser. To review the submitted verification and its results, go to https://office.veriff.me/filters and View the individual verification sessions. Our mobile applications can be tested by downloading the demo versions: iOS / Android

How to find your API keys

Your API keys are stored in the Veriff back office, and can be found by logging in to Veriff Back Office

Choose Management in the sidebar, then Vendor, as follows: ACT12

Your initial (test) API Key and API Secret are to be used for development and testing against the test environment.

Multiple sets of API keys (for different platforms, environments or business rules) can be created upon request.

For live use, Veriff will create the live API keys once the development is completed and integration process has been finalized.

Generating sessions for KYC with Veriff

Generating sessions manually

If you have managed to set up your account and logged in into our back office then you can generate a session:

You can see all the completed sessions from the menu “Dashboard”

Generating sessions in code

{
    "verification": {
        "callback": "https://this.is.your.redirect.url",
        "person": {
            "firstName": "John",
            "lastName": "Smith"
        },
        "lang": "en",
        "features": ["selfid"],
        "timestamp": "2016-05-19T08:30:25.597Z"
    }
}

The simplest way to get a KYC link for your user on the web, is to make a simple JSON object containing the user's name and the redirect(callback) URL to which the user will be sent after they complete KYC. Then use HTTP POST to send the object to https://api.veriff.me/v1/sessions, with Content-Type application/json and the X-AUTH-CLIENT header containing your API Key.

{
    "status": "success",
    "verification":{
        "id":"f04bdb47-d3be-4b28-b028-............",
        "url": "https://magic.veriff.me/v/sample-url.................",
        "sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJh............",
        "baseUrl": "https://magic.veriff.me"
    }
}

In response, we give you a JSON session ID and a URL, as follows:

The URL of the KYC session is where you should redirect your user in your web front end.

The session ID should be saved on your end - you can tie back the webhook responses to your customer record that way.

Once the end user completes the KYC, they will be redirected back to the callback URL. If you do not specify it for each session call, then there is a default configured in your account settings. This "callback" could be to a "thank you" or waiting page on your side.

To be clear, the callback does not contain any decision or verification information yet. After the KYC process completes in the background, we notify your webhook endpoint (also configured in your account settings), or if you have not automated decisions yet, then you can look up the result by logging in to https://office.veriff.me and checking the Dashboard.

The full API for starting a KYC session with Veriff is documented here in the API: #sessions

Generating the X-SIGNATURE header

    "verification": {
        "person": {
            "firstName": "John",
            "lastName": "Smith"
        },
        "features": ["selfid"],
        "timestamp": "2018-10-15T08:30:25.597Z"
    }
}

The X-SIGNATURE header guarantees to us, that API calls are initiated by you. It is based on the shared secret (API secret) that is known only by you and by Veriff.

The X-SIGNATURE is a SHA-256 hex encoded hash of the concatenation of the request body and your API secret.

To generate the X-SIGNATURE header, please:

For example, if the request object is

'{"verification":{"person":{"firstName":"John","lastName":"Smith"},"features":["selfid"],"timestamp":"2018-10-15T08:30:25.597Z"}}'

Next, the serialized JSON payload of the above object will look something like the following string

'{"verification":{"person":{"firstName":"Joh...........}}aeebd8dc-f646-4bc2.....etc'

Then, you will need to concatenate the text of the serialized payload and the text of the API secret, so it will look something like

Now you will need to calculate a SHA256 hash and hex encode it, as the description of that calculation is in the API spec at #sessions

This process depends on the language you use.

Using JavaScript / ECMA

To view the code sample select the language at the top-right

const payload = JSON.stringify(verification);
const signature = crypto.createHash('sha256');
signature.update(new Buffer(payload, 'utf8'));
signature.update(new Buffer(secret, 'utf8'));
return signature.digest('hex');

Using C# / .Net

To view the code sample select the language at the top-right

string hashString;
using (var sha256 = SHA256Managed.Create())
{
    var hash = sha256.ComputeHash(Encoding.Default.GetBytes(payloadPlusSecret));
    hashString = ToHex(hash, false);
}

Using Veriff in an iFrame

To view the code sample select the language at the top-right

var vf = document.createElement('iframe');
vf.src = response.verification.url; /* URL here */
vf.allow = 'microphone; camera';
vf.width = 1000;
vf.height = 650;
document.body.appendChild(iframe);

You can use Veriff in an iFrame. It should fit in a 1000px x 650px frame. This is an example for creating the iframe with the session URL:

/* addEventListener support for IE8 */
function bindEvent(element, eventName, eventHandler) {
  if (element.addEventListener) {
    element.addEventListener(eventName, eventHandler, false);
  } else if (element.attachEvent) {
    element.attachEvent('on' + eventName, eventHandler);
  }
}

/* Listen to message from child window */
bindEvent(window, 'message', function (e) {
  if (e.data && e.data.status && e.data.status === 'finished') {
    /* do whatever */
    document.getElementById('iframe').remove();
  }
});

At the end of the verification, Veriff will send an event to the parent window using JavaScript postMessage. You could use something as follows to catch the event and proceed:

Veriff JS SDK

Veriff JS SDK, is a simple and customisable library which helps to integrate with Veriff Online Identity solution.

Install

Include as a script tag:

<script src='https://cdn.veriff.me/sdk/js/veriff.min.js'></script>

add the CSS styles:

<link rel='stylesheet' href='https://cdn.veriff.me/sdk/js/styles.css'>

or install it via a package manager, styles are added inline

$ npm install --save @veriff/js-sdk

// CommonJS var Veriff = require('@veriff/js-sdk');

// ES6 style import import Veriff from '@veriff/js-sdk';

Usage

Veriff JS SDK requires one parent element in HTML:

<div id='veriff-root'></div>

In order to initialize the library, API Key, parentId and onSession callback function is required.

var veriff = Veriff({ env: 'production', // or 'staging' apiKey: 'API_KEY', parentId: 'veriff-root', onSession: function(err, response) { // received the response, verification can be started now } }); veriff.mount();

By default the following form will be rendered:

JSSDKSAMPLE

onSession function is executed after the response is received from the API, response body contains a verification object with following schema:

{ "status": "success", "verification": { "id": "UUID V4 Identifying the verification", "url": "full url to which a person should be redirected in order to proceed with verification flow", "host": "hostname", "status": "status of the verification", "sessionToken": "JWT encoded verification token" } } In case the Given name / Last name or both are known, they can be passed to the SDK, therefore text input fields will not be rendered.

veriff.setParams({ person: { givenName: 'Foo', lastName: 'Bar', idNumber: 12345 } }); additionally the input labels and button text value can be customised.

veriff.mount({ formLabel: { givenName: 'First name', lastName: 'Family name', idNumber: 'Id' }, submitBtnText: 'Veriff Me' loadingText: 'Please wait...' });

API upload

There are a few scenarios where you may not wish to use Veriff's native SDK or Veriff's web interface to verify your customers. For example:

In those cases, you can do the whole process using our API, according to the documentation, and not show any Veriff front end to your customers, or not expect customers to be present for the verification.

Here are the steps you should do to use the API for upload.

Create a new verification session

Create a new verification session using POST request to #sessions

The goal here is to create a new object (a verification session) that contains the one verification (referred to as 'verification', nested inside the session object in the response).

If you wish to restrict the accepted document to be the one you have on file, you can also send the document type, country, and number along with the session. Document type can be one of [‘PASSPORT’, ‘ID_CARD’, ‘RESIDENCE_PERMIT’, ‘DRIVERS_LICENSE'].

Documentation: #sessions

Send photos

Send photos (face, document front, document back, etc) by uploading all the pictures one by one using POST request to ‘/media’

The goal here is to upload the required photos and associate them with the verification created in step 1.

Documentation: /sessions/{sessionId} /media (POST)

Submit session for review

Submit the verification session using PATCH request to ‘/sessions/:id’

Once all the photos are uploaded, you would then update (PATCH) the verification to mark it into 'submitted' status. This marks the completion of the verification. This step requires all the photos to be submitted prior to triggering this.

Documentation: /sessions/{sessionid} (PATCH)

After these three steps, you've done your part, and the verification will then be taken care of by us.

Wait for webhook response

Veriff sends you a Decision event via Webhook using POST request. You will have to implement the listener.

This hook will be sent back asynchronously, and it contains more data, including the verified identity information.

Documentation: Webhook Decision (POST)

The web hook is sent to the URL that is configurable from the Back office under Management › Vendor › Integrations.

Handling decision responses from Veriff

To automate the handling of responses from verifications, you will need to implement a webhook listener, according to the documentation at Webhook Decision (POST) Once you have determined the URL of the listener, it is possible to configure it in the Veriff back office (Integrations / Notifications / Decision webhook url ) In case you want to test web hooks before the mobile app fully working, it is possible to hand generate verification sessions in the back office (Verifications / Generated tokens / Generate session and then following the URL for a web-based verification session, which will post the result to your webhook)

Configuring the webhook endpoint

Go to Veriff's back office, Management -> Vendors -> Edit, and set 'Decision notification url' to the URL where your server will be listening for decision notifications from Veriff. Veriff will post decision notifications of verification results to this URL. Only HTTPS URLs are allowed.

If there is a network connectivity issue or technical issue with delivering the notification (any non-200 response code), Veriff will retry the notification multiple times for up to a week.

The full description of the webhook format is at Webhook Decision (POST)

Recognizing your customer

When your server receives a decision notification from Veriff, you have to figure out, which customer is it about.

There are two ways to do this:

The easiest way is to track the session ID provided by Veriff during session creation. All future event and decision notifications refer to the session ID. The session ID is unique for each session, and it can be used to look up sessions in the administrative interface at Veriff Back Office

The other way is to provide Veriff with your internal customer ID, or some other key that uniquely identifies your customer. You can store your identifier in the vendorData element as a string, and we will send it back to you in webhook notifications. Please bear in mind that it is technically possible for one customer to be associated with multiple verification sessions, and this could potentially create ambiguous situations in code, if you are only recognizing customers by your own identifier, and not Veriff's session ID.

Handling security

It is important to check that the webhook responses do indeed originate from Veriff.

You can secure the webhook listener URL in three ways:

When Veriff calls your webhook endpoint, we use the same logic of X-SIGNATURE generation on our calls to you, as on your calls to us. So, when we call your endpoint for any notification URL, we set the X-AUTH-CLIENT http header to your API key, and we set the X-SIGNATURE header to the hex encoded sha256 digest of the request body and the secret.

When you accept a webhook call from us, you need to proceed as follows:

  1. compare the X-AUTH-CLIENT header to your api key, if different -> fail with error
  2. access the http request body (before it is parsed)
  3. calculate the sha256 digest of the request body string + api secret
  4. compare the hex encoded digest with the X-SIGNATURE header, if different -> fail with error
  5. only now you should parse the request body JSON object

The calculation for X-SIGNATURE is following the same algorithm as for session generation.

Different webhook calls

The difference between the URLs is as follows:

Meaning of the various verification responses

Verification status is one of

Verification response code is one of 9001, 9102, 9103, 9104, 9151, 9161

Explanation of the meaning of the response codes: Webhook response codes

Lifecycle of the verification session

Responses 9001, 9102, and 9104 are conclusive responses. The session is closed and the URL is not available for the end user.

Response 9103 is an inconclusive response. The session remains open until you receive one of the above conclusive responses. The session is re-opened for the end user, accepting a new attempt.

Responses 9151 and 9161 are intermediate responses. The session is being processed, it is not open for the end user, and you will soon receive one of the above conclusive or inconclusive responses.

Preconditions for approval decisions

We give a positive conclusive decision (status approved, code 9001) when the user has provided us with:

Reasons for negative conclusive decisions

A negative decision means that the person has not been verified. The verification process is complete. Either it was a fraud case or some other severe reason that the person can not be verified. You should investigate the session further and read the "reason". If you decide to give the client another try you need to create a new session

Reasons for inconclusive decisions

*In case of verifications which have received a "Resubmission requested" decision from Veriff, we highly recommend notifying the user about the reason why the verification did verification fail and tips for what could be done better on the next attempt. This can be done either via e-mail, SMS and/or in your platform for better visibility. In case of resubmitted verificatoin attempts where something was missing or the quality of the submission was poor, a next attempt is created ready to be used and accessible via the same session URL. The same session URL should be used for verification attempts by the same user.

Final decisions

You have the right to make the final decision about verifying an end-user even after they have completed the verification process with Veriff. In order for you to make the final decision, we recommend you create an appropriate functionality in your back-end. This will enable you to either approve or reject applications after the person has completed Veriff’s verification session. When you perform additional checks outside of Veriff’s service, it is necessary to have another layer of decision making. The decision has to be motivated based on further checks or extra information independent of Veriff’s decision. The additional verification details can be determined in accordance with your business needs and the amount of data and background information available to you about the end-user. Potential use cases: * Age checks * Name validation checks * A user is unable to pass verification as required, but their attempt is sincere and the document is legitimate * A user has made multiple fraudulent attemtps to verify and cannot pass Veriff's verification any more * You wish to restrict the user's access to your platform based on their earlier behavior Veriff provides a more standardized solution where unconventional user behavior is not deferred to for the benefit of overall decision quality.

Meaning of the various event codes

{
  "id": "f04bdb47-d3be-4b28-b028-a652feb060b5",
  "feature": "selfid",
  "code": 7002,
  "action": "submitted"
}

The event webhook informs you about the progress of the verification. However, it does not inform you of the decision.

The event code can be one of:

Storing verification media

For businesses which are regulated by various KYC and AML laws and rules, storing proof of the customer's verification is often a requirement. While Veriff stores and holds the customer's media - photos and videos - it might also be mandatory and more convenient for the business to store this media internally.

First, you need to get the sessionId of a session you want to download the media for. This can be found from the decision webhook(parameter "id") which is automatically sent after a decision has been made for a verification session. With the sessionID, make a GET request to /sessions/{sessionId}/media endpoint. From there, you will find a mediaId for every media file we have stored.

With the mediaIds, you can make a GET request to /media/{mediaId} endpoint to get the media file in .jpeg or .mp4 format. A separate request will have to be made for each media file.

Automating the download of photo and video files associated with comlpeted verifications.

/sessions/{sessionId}/media First, query for a list of files using a GET request to /media/{mediaId} The response to your GET request to /sessions{sessionID}/media will be a list of videos and images related to this sessionID.

Second, the individual media files can be downloaded by using the mediaID returned in the first step with a GET request to /media/{mediaID}

Testing Manual for your Veriff Integration

You will have two integrations set up for your Backoffice account. A (test) and a (live) integration. These are used for different purposes. The test integration will be used by you to test the communication between Veriff's and your end and to see how the responses are handled. The live integration will be used for your actual customers or to test the service quality of Veriff's responses before actually going live. To test the service quality, please contact your onboarding manager to schedule a timeslot.

Testing verification sessions

Testing security

Testing responses

Each type of response should be accepted:

Automated responses

If you wish to test the behavior of your integration and receive certain decisions when testing your integration with Veriff's service, create the sessions and include the desired decision - "Approve", "Decline", "Resubmit" in the "firstName" field.

This way, after going through the verification flow, you will receive an automated response with the desired decision. The feature can be used to test out the integration behavior on your side and see how Veriff's responses are handled. This will work only when using a test integration. Verifications done with live integrations will be treated as standard and these should not be used for testing purposes.

If you wish to receive certain client or document data along with the verification decision response, you can include data this in the initialization data when creating the verification session, it will be retained throughout the verification and included in the decision webhook response. json { "lang": "en", "person": { "idNumber": "38218.9318", "lastName": "Approved", "firstName": "Approve" }, "callback": "https://awesome.page", "document": { "type": "ID_CARD", "number": "Q021234567", "country": "EE", "nationality": "EE" }, "features": [ "selfid" ], "timestamp": "2016-05-19T08:30:25.597Z", "vendorData": "11111111" }

Testing process in your app

You should test the handling of best cases as well as edge cases

Mobile testing

Test our demo app by downloading it in the app store. iOS / Android

API Upload testing

Required tools Veriff's API library - VeriffAPI.zip Node.js - (Download - https://nodejs.org/en/download/) Notepad/TextEdit (default in Windows/Mac) or Notepad++ - (Download - https://notepad-plus-plus.org/)

  1. Download and install Node.js
  2. Download and extract JS-integration-demo.zip
  3. Open Command (Windows) or Terminal (Mac) on your local computer.
  4. Navigate to js-integration-demo folder cd C:\Users\User\Desktop\Veriff API).
  5. Run command >npm install
  6. Open app.js with your text editing app (Notepad/TextEdit) and update 'Your-API-Key' and 'Your-API-Token' to the values in your Backoffice account (Management -> Vendor). Tokens must be in single quotes. Save the file. APITEST
  7. Run the app.js node app.js

Now the verification session is created and it is being processed. Check your Backoffice dashboard to review the data extracted and decision made by Veriff.

iOS SDK integration guide

If upgrading from version 1.* skip to chapter 3

Requirements

Integration Veriff iOS SDK requires at least iOS version 10.0

1. Add framework to a project

1.1 Via Cocoapods

Steps to set up dependency manager. Only follow these steps if Cocoapods is not installed and iOS project is not using it.

To install Cocoapods run:

sudo gem install cocoapods

Run pod init in your project folder. This creates Podfile with application target. Under that target add following line.

pod 'VeriffSDK', '~> 2.3.4'

After this is done run pod install in folder conntaining Podfile. This will download and install VeriffSDK in your Xcode workspace.

1.2 Manual method

Copy the “Veriff.framework” to your project and add it as embedded binary to application target.

2. Using the Veriff library

The verification process must be presented by application. The app is aware of the current customer, who is either logged in via the Vendor system or who is identified other way with unique system pass. The Vendor must be able to determine the customer later, if verification ends/ or returns. It depends entirely on the Vendor business logic.

Every Veriff session is unique for a client. The session expires after 7 days automatically, but is valid until then. After the verification data is uploaded, the SDK v2.0 does not wait for the final verification result (async). The SDK v2.0 only notifies whether the verification data upload is successful or not.

The verification result is sent to the Vendor server in the background. ( See https://developers.veriff.me/#webhooks_decision_post ). Veriff SDK sends callbacks to vendor mobile application via VeriffDelegate.

2.1 Add usage descriptions to application Info.plist

Not adding these usage descriptions causes system to kill application when it requests the permissions when needed.

2.1.1 Camera Usage Description

Veriff SDK is using camera for capturing photos during identification flow. Application is responsible to describe the reason why camera is used. You must add NSCameraUsageDescription to the info.plist of application with the explanation of usage.

2.1.2 Microphone Usage Description

Veriff SDK is using microphone for capturing video sound during the identification flow. Application is responsible to describe the reason why the microphone is used. You must add NSMicrophoneUsageDescription to the info.plist of application with the explanation of usage.

2.2 Import Veriff in your code:

import Veriff

2.3 Configure SDK before displaying it

Setting configuration parameters

Parameters Explanation
sessionUrl Please use the corresponding url depending on the VeriffSDK version:
VeriffSDK < 2.3.3 please use 'https://magic.veriff.me/v1/'
VeriffSDK >= 2.3.3 please use 'https://magic.veriff.me'
sessionToken The session Token unique for the client. It needs to be generated following https://developers.veriff.me/#sessions_post. Note that token request also sends URL but that is not correct one to use. Prefer ones listed above.
let conf = VeriffConfiguration(sessionToken: token, sessionUrl: url)
let veriff = Veriff.shared
veriff.set(configuration: conf)

UI styling

Some of UI in SDK can be modified to match general appearance of app. This can change with upcoming releases and give more options for styling.

Property Explanation
controlsColor Allows to set custom color for buttons
let schema = ColorSchema()
schema.controlsColor = .red
veriff.set(colorSchema: schema)

2.4 Handling result codes form SDK

Veriff SDK returns a number of result codes, that application can handle. Implement VeriffDelegate and assign it to delegate property of Veriff instance.

Example: swift extension VerificationService: VeriffDelegate { func onSession(result: VeriffResult, sessionToken: String) { switch result.code { case .STATUS_SUBMITTED: } } }

Here is list of all possible status codes

Status code Explanation
UNABLE_TO_ACCESS_CAMERA User denied access to the camera
STATUS_USER_CANCELED User canceled the verification process
STATUS_SUBMITTED User submitted the photos
STATUS_ERROR_SESSION The session token is either corrupt, or has expired. A new sessionToken needs to be generated in this case
STATUS_ERROR_NETWORK SDK could not connect to backend servers.
STATUS_ERROR_NO_IDENTIFICATION_METHODS_AVAILABLE Given session cannot be started as there are no identification methods
STATUS_DONE The session status is finished from clients perspective
STATUS_ERROR_UNKNOWN An unkown error occured

2.5 Start verification process

Veriff SDK looks for currently presented UIViewController from key UIWindows' root view controller. Using this view controller verification UI is presented.

veriff.startAuthentication()

// Alternatively pass ViewController that is used for presenting verification UI. 
// That ViewController has to be in view hierarchy and not presenting.
startAuthentication(from viewController: UIViewController)

3. Migrating from 1.* to 2.*

Veriff library 2.0 integration has changed significantly since 1.*. We dropped TwiloVideo and requirement to pass Veriff specific push notifications to SDK. It simplifies setup and is reflected in API. Since SDK 2.0 it's no longer needed to embed Twiliovideo framework in app as SDK doesn't link against it anymore. Also Firebase project created for Veriff SDK is not needed in new version. If there were push notification translations for Veriff messages this can be also removed from Xcode project.

3.1 API changes

Getting SDK instance

v1.*

Veriff.sharedInstance() 

v2.*

Veriff.shared

Pass session URL and token to SDK

v1.*

configure(_ block: @escaping VeriffConfigurationBlock)

v2.*

set(configuration: VeriffConfiguration)

Customize background for selected views in SDK

v1.x swift setBackgroundImage(_ imageUrlString: String) v2.*

Removes background image customization

Customizing UI of SDK

v1.x

createColorSchema(_ block: @escaping VeriffColorSchemaBlock)

v2.*

set(colorSchema: ColorSchema)

Changes for ColorSchema

v2.0

Removes backgroundColor, footerColor, hintFooterColor, cameraControlsColor properties

Listening callbacks about verification process

v1.x

setResultBlock(_ result: @escaping ProcessBlock)

v2.*

Implement VeriffDelegate to handle result

onSession(result: VeriffResult, sessionToken: String)

Set implementation as a delegate of Veriff shared instance

veriff.delegate = service

Displaying verification flow

v1.x

requestViewController(completion: @escaping AuthCompletionBlock)

v2.*

New API despite removing completion closure is still async.

startAuthentication()

If it's needed to use different ViewController that SDK uses for presenting its own UI use following API

startAuthentication(from viewController: UIViewController)

Android SDK integration

Overview

The Android SDK allows you to add the Veriff verification flow to your native Android application.

Requierments

Veriff Android SDK requiers Android 5.0 or newer.

Adding the SDK

Add two new maven repository destinations under the root build.gradle repositories tag in allprojects section. It should contain the following maven repositories:

    allprojects {
        repositories {
            maven { url "http://dl.bintray.com/argo/sdk" } //probity
            maven { url "https://cdn.veriff.me/android/" } //veriff
            google()
            jcenter()

        }
    }

Add two dependencies in the application build.gradle:

    implementation 'com.veriff:veriff-library:2.4.0'
    implementation 'io.probity.sdk:collector:1.0.0'

Permissions

The SDK will request all the permissions it needs, please make sure that the CAMERA, RECORD_AUDIO, and WRITE_EXTERNAL_STORAGE permissions are not explicitly removed using tools:node="remove" in your app`s manifest file. Ignore this if you are not explicitly removing any permissions.

Starting the verification flow

The verification process must be launched inside the vendor specific Activity class. The activity is aware of the current customer, who is either logged in via the Vendor system or who is identified other way with unique system pass. The vendor must be able to determine the customer later, if application ends/ or returns. It depends entirely on the Vendor business logic.

Every Veriff SDK session is unique for a client. The session expires after 7 days automatically, but is valid until then.

In vendor activity class define the result code and initialize the SDK and launch the verification flow as below:

Parameters Description
baseUrl 'https://api.veriff.me' for testing and 'https://magic.veriff.me' for production
sessionToken 'sessionToken' should be unique for each call. Check '/sessions' endpoint in the backend documentation here to learn how to generate one.
    Veriff.Builder veriffSDK = new Veriff.Builder(baseUrl, sessionToken);
    veriffSDK.launch(MainActivity.this, REQUEST_VERIFF);

Getting the verification status

The verification result is sent to the vendor server in the background. (Reference for that is in the API Spec document ). Veriff SDK sends callbacks to vendor`s mobile application via onActivityResult, background service and broadcasts. The most reliable callback method is the background service because it’s usually waken up by the Android system services. All the mentioned ways return the same status codes so the vendor application developer can choose their preferred method and ignore the other ones. Refer to the handling result section to see how to handle the response and what each staus code means. Different ways to capture the result are as below. After the verification data is uploaded, SDK v1.0 does not wait for the final verification result (async). The SDK v1.0 only notifies whether the verification data upload is successful or not.

In the activity

To capture the result from the SDK in the activity override onActivityResult in vendor activity that starts the verification flow:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (requestCode == REQUEST_VERIFF && data != null) {
       int statusCode = data.getIntExtra(VeriffConstants.INTENT_EXTRA_STATUS, Integer.MIN_VALUE);
       String sessionToken = data.getStringExtra(VeriffConstants.INTENT_EXTRA_SESSION_URL);
       handleResult(statusCode, sessionToken); //see below to know how to handle result
   }
   super.onActivityResult(requestCode, resultCode, data);
}

Using a background service

To capture the result from the SDK using a background service.

public class MyVeriffStatusUpdatesService extends VeriffStatusUpdatesService {
   @Override
   protected void onStatusChanged(String sessionToken, int statusCode) {
       handleResult(statusCode, sessionToken); //see below to know how to handle result
   }
}

Add the service to the application manifest:

<!-- Implement Veriff SDK updates service -->
<service android:name=".MyVeriffStatusUpdatesService"
    android:exported="false">
   <intent-filter>
       <action android:name="me.veriff.STATUS_UPDATE" />
   </intent-filter>
</service>

Using a broadcast receiver

To capture the result using a broadcast receiver create a BroadcastReceiver which will listen to Veriff SDK broadcasts:

public class VeriffStatusReceiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
       Bundle extras = intent.getExtras();
       if (extras.containsKey(VeriffConstants.INTENT_EXTRA_STATUS)) {
           int statusCode = data.getIntExtra(VeriffConstants.INTENT_EXTRA_STATUS, Integer.MIN_VALUE);
           String sessionToken = extras.getString(VeriffConstants.INTENT_EXTRA_SESSION_URL);
           handleResult(statusCode, sessionToken); //see below to know how to handle result
       }
   }
}

Add the receiver to the application manifest:

<!-- Implement you own BroadcastReceiver to track VeriffSDK status, should be protected by "signature" permission -->
<receiver
android:name=".VeriffStatusReceiver"
android:permission="${applicationId}.VERIFF_STATUS_BROADCAST_PERMISSION">
   <intent-filter>
       <category android:name="${applicationId}" />
       <action android:name="veriff.info.status" />
   </intent-filter>
</receiver>

Handling the result

All the three methods will return the same result which can be handled as below.

    public void handleResult(int statusCode, String sessionToken){
       if (statusCode == VeriffConstants.STATUS_USER_FINISHED) {
           //user finished whatever he/she was asked to do, there might be other callbacks coming after this one (for example if the images are still being uploaded in the background)
       } else if (statusCode == VeriffConstants.STATUS_ERROR_NO_IDENTIFICATION_METHODS_AVAILABLE) {
           //there are no identifications methods currently available
       } else if (statusCode == VeriffConstants.STATUS_ERROR_SETUP) {
           //issue with the provided vendor data
       } else if (statusCode == VeriffConstants.STATUS_ERROR_UNKNOWN) {
           //unidentified error
       } else if (statusCode == VeriffConstants.STATUS_ERROR_NETWORK) {
           //network unavailable
       } else if (statusCode == VeriffConstants.STATUS_USER_CANCELED) {
           //user closed SDK
       } else if (statusCode == VeriffConstants.STATUS_UNABLE_TO_ACCESS_CAMERA) {
           //we are unable to access phone camera (either access denied or there are no usable cameras)
       } else if (statusCode == VeriffConstants.STATUS_UNABLE_TO_RECORD_AUDIO) {
           //we are unable to access phone microphone
       } else if (statusCode == VeriffConstants.STATUS_SUBMITTED) {
           //SelfID photos were successfully uploaded
       } else if (statusCode == VeriffConstants.STATUS_OUT_OF_BUSINESS_HOURS) {
           //call was made out of business hours, there were no verification specialists to handle the request
       } else if (statusCode == VeriffConstants.STATUS_ERROR_SESSION) {
           //invalid sessionToken was passed to the SDK
       } else if (statusCode == VeriffConstants.STATUS_DONE) {
           //verification specialist declined the session
       }
    }

Adding error logging

To turn on logging, you simply add your logging implementation instance (instance of LogAccess class) to the SDK before launching the SDK as shown below:

    Veriff.setLoggingImplementation(<Instance of your logging class>);
    Veriff.Builder veriffSDK = new Veriff.Builder(baseUrl, sessionToken);
    veriffSDK.launch(MainActivity.this, REQUEST_VERIFF);

Proguard rules

Veriff project proguard-rules.pro file contents

# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Application classes that will be serialized/deserialized over Gson
-keep class mobi.lab.veriff.data.** { *; }

-dontwarn mobi.lab.veriff.fragment.BaseFragment


-keepparameternames
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
                SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

-keep public class * {
    public protected *;
}

-keepclassmembernames class * {
    java.lang.Class class$(java.lang.String);
    java.lang.Class class$(java.lang.String, boolean);
}

-keepclasseswithmembernames,includedescriptorclasses class * {
    native <methods>;
}

-keepclassmembers,allowoptimization enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

# OkHttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**

-dontwarn com.fasterxml.jackson.databind.ext.DOMSerializer
-dontwarn io.jsonwebtoken.impl.Base64Codec
-dontwarn io.jsonwebtoken.impl.crypto.EllipticCurveProvider

## RETROFIT 2 ##
-dontwarn javax.annotation.**
# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions
## RETROFIT 2 ##

## OkHttp
-dontwarn okio.**
## OKHttp


## GSON 2.2.4 specific rules ##

# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

-keepattributes EnclosingMethod

# Gson specific classes
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }

-dontwarn com.koushikdutta.ion.conscrypt.ConscryptMiddleware

# WebRTC classes, accessed from native via JNI
-keep class org.webrtc.** { *; }

Releases

Our release log can be found here

Upgrading Veriff SDK from 1.* to 2.+

Veriff SDK upgrade to 2.+

Veriff SDK 2.+ integration has changed significantly since 1.*. There are mayor changes in the SDK distribution where the SDK from now on is distributed via gradle import and many previously required services have been removed and trimmed down.

Remove Veriff SDK required Firebase code

If your application uses Firebase notifications Remove Veriff message handling from your Firebase service class and instead you can handle your notification directly

    if (!handleVeriffNotifications(remoteMessage)) {
        handleClientApplicationNotifications(remoteMessage);
    }

If your application does not use Firebase notifications Delete both Firebase classes that extend FirebaseInstanceIdService and FirebaseMessagingService Remove Firebase services from the AndroidManifest:

      <!-- Implement Firebase notification service that handles Veriff notifications-->
      <service android:name=".service.SampleFirebaseMessagingService">
         <intent-filter>
             <action android:name="com.google.firebase.MESSAGING_EVENT" />
         </intent-filter>
      </service>
      <!-- Implement FirebaseInstanceIdService -->
      <service android:name=".service.SampleFirebaseInstanceIdService"
        android:exported="false">
         <intent-filter>
             <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
         </intent-filter>
      </service>

Finally remove all Firebase dependencies from the app build.gradle file

Remove the dependency on the .aar file and replace it with the gradle import from Veriff maven repo

Remove the veriff SDK .aar file from the lib directory

If you are not using any other manually added libraries remove the lib directory and the reference to the lib directory from the application build.gradle file.

  allprojects {
      repositories {
          jcenter()
          flatDir {
              dirs 'libs'
          }
      }
  }

Add a new maven repository destination under the root build.gradle repositories tag in allprojects bracket. It should contain the following two maven repositories:

  allprojects {
      repositories {
          maven { url "http://dl.bintray.com/argo/sdk" } //probity
          maven { url "https://cdn.veriff.me/android/" } //veriff
          google()
          jcenter()

      }
  }

From the application build.gradle file remove all Veriff dependencies that you don't use as those are no longer needed and have been packaged in the gradle import

The exception is that still needs to be added on the parent application side.

  implementation "com.google.firebase:firebase-core:16.0.6"
  implementation "com.google.firebase:firebase-messaging:17.3.4"
  implementation "com.google.android.gms:play-services-gcm:16.0.0"
  implementation 'com.android.support.constraint:constraint-layout:1.1.3'
  implementation 'com.squareup.retrofit2:retrofit:2.3.0'
  implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
  implementation 'com.squareup.okhttp3:okhttp:3.10.0'
  implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
  implementation 'com.jaredrummler:android-device-names:1.0.7'
  implementation 'com.koushikdutta.ion:ion:2.2.1'
  implementation 'com.twilio:video-android:1.3.4'
  implementation 'io.jsonwebtoken:jjwt:0.6.0'
  implementation 'org.greenrobot:eventbus:3.1.1'

Remove irrelevant return values from VeriffSDKStatusUpdatedService and VeriffStatusReceiver

  VeriffConstants.STATUS_OUT_OF_BUSINESS_HOURS, VeriffConstants.STATUS_UNABLE_TO_RECORD_AUDIO and VeriffConstants.STATUS_VIDEO_CALL_ENDED

As a final step add the import for Veriff libary in the application build.gradle dependency list. It should contain the following two lines:

  implementation 'com.veriff:veriff-library:2.4.0'
  implementation 'io.probity.sdk:collector:1.0.0'

Request, response format

Request (Header)

X-AUTH-CLIENT: string (required)
Vendor’s API Key

X-SIGNATURE: string (required)
Request Body signed with Vendor’s API Secret. X-Signature is a SHA-256 hex encoded hash. The stringified body is concatenated by the Vendor’s API Secret and then hex digested.

CONTENT-TYPE: string (required) Type for the request: (application/json)

https://api.veriff.me/v1

Vendor-Veriff-Client-visual_Request-illustration

/sessions

Response

Properties:

 {
  "verification": {
    "callback": "https://awesome.page",
    "person": {
      "firstName": "Tundmatu",
      "lastName": "Toomas",
      "idNumber": "1234567890"
    },
    "document": {
      "number": "B01234567",
      "type": "PASSPORT",
      "country": "EE",
      "nationality": "EE"
      "citizenship": "EE"
    },
    "vendorData": "11111111",
    "lang": "en",
    "features": ["selfid"],
    "timestamp": "2016-05-19T08:30:25.597Z"
  }
}

Example

[
"selfid"
]

Response (201)

Properties

 {
  "status": "success",
  "verification": {
    "id":"f04bdb47-d3be-4b28-b028-a652feb060b5",
    "url": "https://magic.veriff.me/v/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoX3Rva2VuIjoiOThiYzdjMjEtZTQ0Yy00MTZiLTkxOTMtMTU5ZGZkMzBmMDg4Iiwic2Vzc2lvbl9pZCI6Ijc2ODhmMzYzLTAyZjctNDE1My1iMzM1LWE0ODQ3OTRkMzZmNyIsImlhdCI6MTUwMTIyODI1MSwiZXhwIjoxNTAxODMzMDUxfQ.bMEF37E6-zT2Aa6Q8UXK3B_ZL51w6D_lxnGgQvhj214",
    "sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoX3Rva2VuIjoiOThiYzdjMjEtZTQ0Yy00MTZiLTkxOTMtMTU5ZGZkMzBmMDg4Iiwic2Vzc2lvbl9pZCI6Ijc2ODhmMzYzLTAyZjctNDE1My1iMzM1LWE0ODQ3OTRkMzZmNyIsImlhdCI6MTUwMTIyODI1MSwiZXhwIjoxNTAxODMzMDUxfQ.bMEF37E6-zT2Aa6Q8UXK3B_ZL51w6D_lxnGgQvhj214",
    "baseUrl": "https://magic.veriff.me"
      }
  }

Response (400)

Properties

{
  "status": "fail",
  "code:": "1102",
  "error": "Mandatory parameters are missing from the request."
}





Code Description
1001 Query ID must be between 20 and 40 symbols.
1002 Query ID must be a valid UUID V4
1003 Query ID must be unique, it has already been used.
1101 Invalid Vendor API Key.
1102 Mandatory parameters are missing from the request.
1104 Request includes invalid parameters.
1201 Invalid timestamp. Timestamp must not be older than one hour.
1202 Timestamp format is incorrect. YYYY-MM-DDTHH:MM:S+Timezone Offset|Z or UTC.
1301 Requested features are not supported.
1302 Only HTTPS return URLs are allowed.
1500 Vendor data cannot be more than 40 symbols.
1501 Vendor data must be a string.
2001 Identity code must be 11 digits in length.
2002 Identity code is not a valid Estonian identity code.
2003 Date of birth is not a valid date.
2101 Document number has to be between 6 and 9 characters.
2102 Document number may contain only characters and numbers A-Z, 0-9.
2103 Document type is not supported.
2104 Document from provided country is not supported.

Response (401)

Example

{
  "status": "fail",
  "error": "Not Authorized."
}

/sessions/{sessionId} (PATCH)

Method to change the status of the verification.

URI Parameters

sessionId: string (required)

Properties:

Response (200):

Body Properties

 { status: 'success',
  verification:
   { id: '82c90c22-c8a8-412c-8e0e-f3f27b385071',
     url: 'https://magic.veriff.me/v1/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uX2lkIjoiODJjOTBjMjItYzhhOC00MTJjLThlMGUtZjNmMjdiMzg1MDcxIiwiaWF0IjoxNTIwMjgyMjAxLCJleHAiOjE1MjA4ODcwMDF9.dwjLFSd79pJR2Csv5nRU-bLNJ_mpBm1cS654HeI9HWo',
     host: 'https://magic.veriff.me',
     sessionToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXNzaW9uX2lkIjoiODJjOTBjMjItYzhhOC00MTJjLThlMGUtZjNmMjdiMzg1MDcxIiwiaWF0IjoxNTIwMjgyMjAxLCJleHAiOjE1MjA4ODcwMDF9.dwjLFSd79pJR2Csv5nRU-bLNJ_mpBm1cS654HeI9HWo' 
    }   
  }

/sessions/{sessionId} /media (GET)

Get the list of media objects with sessionId = {sessionId}

URI Parameters

sessionId: string (required)

Properties

{
  "status": "success",
  "videos": [
    {
      "id": "{MEDIA_ID}",
      "name": "{VIDEO_NAME}",
      "duration": "{DURATION_IN_SECONDS}",
      "url": "{MEDIA_DOWNLOAD_URL}",
      "timestamp": {
        "url": "{GUARDTIME_TIMESTAMP_URL}",
        "id": "{TIMESTAMP_ID}"
      },
      "size": "{SIZE_IN_KB}",
      "mimetype": "{MEDIA_MIME_TYPE}"
    }
  ],
  "images": [
    {
      "id": "{MEDIA_ID}",
      "name": "{IMAGE_NAME}",
      "url": "{MEDIA_DOWNLOAD_URL}",
      "timestamp": {
        "url": "{GUARDTIME_TIMESTAMP_URL}",
        "id": "{TIMESTAMP_ID}"
      },
      "size": "{SIZE_IN_KB}",
      "mimetype": "{MEDIA_MIME_TYPE}"
    }
  ]
}

/sessions/{sessionId} /media (POST)

In this post request the vendor sends a file (base64 encoded image string inside a JSON body object), where they could upload images (1 image at a time), specifying also a type of the image that is being uploaded.

Request

URI Parameters sessionId: string (required)

Properties:

data:image/png;base64,R0lGODlhAQABAAAAACw=

timestamp: string (required)
Combined ISO 8601 date and time in UTC (YYYY-MM-DDTHH:MM:S+Timezone Offset|Z, i.e., 2018-04-18T11:02:05.261Z)

Response

Properties

{ status: 'success',
  image:
   { id: '39388f8d-c6d6-4e9b-92c6-6978b2e8d664',
     name: 'document-back.jpg',
     timestamp:
      { url: 'https://magic.veriff.me/v1/timestamps/6f7e2967-4953-4e35-9aed-4ba69f65db80',
        id: '6f7e2967-4953-4e35-9aed-4ba69f65db80' },
     size: 52268,
     mimetype: 'image/png',
     url: 'https://magic.veriff.me/v1/media/39388f8d-c6d6-4e9b-92c6-6978b2e8d664'
   }
}

/sessions/{sessionId} /person (GET)

Get the Person object with sessionId = {sessionId}

Request

URI Parameters sessionId: string (required)

Response

{
    "status": "success",
    "person": {
        "id": "uuid",
        "firstName": "string",
        "lastName": "string",
        "idCode": "string",
        "dateOfBirth": "string, format (YYYY-MM-DD)",
        "gender": "string, values can be M - male, F - female, null - undefined",
        "nationality": "string, iso2 country code",
        "placeOfBirth": "string, iso2 country code",
        "citizenships": [
            {
                "kind": "string, Main or Secondary",
                "citizenship": "string, country name"
            }
        ],
        "pepSanctionMatches": [
            {
                "numberOfMatches": "number",
                "date": "date with timestamp, 2018-11-28T17:13:28.154Z",
                "matches": [
                    {
                        "name": "string",
                        "nationality": "string",
                        "category": "string, SIP or PEP"
                    },
                ]
            }
        ]
    }
}

/sessions/{sessionId} /timestamps (GET)

Get the list of signature timestamp objects with sessionId = {sessionId}

Request

URI Parameters sessionId: string (required)

Response

Properties

{
  "status": "success",
  "timestamps": [
    {
      "id": "{TIMESTAMP_ID}",
      "url": "{GUARDTIME_TIMESTAMP_URL}",
      "context": "{TIMESTAMP_TYPE}"
    }
  ]
}

/sessions/{sessionId} /attempts (GET)

Get the list of attempt objects with sessionId = {sessionId}

Request

URI Parameters sessionId: string (required)

Response

Properties

{ 
  status: 'success',
  verifications: [ 
    {
      id: '39388f8d-c6d6-4e9b-92c6-6978b2e8d664',
      status: 'declined'
    },
    {
      id: '6854c51c-8754-4c6a-907c-4b8f2ba5b23c',
      status: 'approved'
    },
    { id :'6klb5bcq-1e2d-2fd5-925d-f55e6d93b4dd',
    status: 'resubmission_requested'
    }
   ]
}

/sessions/{sessionId} /decision (GET)

Get the session decision object with sessionId = {sessionId}, if available.

{
  "status": "success",
  "verification": {
    "id": "8c23aced-c45b-4942-881c-4d784914561d",
    "code": 9103,
    "person": {
      "gender": null,
      "idNumber": "38508-60269",
      "lastName": "Jane",
      "firstName": "Mary",
      "citizenship": null,
      "dateOfBirth": "1971-01-01",
      "nationality": null,
      "yearOfBirth": null,
      "pepSanctionMatch": null
    },
    "reason": "Document expired",
    "status": "resubmission_requested",
    "comments": [

    ],
    "document": {
      "type": "ID_CARD",
      "number": "B01234567",
      "country": "EE",
      "validFrom": null,
      "validUntil": "2015-05-19"
    },
    "reasonCode": 207,
    "vendorData": null,
    "decisionTime": "2019-09-05T13:38:17.568Z",
    "acceptanceTime": "2019-09-05T13:37:54.000Z",
    "additionalVerifiedData": {
    }
  },
  "technicalData": {
    "ip": null
  }
}

Request

URI Parameters sessionId: string (required)

Response

Properties

code: Verification response code (one of 9001, 9102, 9103, 9104, 9151, 9161)


9001 Positive: Person was verified. The verification process is complete. Accessing the sessionURL again will show the client that nothing is to be done here.
9102 Negative: Person has not been verified. The verification process is complete. Either it was a fraud case or some other severe reason that the person can not be verified. You should investigate the session further and read the "reason". If you decide to give the client another try you need to create a new session.
9103 Resubmitted: Resubmission has been requested. The verification process is not completed. Something was missing from the client and she or he needs to go through the flow once more. The same sessionURL can and should be used for this purpose.
9104 Negative: Verification has been expired. The verification process is complete. After 7 days the session get's expired. If the client started the verification process we reply "abandoned" here, otherwise if the client never arrived in our environment the status will be "expired".
9151 Intermediate Positive: SelfID was successful - this code is only send if the configuration flag is set.

Attempts

/attempts /{attemptId}/media (GET)

Get the list of media objects with attemptId = {attemptId}

Request

URI Parameters attemptId: string (required)

Response

Properties

{
  "status": "success",
  "videos": [
    {
      "id": "{MEDIA_ID}",
      "name": "{VIDEO_NAME}",
      "duration": "{DURATION_IN_SECONDS}",
      "url": "{MEDIA_DOWNLOAD_URL}",
      "timestamp": {
        "url": "{GUARDTIME_TIMESTAMP_URL}",
        "id": "{TIMESTAMP_ID}"
      },
      "size": "{SIZE_IN_KB}",
      "mimetype": "{MEDIA_MIME_TYPE}"
    }
  ],
  "images": [
    {
      "id": "{MEDIA_ID}",
      "name": "{IMAGE_NAME}",
      "url": "{MEDIA_DOWNLOAD_URL}",
      "timestamp": {
        "url": "{GUARDTIME_TIMESTAMP_URL}",
        "id": "{TIMESTAMP_ID}"
      },
      "size": "{SIZE_IN_KB}",
      "mimetype": "{MEDIA_MIME_TYPE}"
    }
  ]
}

Media

/media /{mediaId} (GET)

Get the media with mediaId = {mediaId}

Request

URI Parameters mediaId: string (required)

Response

Transfer-Encoding: chunked

Timestamps

/timestamps /{timestampId}

Get the timestamp with timestampId = {timestampId}

Request

URI Parameters timestampId: string (required)

Response

{
  "status": "success",
  "timestamp": {
    "id": "{TIMESTAMP_ID}",
    "context": "{TIMESTAMP_CONTEXT}",
    "signature": "{SIGNATURE}",
    "dataHash": {
      "algorithm": "SHA-256",
      "value": "{HASH_VALUE}"
    }
  }
}

Webhooks

/webhooks /decision (POST)

This endpoint specifies how the asynchronous response to the notification url looks like. It sends the result of the verification back to the vendor once the verification has been reviewed. The notification url needs to be specified in Veriff's backoffice.

Response

Description For testing this endpoint without depending on Veriff sending responses you can use this Curl command. Beware, that the signature will not match your Vendors Key and Secret. To validate this example signature and payload use Secret '3c184872-6929-43d9-91d5-9e68468b5aa1'.

curl --request POST 'https://your.url' -k \
--header 'accept:application/json' \
--header 'x-auth-client:8e4f7cd8-7a19-4d7d-971f-a076407ee03c' \
--header 'x-signature:328b360ef2bd2d6b8aa19b41ec5840f3cae94754ac0cfc11484d4ca84a82d9fd' \
--header 'content-type:application/json' \
--data '{"status":"success","verification":{"id":"a4c0a230-859a-4861-b99b-ac39e4a05bfd","status":"resubmission_requested","code":9103,"reason":"Photos are not from the same document.","acceptanceTime":"2017-09-26T12:27:55.000Z","decisionTime":"2017-09-26T12:34:21.000Z","person":{"firstName":"Morton","lastName":"Stracke","idNumber":"48002020011"},"document":{"number":"AA0052283","type":"ID_CARD","validFrom": "2017-02-27", "validUntil": "2022-02-27"},"comments":[{"type": "General Comment", "comment": "Person refuses to take off hat.", "timestamp": "2017-10-10T13:18:44.009Z"}],"technicalData":{"ip":"124.153.46.66"}}'

Properties

{
  "status": "success",
  "verification": {
    "id": "f04bdb47-d3be-4b28-b028-a652feb060b5",
    "status": "approved",
    "code": 9001,
    "acceptanceTime": "2017-01-18T12:22:50.239Z",
    "decisionTime": "2017-01-18T12:28:13.154Z",
    "person": {
      "firstName": "TestName",
      "lastName": "TestName",
      "idNumber": "1234567890",
      "nationality": "UK"
      "citizenship": "UK"
    },
    "document": {
      "number": "B01234567",
      "type": "PASSPORT",
      "validFrom": "2015-11-11",
      "validUntil": "2021-12-09"
    },
    "vendorData": "11111111",
    "comment": [{
      "type": "comment",
      "comment": "LH 2",
      "timestamp": "2016-05-19T08:30:25.597Z"
    }]
  },
  "technicalData": {
    "ip": "186.153.67.122"
  }
}
{
  "status": "success",
  "verification": {
    "id": "f04bdb47-d3be-4b28-b028-a652feb060b5",
    "code": 9103,
    "person": {
      "gender": null,
      "idNumber": null,
      "lastName": "TestName",
      "firstName": "TestName",
      "citizenship": null,
      "dateOfBirth": "1986-04-0",
      "nationality": null,
      "yearOfBirth": null,
      "pepSanctionMatch": null
    },
    "reason": "Video and/or photos missing",
    "status": "resubmission_requested",
    "comments": [

    ],
    "document": {
      "type": "PASSPORT",
      "number": "null",
      "country": "DE",
      "validFrom": null,
      "validUntil": "2024-01-14"
    },
    "reasonCode": 201,
    "vendorData": null,
    "decisionTime": "2019-06-29T11:05:00.780Z",
    "acceptanceTime": "2019-08-29T11:00:51.000Z",
    "additionalVerifiedData": {
    }
  },
  "technicalData": {
    "ip": "186.153.67.122"
  }
}
9001 Positive: Person was verified. The verification process is complete. Accessing the sessionURL again will show the client that nothing is to be done here.
9102 Negative: Person has not been verified. The verification process is complete. Either it was a fraud case or some other severe reason that the person can not be verified. You should investigate the session further and read the "reason". If you decide to give the client another try you need to create a new session.
9103 Resubmitted: Resubmission has been requested. The verification process is not completed. Something was missing from the client and she or he needs to go through the flow once more. The same sessionURL can and should be used for this purpose.
9104 Negative: Verification has been expired. The verification process is complete. After 7 days the session get's expired. If the client started the verification process we reply "abandoned" here, otherwise if the client never arrived in our environment the status will be "expired"' '**9151** : Intermediate Positive: SelfID was successful - this code is only send if the configuration flag is set.
9151 Intermediate Positive: SelfID was successful - this code is only send if the configuration flag is set.
101 Physical document not used
102 Suspected document tampering
103 Person showing the document does not appear to match document photo
105 Suspicious behaviour
106 Known fraud
107 Velocity/abuse
201 Video and/or photos missing
202 Face not clearly visible
203 Full document not visible
204 Poor image quality
205 Document damaged
206 Document type not supported
207 Document expired.

/webhooks /events (POST)

Description To keep up to date with the clients progress during the verification process Veriff allows to subscribe to certain events, at the moment three events are triggered, first when client arrives to veriff environment and starts the verification process, second when client is done with the process and submits the attempt,

Properties

{
  "id": "f04bdb47-d3be-4b28-b028-a652feb060b5",
  "feature": "selfid",
  "code": 7002,
  "action": "submitted"
}

id: String (required)
UUID v4 which identifies the verification session attemptId: String (required)
UUID v4 which identifies session attempt feature: String (required)
Feature on which the event was triggered (selfid) code: (one of 7001, 7002, 7003) (required)
Event code

7001 Started.
7002 Submitted.

action: Corresponding action description (required)