IDV Service flows

Introduction

FrankieOne has integrated with a number of ID Verification (IDV) services (speak with our sales team for the latest list. This article refers to Onfido, but applies to all supported services).

These are services that can:

  • capture photos of identity documents (OCR Capture)
  • capture selfie pictures/videos (Biometrics capture)
  • validate the photo of the ID for evidence of forgery, tampering, etc (Document report)
  • compare the selfie with the photo on the ID for facial similarity (Facial Similarity report)

For the best customer experience, you should use their supplied SDKs (both for web and native) in your applications to manage the actual photo/selfie process, as they have a number of inbuilt features designed to capture the best images for use in the IDV process . In order to activate those SDKs, you usually need 2 items:

  1. An applicantID - which is a unique identifier the SDK will use to upload data to the IDV service.
  2. A time-limited, single-use token that will be used to authenticate the applicant ID via the SDK.

Types of call to obtain a token

The FrankieOne API offers up 2 calls that can be used to obtain a token:

These will allow you to create/update an entity, then obtain a new token.

Calls to these endpoints will generate a token and applicantId that can then be passed to the SDK when it is activated in your native/web application.

Once your app has completed capturing the images, you then need to let us know it's time to gather the data and run the comparison process. You do this with a call to the following endpoint:

This call will allow you to update any further entity details captured before we start downloading data. The download process can take anywhere from 1 to 5 minutes due to the fact that Frankie uses service providers that have human failover checks when the AI components cannot fully analyze the ID document images.

🚧

Pro Tip

FrankieOne recommends that OCR data should not be relied upon to capture pre-populated fields. Whilst very good and accurate in the majority of cases, the time taken (see above) and potential for mistakes can lead to a poorer customer experience.

We recommend that details are captured manually and use the OCR process to verify that the data the users entered matches what was scanned in order to maintain the chain of trust.

The following diagram describes the flow in more detail:

  1. The SDK or Service indicates that a document capture and facial similarity comparison is needed and thus a token is required.

User data such as a name (at a minimum), date of birth, address, and even the ID document data can be collected at this time if available.

  1. Customer's Back-ends services call the FrankieOne getToken API, passing through what user data is available, along with application IDs (for native apps) or a referrer domain URL (for web apps).

FrankieOne will then obtain a token and applicantID from your configured service provider and return those to the calling Back-end Service.

  1. The applicantID and token are supplied to the SDK which is then activated.

It will then guide the user through the ID and selfie capture process. These documents will be uploaded to the service provider directly.

  1. The app will then inform the Customer Backend Service that the capture process is complete and pass on any additional user data obtained (address, etc)

  2. The Backend Service will call the initProcess API, updating the user data if available.

  3. The FrankieOne service will then proceed to download the image and report data and save that into the database. It is recommended that you background this call as it can take several seconds to initialise.

Once all the data has been downloaded, the FrankieOne service will proceed with incorporating the results into the overall risk profile of the user.

  1. Once the risk assessment is complete, a notification webhook is pushed to the Customer service with the latest risk assessment results.

All of the captured images/videos as well as the full IDV process results are then available through the Frankie portal, or via our GET entity API calls.

Using Onfido SDK to capture biometric information

The guide below provides a step by step process to implement the Onfido SDK to run a check with FrankieOne's Biometrics flow described in https://apidocs.frankiefinancial.com/docs/idv-service-flows

1. Creating an entity and getting a token

The first step is to create an entity and get a token to be used in initiating the Onfido SDK. This step can also be done as part of updating the entity details. Please see Create Entity and Get IDV Token to see the API call to create a new entity and get a token or Update Entity and Get IDV Token to see the API call to update an existing entity and get a token at the same time.

Sample Request

POST https://api.demo.frankiefinancial.io/compliance/v1.2/entity/new/idvalidate/getToken

{
	"applicationId": "TheNameOfYourApp",
	"entity": {
		"entityProfile": "safe_harbor_id",
		"entityType": "INDIVIDUAL",
		"name": {
			"familyName": "Johnson",
			"middleName": "twopass",
			"givenName": "<random_first_name>"
		},
		"dateOfBirth": {
			"dateOfBirth": "2000-01-01"
		},
		"addresses": [
			{
				"addressType": "RESIDENTIAL1",
				"country": "AUS",
				"streetNumber": "27",
				"streetName": "MILMAN",
				"streetType": "STREET",
				"suburb": "",
				"town": "MARLBOROUGH",
				"region": "",
				"state": "QLD",
				"postalCode": "4705"
			}
		],
		"extraData": [
			{// Consents are required to run checks with FrankieOne and a general good practice to pass on consent from your front end to Frankie which we will pass on to the vendors should they require it.
				"kvpKey": "consent.general", "kvpValue": "true", "kvpType": "general.bool"
			},
			{
				"kvpKey": "consent.docs","kvpValue": "true","kvpType": "general.bool"
			},
			{
				"kvpKey": "consent.creditheader","kvpValue": "true","kvpType": "general.bool"
			},
			{
				"kvpKey": "customer_reference",
				"kvpValue": "<customer_reference>", 
        //This should be your own internal customer reference for this individual in your system
				"kvpType": "id.external"
			}
		]
	}
}




