4. Performing KYC

This page describes the KYC; getting ratings and background on your customer. It also describes the KBA process, in the event a customer fails the KYC process.

After your Customer has provided the information to complete onboarding, you must authenticate and verify the information they've provided. This is a critical step, known as KYC, in which you validate your customer's identity and documents, and ensure they're compliant with federal regulations. This is performed using the KYC API.

To run the KYC process, you need the customer_id, your own authorization headers, and various personal information related to the customer.

📘

Repeat KYC requests after a successful KYC request

Once a customer has successfully passed the KYC process, no further KYC attempts are allowed. Any further call for KYC authentication responds with an error and returns the timestamp of the previously successful KYC process.

The KYC endpoint is idempotentidempotent - Has the same result when called multiple times with the same idempotent key and requests using the same Idempotency-Key within a 24 hour period will fail.

KYC workflow

  1. Create a webhook to listen to KYC events.
  2. Submit a KYC request, an example of which is shown below.
curl  
--request POST \ 
--url 'https://sandbox.bond.tech/api/v0/customers/{CUSTOMER_ID}/verification-kyc' \
--header 'Identity: YOUR-IDENTITY' \
--header 'Authorization: YOUR-AUTHORIZATION' \
--header 'Content-Type: application/json' \
--data-raw '{
    "program_id": "b50063df-0b39-43f7-9458-25b08a75d42a",
    "ssn": "000-00-0000",
    "phone": "555-555-5555",
    "phone_country_code": "1",
    "email": "[email protected]",
    "ip": "127.1.1.1"
}
require "uri"
require "net/http"

url = URI("https://sandbox.bond.tech/api/v0/customers/{CUSTOMER_ID}/verification-kyc")

http = Net::HTTP.new(url.host, url.port);
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["Identity"] = YOUR-IDENTITY
request["Authorization"] = YOUR-AUTHORIZATION
request["Content-Type"] = "application/json"
request.body = "{\n    \"program_id\": \"b50063df-0b39-43f7-9458-25b08a75d42a\",\n    \"ssn\": \"000-00-0000\",\n    \"phone\": \"555-555-5555\",\n    \"phone_country_code\": \"1\",\n    \"email\": \"[email protected]\",\n    \"ip\": \"127.1.1.1\"\n}"

response = http.request(request)
puts response.read_body
const options = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Identity: 'YOUR-IDENTITY',
    Authorization: 'YOUR-AUTHORIZATION'
  },
  body: JSON.stringify({
    program_id: '72585109-8222-4221-b15b-48e87ffed790',
    ssn: '123-45-6789',
    phone: '555-111-2222',
    phone_country_code: '1',
    email: '[email protected]',
    ip: '257.134.1.57'
  })
};

fetch('https://sandbox.bond.tech/api/v0/customers/931e2341-c3eb-4681-97d4-f6e09d90da14/verification-kyc', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));
import requests

url = "https://sandbox.bond.tech/api/v0/customers/{CUSTOMER_ID}/verification-kyc"

payload="{\n    \"program_id\": \"b50063df-0b39-43f7-9458-25b08a75d42a\",\n    \"ssn\": \"000-00-0000\",\n    \"phone\": \"555-555-5555\",\n    \"phone_country_code\": \"1\",\n    \"email\": \"[email protected]\",\n    \"ip\": \"127.1.1.1\"\n}"
headers = {
  'Identity': YOUR-IDENTITY,
  'Authorization': YOUR-AUTHORIZATION,
  'Content-Type': 'application/json'
}

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