Sample Response

In the samples below ... implies that there's information that's been removed for clarity's sake.

{
	"applicantId": "a07e1dd2-1307-473a-8e5b-3eba61676123",
	"entity": {
		"addresses": [
...
		],
		"dateOfBirth": {
...
		},
		"entityId": "938cb742-14f8-b6fb-4730-9ecfcb15b269", // This is ID that the record will have in Frankie
		"extraData": [
			{
				"kvpKey": "consent.general",
				"kvpType": "general.bool",
				"kvpValue": "true"
			},
			{
				"kvpKey": "consent.docs",
				"kvpType": "general.bool",
				"kvpValue": "true"
			},
			{
				"kvpKey": "consent.creditheader",
				"kvpType": "general.bool",
				"kvpValue": "true"
			},
			{
				"kvpKey": "customer_reference",
				"kvpType": "id.external",
				"kvpValue": "k58nmpsdnwjcnsfzx85ds"
			},
			{
				"kvpKey": "applicantId",
				"kvpType": "general.string",
				"kvpValue": "a07e1dd2-1307-473a-8e5b-3eba61676123"
			}
		],
		"name": {
...
		}
	},
	"requestId": "01GPYD0W0JTYG47XXE29QDW47S",
	"token": "eyJhbGciOiJFUzUxMiJ9.eyJleHAiOjE2NzM5MTU0NTcsInBheWxvYWQiOnsiYXBwIjoiYTA3ZTFkZDItMTMwNy00NzNhLThlNWItM2ViYTYxNjc2MTIzIiwiY2xpZW50X3V1aWQiOiIwNTJlNmIwNC1jYzJjLTRjN2YtOGE4Mi04YWYyYjdkY2UxYTkiLCJpc19zYW5kYm94Ijp0cnVlLCJpc190cmlhbCI6ZmFsc2UsInNhcmRpbmVfc2Vzc2lvbiI6ImVhNjgxOWRhLWMyYWEtNDE3OS04NzE1LWIxOWU2MzhjNTg1NCJ9LCJ1dWlkIjoicGxhdGZvcm1fc3RhdGljX2FwaV90b2tlbl91dWlkIiwidXJscyI6eyJkZXRlY3RfZG9jdW1lbnRfdXJsIjoiaHR0cHM6Ly9zZGsub25maWRvLmNvbSIsInN5bmNfdXJsIjoiaHR0cHM6Ly9zeW5jLm9uZmlkby5jb20iLCJob3N0ZWRfc2RrX3VybCI6Imh0dHBzOi8vaWQub25maWRvLmNvbSIsImF1dGhfdXJsIjoiaHR0cHM6Ly9hcGkub25maWRvLmNvbSIsIm9uZmlkb19hcGlfdXJsIjoiaHR0cHM6Ly9hcGkub25maWRvLmNvbSIsInRlbGVwaG9ueV91cmwiOiJodHRwczovL2FwaS5vbmZpZG8uY29tIn19.MIGHAkIAs4RTlzLFv0hsMoIn4TES9F1OACTVOoRy2LtlwIcCXwIp9GD-p8J7XqLFDFPf7slqL1FFutahT741P_O_MgjwuX0CQWZau9uNezHvsQZKA-fw4ugS-YMzLy825OC1klovhJ6_ZBAU_w2Y7wlhmnpoyyLW8D850Rg16qgvUkLAfSs4pXqY"
}
  

📘

Key Information in Getting the Token

From the response there's key information that is essential to keep and they are:

  1. token: a temporary string that will allow you to instantiate the onfido SDK as we'll see below
  2. entity.entityId: The FrankieOne reference that you'll need to save to interact with the record you've created.
  3. applicantID: The Onfido reference that we'll persist on this entity moving forward.
  4. requestId: The unique reference for making this API call. Should you have any issues please send this along with a description of your issue to [email protected]

2. Use the Onfido Token to capture information

In the example below we'll implement the Web SDK in a plain HTML page with commented information. You'll need the token from the first API call above.

<!DOCTYPE html>
<head>
    <meta charset="utf-8" />
    <title>FrankieOne Onfido Biometrics Guide</title>
    <!-- Replace "<version>" with the actual version you want to use, example: 9.0.0 -->
    <script src="https://assets.onfido.com/web-sdk-releases/10.2.0/onfido.min.js"></script>
    <script src="https://assets.onfido.com/web-sdk-releases/10.2.0/onfidoAuth.min.js"></script>
    <link rel="stylesheet" href="https://assets.onfido.com/web-sdk-releases/10.2.0/style.css" />
</head>
<body>
    <!-- This is the ID of the element that the Onfido SDK will be mounted on -->
    <div id="onfido-mount">

    </div>
</body>
<script>
    //THIS IS THE SECTION WHERE THE ONFIDO DOCUMENT CAPTURE IS DONE AND COMPLETED BY THE END USER
    window.onload = function () {
        //This would be the token you got from the `/entity/new/idvalidate/getToken` or `/entity/{entityId}/idvalidate/getToken` endpoint
        let token = "eyJhbGciOiJFUzUxMiJ9eyJleHAiOjE2Nz....."

        //Refer to https://documentation.onfido.com/sdk/web/#initialization-options for documentation on the initialisation sections
        var onfidoOut = Onfido.init({
            containerId: 'onfido-mount',  //The id of the element you want to mount the Onfido widget
            crossDeviceClientIntroProductName:"Your App's Name", //The name of your app or organisation will be shown when the end user switches from a desktop device to a mobile one to capture their details
            crossDeviceClientIntroProductLogoSrc:"https:///static.yourappurl.io/logo", //URL to your logo that will be shown when the user switches from desktop to mobile
            useModal: false,
            token: token,  //Passing in the token 
            //You can customise the flow of the widget based on https://documentation.onfido.com/sdk/web/#flow-customization 
            steps: [
                'welcome',
                {
                    "type": "document",
                    "options": {
                        "documentTypes": {
                            "driving_licence": {
                                "country": "AUS"  
              // The Web SDK only accepts one country as an option for initialising a document. To change the country you'd need to change it during run time. Please see https://documentation.onfido.com/sdk/web/#changing-options-in-runtime for more details
                            },
                            "passport": true // Since all passports look similar you can't limit the country of passports that can be configured. 
                        }
                    }
                },
                {
                    "type": "face",
                    "options": {
                        "requestedVariant": 'video' //This captures a video and enables you to run the liveliness check for onfido. if liveliness is not required then pass in "standard"
                    }
                },
                'complete'],

            onComplete: function (data) {
                // After this point is where you can trigger your back end to run the initProcess API call for Frankie to initialise checks / create checks. //FOLLOW UP OF WHAT TO DO IS DOCUMENTED BELOW :)
                console.log('everything is complete')
                console.log(data)
                //The data you get back will look a little like the snippet below. The informaiton below might be helpful when troubleshooting issues
                /*
                {
                    "document_front": {
                        "id": "053ad85c-95ae-4d2a-85ab-1cea211d3e00", "type": "driving_licence", "side": "front", "variant": "standard"                    },
                    "document_back": {
                        "id": "1d56b930-b1c8-4012-a22a-210b347c55e1", "type": "driving_licence", "side": "back", "variant": "standard"
                    },
                    "face": {
                        "id": "478bc444-c9d5-43a9-bb12-7c6fe7ef41ba", "variant": "video"
                    }
                }
                */

            },
            onError: function (data) {
                console.log('Woops something went wrong while initialising or using the onfido widget')
                console.log(data)
                //Mostlikely token is wrong or expired you will get content that looks like 
                //{"type": "exception", "message": "Authorization error: please re-check your credentials"
            },
            onUserExit: function (data) {
                console.log('Uh Oh customer left the flow please see the output')
              //This might be a good trigger to have your front end bring the customer back directly into the Onfido Flow 
                console.log(data)
            },

            
        })

    }
</script>
</html>

3. Initiate biometrics report process

Once the images have been captured by the user your backend needs to notify FrankieOne that the image capture process has been completed and we can start the process of running the analysis of the images captured and download them from Onfido.

FrankieOne will also go through the process of comparing the data entered by the customer and the information that has been detected as part of the OCR process.

The endpoint to initiate this process is the Update Entity and Initiate IDV Process endpoint.

Sample Request

POST https://api.demo.frankiefinancial.io/compliance/v1.2/entity/<entity_id>/idvalidate/initProcess

{
	"entity": {
		"entityId": "<entity_id>"
	}
}

The payload above is the minimum content required to trigger this API call. You could use it to update additional information you have received between the getToken API call and the initProcess API call.

Sample Response

❗️

500 Error Response

If you get a 500 Error response similar to the one below then it means that the document capture process has not occurred and there's no images at Onfido.

You would need the user to complete the Onfido SDK flow before running the initProcess API call.