print(response.text.encode('utf8'))
var client = new RestClient("https://sandbox.bond.tech/api/v0/customers/{CUSTOMER_ID}/verification-kyc");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Identity", "e6b234b4-650e-48e4-93eb-6550a07cc075");
request.AddHeader("Authorization", "sasAXw8ElVJihL3+3mzItCsVtKzh4Kqa0xdECC/F1GbwA6LQTAs/KxkZ9QFYST3l");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n    \"program_id\": \"b50063df-0b39-43f7-9458-25b08a75d42a\",\n    \"ssn\": \"000-00-0000\",\n    \"phone\": \"555-555-5555\",\n    \"phone_country_code\": \"1\",\n    \"email\": \"[email protected]\",\n    \"ip\": \"127.1.1.1\"\n}",  ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Unirest.setTimeouts(0, 0);
HttpResponse<String> response = Unirest.post("https://sandbox.bond.tech/api/v0/customers/{CUSTOMER_ID}/verification-kyc")
  .header("Identity", "e6b234b4-650e-48e4-93eb-6550a07cc075")
  .header("Authorization", "sasAXw8ElVJihL3+3mzItCsVtKzh4Kqa0xdECC/F1GbwA6LQTAs/KxkZ9QFYST3l")
  .header("Content-Type", "application/json")
  .body("{\n    \"program_id\": \"b50063df-0b39-43f7-9458-25b08a75d42a\",\n    \"ssn\": \"000-00-0000\",\n    \"phone\": \"555-555-5555\",\n    \"phone_country_code\": \"1\",\n    \"email\": \"[email protected]\",\n    \"ip\": \"127.1.1.1\"\n}")
  .asString();
  1. The Bond Studio process responds with a POST request containing initialized to your callback URL, as in the example below. The result of the KYC request comes via the webhook.
{
    "customer_id": "2df10ec1-130f-41bb-b0cf-f3af48350eb7",
    "kyc_status": "initialized"
}

Once the KYC process is successful, you receive a webhook containing customer_id and an event of kyc.verification.success, as shown in the example below:

{
    "event": "kyc.verification.success",
    "customer_id": "a5bcf5a8-c4e0-4025-8183-5346176ee3db",
    "occurred_at": "2021-02-02-00:50:58.484840+00:00"
}

If the KYC process is unsuccessful, the KBAKBA - Knowledge Based Authentication. A form of identity validation done by prompting the user to answer questions based on their private information. Performed in the event that the KYC process fails. Generally KBA is interchangeable with OOW. For example, "Out of these 4 addresses, in which have you resided previously?". process is triggered.

KBA

The KBA process is triggered when a customer fails the KYC validation. KBA allows your customer to personally validate their identity by answering multiple-choice questions that should be straightforward for them to answer, but difficult for others to answer.

KBA includes up to three rounds of four multiple-choice questions each. If a customer answers a question incorrectly, they're posed new questions. After three failed attempts, the KBA fails (and hence the overall KYC process fails). Submitting a fourth attempt results in a 400 error and the Maximum number of attempts exceeded message. In such a case, manual verification may be required.

📘

Performing a KBA process in the sandbox

To run the KBA authentication in the sandbox environment, create a customer with a first name of xyz and then initiate a KYC.

An example of a KBA response (with only one question for simplicity) is shown below.

{
    "customer_id": "2df10ec1-130f-41bb-b0cf-f3af48350eb7",
    "kyc_status": "kba triggered",
    "reasons": {
        "ofac": "passed",
        "bureau": "kba triggered",
        "ip": "failed",
        "phone": "passed",
        "email": "passed"
    },
    "kba": [
        {
            "question_id": "1",
            "question": "Which one of the following retail credit cards do you have? If there is not a matched retail credit card, please select 'NONE OF THE ABOVE'",
            "choices": [
                {
                    "choice_id": "1",
                    "choice": "AMAZON"
                },
                {
                    "choice_id": "2",
                    "choice": "TARGET"
                },
                {
                    "choice_id": "3",
                    "choice": "COSTCO"
                },
                {
                    "choice_id": "4",
                    "choice": "KOHLS"
                },
                {
                    "choice_id": "5",
                    "choice": "NONE OF THE ABOVE"
                }
            ]
        }
    ]
}

To send the customer's chosen set of questions back to Bond Studio, make a POST request to /customers/{customer_id}/verification-kba with the {question_id}/{answer_id} pair. An example of this is shown below.