{
	"commit": "5642e72",
	"errorCode": "SYS-1071",
	"errorMsg": "Could not reach srv_idv service",
	"httpStatusCode": 500,
	"requestId": "01GPVQ53ZR37KW2DXHG2CW2HGN"
}
 {
	"applicantId": "a07e1dd2-1307-473a-8e5b-3eba61676123",
	"entity": {
		"addresses": [
			...
		],
		"dateOfBirth": {
			...
		},
		"entityId": "938cb742-14f8-b6fb-4730-9ecfcb15b269",
		"entityProfile": "safe_harbor_id",
		"entityType": "INDIVIDUAL",
		"extraData": [
			...
			{
				"kvpKey": "applicantId",
				"kvpType": "general.string",
				"kvpValue": "a07e1dd2-1307-473a-8e5b-3eba61676123"
			},
			{
				"kvpKey": "biometric_check_last_initiated",
				"kvpType": "general.string",
				"kvpValue": "2023-01-17T03:07:44" 
				//This is the date you did the initProcess API Call. 
			},
			{
				"kvpKey": "docs_uploaded",
				"kvpType": "general.string",
				"kvpValue": "2023-01-17T03:07:44.175Z"
			}
		],
		"identityDocs": [
			{
				"country": "AUS",
				"documentId": "850f4caa-030b-832c-ff94-b1034c525ed3",
				"documentStatus": "DOC_SCANNED",
				"extraData": [
					{
						"kvpKey": "idv_webcapture_check_id",
						"kvpType": "general.string",
						"kvpValue": "39ec5dd2-fa19-4365-9cfd-9b66c2303a53"
					},
					{
						"kvpKey": "idv_webcapture_doc_type",
						"kvpType": "general.string",
						"kvpValue": "facial_similarity"
					},
					{
						"kvpKey": "SubsequentCheckDocumentIDs",
						"kvpType": "general.string"
					}
				],
				...
				"idType": "DRIVERS_LICENCE"
			},
			{
				"country": "AUS",
				"createdFromScan": true,
				"docScan": [
					{
						"scanCreated": "2023-01-17T02:55:20.000Z",
						"scanDataRetrievalState": "EXCLUDED",
						"scanDocId": "a765e96c-c865-9599-9ee3-d47ccee7747a",
						"scanFilename": "478bc444-c9d5-43a9-bb12-7c6fe7ef41ba.jpg",
						"scanMIME": "image/jpeg",
						"scanType": "PHOTO"
					},
					{
						"scanCreated": "2023-01-17T02:55:20.000Z",
						"scanDataRetrievalState": "EXCLUDED",
						"scanDocId": "8452670f-07af-5d60-10bb-7bcf1d5ce832",
						"scanFilename": "blob",
						"scanMIME": "video/webm",
						"scanType": "VIDEO"
					}
				],
				"documentId": "65cea117-f20c-9b21-f175-ac6a7e5ac545",
				"documentStatus": "DOC_SCANNED",
				"extraData": [
					{
						"kvpKey": "id_provider_id",
						"kvpType": "general.string",
						"kvpValue": "478bc444-c9d5-43a9-bb12-7c6fe7ef41ba"
					},
					{
						"kvpKey": "idv_webcapture_doc_type",
						"kvpType": "general.string",
						"kvpValue": "facial_similarity"
					},
					{
						"kvpKey": "idv_reports_count",
						"kvpType": "general.integer",
						"kvpValue": "1"
					},
					{
						"kvpKey": "idv_webcapture_check_id",
						"kvpType": "general.string",
						"kvpValue": "39ec5dd2-fa19-4365-9cfd-9b66c2303a53"
					},
					{
						"kvpKey": "idv_webcapture_doc_type",
						"kvpType": "general.string",
						"kvpValue": "facial_similarity"
					}
				],
				...
				"idSubType": "Photo Comparison",
				"idType": "ATTESTATION"
			},
			{
				"country": "AUS",
				"createdFromScan": true,
				"documentId": "434fc495-c918-0c98-63d8-20b9f62127ac",
				"documentStatus": "DOC_SCANNED",
				"extraData": [
					{
						"kvpKey": "idv_reports_count",
						"kvpType": "general.integer",
						"kvpValue": "1"
					},
					{
						"kvpKey": "idv_webcapture_check_id",
						"kvpType": "general.string",
						"kvpValue": "39ec5dd2-fa19-4365-9cfd-9b66c2303a53"
					}
				],
				...
				"idSubType": "ID Validation",
				"idType": "ATTESTATION"
			}
		],
		"name": {
			...
		}
	},
	"requestId": "01GPYV4MT21P84HCKJB29FPW5W",
	"token": ""
}

Understanding the initProcess API response

Assuming that the user has only put in one document ideally you'll have three objects in the identityDocs objects array:

  1. The id document that was processed either passport, national ID or Driver's license, if you did not create one in the process of getting a token or running the initProcess one will be created for you.
  2. idType: ATTESTATION and idSubType: ID Validation - This is a report containing the analysis done on the document above to see if it has any signs of fraud or quality issues.
  3. idType: ATTESTATION and idSubType: Photo Comparison - this is the comparison of the selfie with the document that's been uploaded.

The init process is an async process therefore we recommend having webhooks configured with Frankie to be able to accept the events that signify that the check has been completed.

You can contact out Developer Support team on [email protected] to get some webhooks configured on your account. Please refer to https://apidocs.frankiefinancial.com/docs/notifications-webhooks on documentation about webhooks

Once you have the event confiming that the check has been completed you should run the getChecks endpoint to get information on the outcome of the check.

Below are some Key notes about the resulting Payload from the get GetChecks endpoint.

👍

Key notes on getChecks result payload

  1. entityProfileResult.actionRecommended : This field will let determine if all the checks have passed or not.
  2. entityProfileResult.checkResults[]: Will contain an array of all the checks that the recipe you chose should run and their results. If the field above isn't a pass drilling into this array will let you know what hasn't been completed or has failed.
  3. entityResult.identityDocsCheck[] will contain an array with the documents and check results of all documents on the entity.
    1. entityResult.identityDocsCheck[x].idDocument: This is the document object for the ID you're interacting with. It could be one of the idtypes highlighted earlier.
    2. entityResult.identityDocsCheck[x].idDocument.documentId: This is the UUID of this particular document and if you would like to interact with it you need to reference it.
    3. entityResult.identityDocsCheck[x].idDocument.docScan: if the full parameter was used you'll get base64 content of the document if they're available. e.g image of the selfie , image of the document etc
    4. entityResult.identityDocsCheck[x].checkResult[]: This will contain results about checks that have been done on this document. If you have government ID data source verification you'll see two objects in this array. One for the data sources and another one for the biometrics

Below is a HTML page that puts together the steps put together into one document and would enable you to run a check provide you have demo API credentials.

Full HTML Onfido Implementation
<!DOCTYPE html>

<head>
    <meta charset="utf-8" />
    <title>FrankieOne Onfido Biometrics Guide</title>
    <!--Below gets the latest versions of onfido-->
    <!-- Replace "<version>" with the actual version you want to use, example: 9.0.0 -->
    <script src="https://assets.onfido.com/web-sdk-releases/10.2.0/onfido.min.js"></script>
    <script src="https://assets.onfido.com/web-sdk-releases/10.2.0/onfidoAuth.min.js"></script>

    <link rel="stylesheet" href="https://assets.onfido.com/web-sdk-releases/10.2.0/style.css" />

    <script>
        /*
        Run the Curl command below and get the information below from the payload returned. This will save you hours trying to get CORS working on this html page (yes this is intentional)
        
        Thing to note about the payload sent: 
        - You need to specify either applicationId or referrer
        -- applicationId: If this is for a native application SDK, then we need the applicationId as reported by the SDK. This will then be tied to the token so it cannot be used in another application or handset.
        -- referrer is the URL of where your app is hosted and the traffic to onfido will be coming from.  
        
        curl --location --request POST 'https://api.demo.frankiefinancial.io/compliance/v1.2/entity/new/idvalidate/getToken' \
        --header 'api_key: <YOUR_API_KEY>' \
        --header 'X-Frankie-CustomerId: <YOU_CUSTOMER_ID>' \
        --header 'Content-Type: application/json' \
        --data-raw '{
            "applicationId": "YourApp",
            "entity": {
                "entityProfile": "safe_harbor_id",
                "entityType": "INDIVIDUAL",
                "name": {
                    "familyName": "Johnson",
                    "middleName": "twopass",
                    "givenName": "<random_first_name>"
                },
                "dateOfBirth": {
                    "dateOfBirth": "2000-01-01"
                },
                "addresses": [
                    {
                        "addressType": "RESIDENTIAL1",
                        "country": "AUS",
                        "streetNumber": "27",
                        "streetName": "MILMAN",
                        "streetType": "STREET",
                        "suburb": "",
                        "town": "MARLBOROUGH",
                        "region": "",
                        "state": "QLD",
                        "postalCode": "4705"
                    }
                ],
                "extraData": [
                    {// Consents are required to run checks with FrankieOne and a general good practice to pass on consent from your front end to Frankie which we will pass on to the vendors should they require it.
                        "kvpKey": "consent.general",                        "kvpValue": "true",                        "kvpType": "general.bool"
                    },
                    {
                        "kvpKey": "consent.docs",                        "kvpValue": "true",                        "kvpType": "general.bool"
                    },
                    {
                        "kvpKey": "consent.creditheader",                        "kvpValue": "true",                        "kvpType": "general.bool"
                    },
                    {
                        "kvpKey": "customer_reference",
                        "kvpValue": "<customer_reference>", //This should be your own internal customer reference for this individual in your system
                        "kvpType": "id.external"
                    }
                ]
            }
        }'
        
        
        THE RESPONSE WILL LOOK A LITTLE LIKE THIS. THE THREE DOTS IMPLY SOME INFORMATION HAS BEEN REMOVED TO MAKE THIS DOCUMENT EASIER
        
        {
            "applicantId": "a07e1dd2-1307-473a-8e5b-3eba61676123",
            "entity": {
                "addresses": [
        ...
                ],
                "dateOfBirth": {
        ...
                },
                "entityId": "938cb742-14f8-b6fb-4730-9ecfcb15b269",
                "extraData": [
                    {
                        "kvpKey": "consent.general",
                        "kvpType": "general.bool",
                        "kvpValue": "true"
                    },
                    {
                        "kvpKey": "consent.docs",
                        "kvpType": "general.bool",
                        "kvpValue": "true"
                    },
                    {
                        "kvpKey": "consent.creditheader",
                        "kvpType": "general.bool",
                        "kvpValue": "true"
                    },
                    {
                        "kvpKey": "customer_reference",
                        "kvpType": "id.external",
                        "kvpValue": "k58nmpsdnwjcnsfzx85ds"
                    },
                    {
                        "kvpKey": "applicantId",
                        "kvpType": "general.string",
                        "kvpValue": "a07e1dd2-1307-473a-8e5b-3eba61676123"
                    }
                ],
                "name": {
        ...
                }
            },
            "requestId": "01GPYD0W0JTYG47XXE29QDW47S",
            "token": "eyJhbGciOiJFUzUxMiJ9.eyJleHAiOjE2NzM5MTU0NTcsInBheWxvYWQiOnsiYXBwIjoiYTA3ZTFkZDItMTMwNy00NzNhLThlNWItM2ViYTYxNjc2MTIzIiwiY2xpZW50X3V1aWQiOiIwNTJlNmIwNC1jYzJjLTRjN2YtOGE4Mi04YWYyYjdkY2UxYTkiLCJpc19zYW5kYm94Ijp0cnVlLCJpc190cmlhbCI6ZmFsc2UsInNhcmRpbmVfc2Vzc2lvbiI6ImVhNjgxOWRhLWMyYWEtNDE3OS04NzE1LWIxOWU2MzhjNTg1NCJ9LCJ1dWlkIjoicGxhdGZvcm1fc3RhdGljX2FwaV90b2tlbl91dWlkIiwidXJscyI6eyJkZXRlY3RfZG9jdW1lbnRfdXJsIjoiaHR0cHM6Ly9zZGsub25maWRvLmNvbSIsInN5bmNfdXJsIjoiaHR0cHM6Ly9zeW5jLm9uZmlkby5jb20iLCJob3N0ZWRfc2RrX3VybCI6Imh0dHBzOi8vaWQub25maWRvLmNvbSIsImF1dGhfdXJsIjoiaHR0cHM6Ly9hcGkub25maWRvLmNvbSIsIm9uZmlkb19hcGlfdXJsIjoiaHR0cHM6Ly9hcGkub25maWRvLmNvbSIsInRlbGVwaG9ueV91cmwiOiJodHRwczovL2FwaS5vbmZpZG8uY29tIn19.MIGHAkIAs4RTlzLFv0hsMoIn4TES9F1OACTVOoRy2LtlwIcCXwIp9GD-p8J7XqLFDFPf7slqL1FFutahT741P_O_MgjwuX0CQWZau9uNezHvsQZKA-fw4ugS-YMzLy825OC1klovhJ6_ZBAU_w2Y7wlhmnpoyyLW8D850Rg16qgvUkLAfSs4pXqY"
        }
        
        
        INFORMATION YOU NEED FROM THE RESPONSE IS 
        - token: a temporary string that will allow yuo to instantiate the onfido SDK below
        - entity.entityId: The FrankieOne reference that you'll need to save to interact with the record you've created. 
        - applicantID: The Onfido reference that we'll persist on this entity moving forward. 
        - requestId: The unique reference for making this API call. Shuold you have any issues please send this along with a description of your issue to [email protected] 
        
        
        */



    </script>