curl --request POST \
     --url https://sandbox.bond.tech/api/v0/customers/931e2341-c3eb-4681-97d4-f6e09d90da14/verification-kba \
     --header 'Authorization: YOUR-AUTHORIZATION' \
     --header 'Content-Type: application/json' \
     --header 'Identity: YOUR-IDENTITY' \
     --data '
{
     "kba_responses": [
          {
               "question_id": "1",
               "choice_id": "3"
          },
          {
               "question_id": "2",
               "choice_id": "4"
          },
          {
               "question_id": "3",
               "choice_id": "1"
          },
          {
               "question_id": "4",
               "choice_id": "2"
          }
     ]
}
'
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://sandbox.bond.tech/api/v0/customers/931e2341-c3eb-4681-97d4-f6e09d90da14/verification-kba")

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

request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request["Identity"] = 'YOUR-IDENTITY'
request["Authorization"] = 'YOUR-AUTHORIZATION'
request.body = "{\"kba_responses\":[{\"question_id\":\"1\",\"choice_id\":\"3\"},{\"question_id\":\"2\",\"choice_id\":\"4\"},{\"question_id\":\"3\",\"choice_id\":\"1\"},{\"question_id\":\"4\",\"choice_id\":\"2\"}]}"

response = http.request(request)
puts response.read_body
const options = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Identity: 'YOUR-IDENTITY',
    Authorization: 'YOUR-AUTHORIZATION'
  },
  body: JSON.stringify({
    kba_responses: [
      {question_id: '1', choice_id: '3'},
      {question_id: '2', choice_id: '4'},
      {question_id: '3', choice_id: '1'},
      {question_id: '4', choice_id: '2'}
    ]
  })
};

fetch('https://sandbox.bond.tech/api/v0/customers/931e2341-c3eb-4681-97d4-f6e09d90da14/verification-kba', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));
import requests

url = "https://sandbox.bond.tech/api/v0/customers/931e2341-c3eb-4681-97d4-f6e09d90da14/verification-kba"

payload = {"kba_responses": [
        {
            "question_id": "1",
            "choice_id": "3"
        },
        {
            "question_id": "2",
            "choice_id": "4"
        },
        {
            "question_id": "3",
            "choice_id": "1"
        },
        {
            "question_id": "4",
            "choice_id": "2"
        }
    ]}
headers = {
    "Content-Type": "application/json",
    "Identity": "YOUR-IDENTITY",
    "Authorization": "YOUR-AUTHORIZATION"
}

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

print(response.text)
var client = new RestClient("https://sandbox.bond.tech/api/v0/customers/931e2341-c3eb-4681-97d4-f6e09d90da14/verification-kba");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Identity", "YOUR-IDENTITY");
request.AddHeader("Authorization", "YOUR-AUTHORIZATION");
request.AddParameter("application/json", "{\"kba_responses\":[{\"question_id\":\"1\",\"choice_id\":\"3\"},{\"question_id\":\"2\",\"choice_id\":\"4\"},{\"question_id\":\"3\",\"choice_id\":\"1\"},{\"question_id\":\"4\",\"choice_id\":\"2\"}]}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"kba_responses\":[{\"question_id\":\"1\",\"choice_id\":\"3\"},{\"question_id\":\"2\",\"choice_id\":\"4\"},{\"question_id\":\"3\",\"choice_id\":\"1\"},{\"question_id\":\"4\",\"choice_id\":\"2\"}]}");
Request request = new Request.Builder()
  .url("https://sandbox.bond.tech/api/v0/customers/931e2341-c3eb-4681-97d4-f6e09d90da14/verification-kba")
  .post(body)
  .addHeader("Content-Type", "application/json")
  .addHeader("Identity", "YOUR-IDENTITY")
  .addHeader("Authorization", "YOUR-AUTHORIZATION")
  .build();

Response response = client.newCall(request).execute();

Invalid requests to run KYC

Requests made with the same idempotency key within a 24 period or with missing fields returns a response similar to that shown in the example below.

409
{
       "type": "RESOURCE_CONFLICT",
       "code": "idempotency_key_exists",
       "message": "A request was made with this idempotency key in the past 24 hours",
   }
400
{
'Message': {ssn: ['Missing data for required field.']},
 'Status': 400,
 'Code': 'kyc_post_schema',
 'Type': 'Request Error'
}

Did this page help you?