</head>

<body>

    <div id="onfido-mount">

    </div>
</body>
<script>
    //THIS IS THE SECTION WHERE THE ONFIDO DOCUMENT CAPTURE IS DONE AND COMPLETED BY THE END USER
    window.onload = function () {

        //This would be the token you got from the `/entity/new/idvalidate/getToken` or `/entity/{entityId}/idvalidate/getToken` endpoint
        let token = "eyJhbGciOiJFUzUxMiJ9.eyJleHAiOjE2NzM5OTcyMjUsInBheWxvYWQiOnsiYXBwIjoiYTA3ZTFkZDItMTMwNy00NzNhLThlNWItM2ViYTYxNjc2MTIzIiwiY2xpZW50X3V1aWQiOiIwNTJlNmIwNC1jYzJjLTRjN2YtOGE4Mi04YWYyYjdkY2UxYTkiLCJpc19zYW5kYm94Ijp0cnVlLCJpc190cmlhbCI6ZmFsc2UsInNhcmRpbmVfc2Vzc2lvbiI6IjJiZDY0YjZmLTYzZjUtNDllYy1iMGVkLWI0YjEyZGIxZDJiMiJ9LCJ1dWlkIjoicGxhdGZvcm1fc3RhdGljX2FwaV90b2tlbl91dWlkIiwidXJscyI6eyJkZXRlY3RfZG9jdW1lbnRfdXJsIjoiaHR0cHM6Ly9zZGsub25maWRvLmNvbSIsInN5bmNfdXJsIjoiaHR0cHM6Ly9zeW5jLm9uZmlkby5jb20iLCJob3N0ZWRfc2RrX3VybCI6Imh0dHBzOi8vaWQub25maWRvLmNvbSIsImF1dGhfdXJsIjoiaHR0cHM6Ly9hcGkub25maWRvLmNvbSIsIm9uZmlkb19hcGlfdXJsIjoiaHR0cHM6Ly9hcGkub25maWRvLmNvbSIsInRlbGVwaG9ueV91cmwiOiJodHRwczovL2FwaS5vbmZpZG8uY29tIn19.MIGHAkIB0f3MlUcbpCwsM-v0OkBu6tBPi6vif2PNLcvdBYugwEQDgai5Rqoxqdb26qyu7TomMxDitqR_MBdQxTPN3igSR80CQRS5kjNk5dZXIL39TsFW_nZKosEwgvFDryYVKe-Zdp8URgnI0nKShgcExUxmKBwmlVGjCgGiht48-7gnEph1R2YG"

        //Refer to https://documentation.onfido.com/sdk/web/#initialization-options for documentation on the initialisation sections
        Onfido.init({
            containerId: 'onfido-mount',  //The id of the element you want to mount the Onfido widget
            useModal: false,
            token: token,  //Passing in the token 
            //You can customise the flow of the widget based on https://documentation.onfido.com/sdk/web/#flow-customization 
            steps: [
                'welcome',
                {
                    "type": "document",
                    "options": {
                        "documentTypes": {
                            "passport": {
                                "country": "AUS"   //This configuration specifies that you can only upload an Australian Driver's license and no passports although with this option you don't really need the welcome screen
                            }
                        }
                    }
                },
                {
                    "type": "face",
                    "options": {
                        "requestedVariant": 'video' //This captures a video and enables you to run the liveliness check for onfido. if liveliness is not required then pass in "standard"
                    }
                },
                'complete'],

            onComplete: function (data) {
                // After this point is where you can run the init API call for Frankie to initialise checks / create checks. //FOLLOW UP OF WHAT TO DO IS DOCUMENTED BELOW :)
                console.log('everything is complete')
                console.log(data)
                //The data you get back will look a little like the snippet below no need to save this information
                /*
                {
                    "document_front": {
                        "id": "053ad85c-95ae-4d2a-85ab-1cea211d3e00",
                        "type": "driving_licence",
                        "side": "front",
                        "variant": "standard"
                    },
                    "document_back": {
                        "id": "1d56b930-b1c8-4012-a22a-210b347c55e1",
                        "type": "driving_licence",
                        "side": "back",
                        "variant": "standard"
                    },
                    "face": {
                        "id": "478bc444-c9d5-43a9-bb12-7c6fe7ef41ba",
                        "variant": "video"
                    }
                }
                */


            },
            onError: function (data) {
                console.log('Woops something went wrong while initialising or using the onfido widget')
                console.log(data)
                //Mostlikely token is wrong or expired you will get content that looks like 
                //{"type": "exception", "message": "Authorization error: please re-check your credentials"
            },
            onUserExit: function (data) {
                console.log('Uh Oh customer left the flow please see the output')
                console.log(data)
            },

        })
    }

    /*
        ONCE THE CAPTURE PROCESS IS DONE IN YOUR BACK END MAKE THE API CALL BELOW. INFO:You can use this endpoint to update other information you need to put on the profile. 
        
        curl --location --request POST 'https://api.demo.frankiefinancial.io/compliance/v1.2/entity/<entity_id>/idvalidate/initProcess' \
        --header 'api_key: <YOUR_API_KEY>' \
        --header 'X-Frankie-CustomerId: <YOU_CUSTOMER_ID>' \
        --header 'Content-Type: application/json' \
        --data-raw '{
            "entity": {
                "entityId":"<entity_id>"
            }       
        }'

        If you get a 500 Error below, chances are your customer hasn't done the document capture process and there's no documents to process. 
        {
            "commit": "5642e72",
            "errorCode": "SYS-1071",
            "errorMsg": "Could not reach srv_idv service",
            "httpStatusCode": 500,
            "requestId": "01GPVQ53ZR37KW2DXHG2CW2HGN"
        } 

        If you get a 200 response the data should look a little like this 

        {
        "applicantId": "a07e1dd2-1307-473a-8e5b-3eba61676123",
        "entity": {
            "addresses": [
                ...
            ],
            "dateOfBirth": {
                ...
            },
            "entityId": "938cb742-14f8-b6fb-4730-9ecfcb15b269",
            "entityProfile": "safe_harbor_id",
            "entityType": "INDIVIDUAL",
            "extraData": [
                {
                    "kvpKey": "consent.general",
                    "kvpType": "general.bool",
                    "kvpValue": "true"
                },
                {
                    "kvpKey": "consent.docs",
                    "kvpType": "general.bool",
                    "kvpValue": "true"
                },
                {
                    "kvpKey": "consent.creditheader",
                    "kvpType": "general.bool",
                    "kvpValue": "true"
                },
                {
                    "kvpKey": "customer_reference",
                    "kvpType": "id.external",
                    "kvpValue": "k58nmpsdnwjcnsfzx85ds"
                },
                {
                    "kvpKey": "applicantId",
                    "kvpType": "general.string",
                    "kvpValue": "a07e1dd2-1307-473a-8e5b-3eba61676123"
                },
                {
                    "kvpKey": "biometric_check_last_initiated",
                    "kvpType": "general.string",
                    "kvpValue": "2023-01-17T03:07:44" 
                    //This is the date you did the initProcess API Call. 
                },
                {
                    "kvpKey": "docs_uploaded",
                    "kvpType": "general.string",
                    "kvpValue": "2023-01-17T03:07:44.175Z"
                }
            ],
            "identityDocs": [
                {
                    "country": "AUS",
                    "documentId": "850f4caa-030b-832c-ff94-b1034c525ed3",
                    "documentStatus": "DOC_SCANNED",
                    "extraData": [
                        {
                            "kvpKey": "idv_webcapture_check_id",
                            "kvpType": "general.string",
                            "kvpValue": "39ec5dd2-fa19-4365-9cfd-9b66c2303a53"
                        },
                        {
                            "kvpKey": "idv_webcapture_doc_type",
                            "kvpType": "general.string",
                            "kvpValue": "facial_similarity"
                        },
                        {
                            "kvpKey": "SubsequentCheckDocumentIDs",
                            "kvpType": "general.string"
                        }
                    ],
                    ...
                    "idType": "DRIVERS_LICENCE"
                },
                {
                    "country": "AUS",
                    "createdFromScan": true,
                    "docScan": [
                        {
                            "scanCreated": "2023-01-17T02:55:20.000Z",
                            "scanDataRetrievalState": "EXCLUDED",
                            "scanDocId": "a765e96c-c865-9599-9ee3-d47ccee7747a",
                            "scanFilename": "478bc444-c9d5-43a9-bb12-7c6fe7ef41ba.jpg",
                            "scanMIME": "image/jpeg",
                            "scanType": "PHOTO"
                        },
                        {
                            "scanCreated": "2023-01-17T02:55:20.000Z",
                            "scanDataRetrievalState": "EXCLUDED",
                            "scanDocId": "8452670f-07af-5d60-10bb-7bcf1d5ce832",
                            "scanFilename": "blob",
                            "scanMIME": "video/webm",
                            "scanType": "VIDEO"
                        }
                    ],
                    "documentId": "65cea117-f20c-9b21-f175-ac6a7e5ac545",
                    "documentStatus": "DOC_SCANNED",
                    "extraData": [
                        {
                            "kvpKey": "id_provider_id",
                            "kvpType": "general.string",
                            "kvpValue": "478bc444-c9d5-43a9-bb12-7c6fe7ef41ba"
                        },
                        {
                            "kvpKey": "idv_webcapture_doc_type",
                            "kvpType": "general.string",
                            "kvpValue": "facial_similarity"
                        },
                        {
                            "kvpKey": "idv_reports_count",
                            "kvpType": "general.integer",
                            "kvpValue": "1"
                        },
                        {
                            "kvpKey": "idv_webcapture_check_id",
                            "kvpType": "general.string",
                            "kvpValue": "39ec5dd2-fa19-4365-9cfd-9b66c2303a53"
                        },
                        {
                            "kvpKey": "idv_webcapture_doc_type",
                            "kvpType": "general.string",
                            "kvpValue": "facial_similarity"
                        }
                    ],
                    ...
                    "idSubType": "Photo Comparison",
                    "idType": "ATTESTATION"
                },
                {
                    "country": "AUS",
                    "createdFromScan": true,
                    "documentId": "434fc495-c918-0c98-63d8-20b9f62127ac",
                    "documentStatus": "DOC_SCANNED",
                    "extraData": [
                        {
                            "kvpKey": "idv_reports_count",
                            "kvpType": "general.integer",
                            "kvpValue": "1"
                        },
                        {
                            "kvpKey": "idv_webcapture_check_id",
                            "kvpType": "general.string",
                            "kvpValue": "39ec5dd2-fa19-4365-9cfd-9b66c2303a53"
                        }
                    ],
                    ...
                    "idSubType": "ID Validation",
                    "idType": "ATTESTATION"
                }
            ],
            "name": {
                ...
            }
        },
        "requestId": "01GPYV4MT21P84HCKJB29FPW5W",
        "token": ""
    }
        

    Ideally you'll have three identityDocs objects in the array 
        - The id document that was processed either passport, national ID or Driver's license 
        - idType: ATTESTATION and idSubType: ID Validation - This is a report containing the analysis done on the document above to see if it has any signs of fraud or quality issues
        - idType: ATTESTATION and idSubType: Photo Comparison - this is the comparison of the selfie with the document that's been uploaded. 

    The init process is an async process therefore we recommend having webhooks configured with Frankie to be able to accept the events that signify that the check has been completed.
    Contact our TechOps team on [email protected] to get some webhooks configured on your account.  

    Once you have the event confiming that the check has been completed you should run the getChecks endpoint to get information on the outcome of the check. 

    Key notes about the resulting payload. 
        - entityProfileResult.actionRecommended : This field will let determine if all the checks have passed or not. 
        - entityProfileResult.checkResults[]: Will contain an array of all the checks that the recipe you chose should run and their results. If the field above isn't a pass drilling into this array will let you know what hasn't been completed or has failed. 
        - entityResult.identityDocsCheck[] will contain an array with the documents and check results of all documents on the entity. 
            -- entityResult.identityDocsCheck[x].idDocument: This is the document object for the ID you're interacting with. It could be one of the idtypes highlighted earlier.  
                --- entityResult.identityDocsCheck[x].idDocument.documentId: This is the UUID of this particular document and if you would like to interact with it you need to reference it. 
                --- entityResult.identityDocsCheck[x].idDocument.docScan: if the full parameter was used you'll get base64 content of the document if they're available. e.g image of the selfie , image of the document etc 
            
            -- entityResult.identityDocsCheck[x].checkResult[]: This will contain results about checks that have been done on this document. If you have Gov ID data source verification you'll see two objects in this array. One for the data sources and another one for the biometrics

        */
</script>

</html>