KYC Links for New Customers

An alternative to using the Customers API to KYC/B Customers (both individuals and businesses) is to use KYC Links. KYC Links support individual and business customers from all over the world (US + international).

KYC Links takes a full_name, email, and type. The full_name can be populated with either the customer name or unique identifier. When the Customer is created, the first_name and last_name are derived from the verification information submitted during the KYC process. After generating the KYC link, pass the link on to your customers to enable them to complete the KYC process. Links enable you to get up and running faster by eliminating the need to build the UI/UX needed to collect much of this compliance information.

There response will contain two different links that will need to be completed:

  • tos_link will contain a link to Bridge's Terms of Service, which can be seen here. These terms need to be accepted by the customer before they can be approved.
  • kyc_link will contain a link to a hosted KYC/B flow with our partner. Customers will need to go through this flow and submit information to Bridge before they can be approved.

NOTE: for a business customer use case, please enter the full legal name of the business entity under the full_name parameter

To create a KYC Link, use the following endpoint:

curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \
--header 'Content-Type: application/json' \
--header 'Api-Key: <API Key>' \
--header 'Idempotency-Key: <generate a uuid>' \
--data-raw '{
  "full_name": "John Doe",
  "email": "[email protected]",
  "type": "individual", // or "business",
}'

This endpoint will respond with:

{
  "id": "kyc_link_uuid",
  "email": "[email protected]",
  "type": "individual", // or "business"
  "kyc_link": "persona.com/blah",
  "tos_link": "bridge.xyz/tos?blah=blah",
  "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected"
  "tos_status": "pending", // or "approved"
  "created_at": "Wed, 14 Jun 2023 20:44:57.375900000 UTC +00:00"
}

To create a KYC Link with Proof-of-Address step enabled for non-EEA customers, an endorsements array field including an element with the value sepacan be specified in the request:

curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \
--header 'Content-Type: application/json' \
--header 'Api-Key: <API Key>' \
--header 'Idempotency-Key: <generate a uuid>' \
--data-raw '{
  "full_name": "John Doe",
  "email": "[email protected]",
  "type": "individual", // or "business"
  "endorsements": ["sepa"]
}'

You can check the status of your customers kyc_link by using the GET /v0/kyc_links/:kyc_links_id endpoint

curl --location --request GET 'https://api.bridge.xyz/v0/kyc_links/:kyc_link_id' \
--header 'Content-Type: application/json' \
--header 'Api-Key: <API Key>' \

This responds with a kyc_link object.

{
  "id": "kyc_link_uuid",
  "email": "[email protected]",
  "type": "individual", // or "business"
  "kyc_link": "persona.com/blah",
  "tos_link": "bridge.xyz/tos?blah=blah",
  "kyc_status": "approved",
  "tos_status": "approved",
  "created_at": "Wed, 14 Jun 2023 20:44:57.375900000 UTC +00:00",
  "customer_id": "fa03ab80-2c75-4010-8d2f-224282cf25bf"
}

When creating a KYC Link, you can optionally provide a redirect_uri in the request body that points to the location that your customers should be redirected to once the KYC flow is complete. The API will take that redirect_uri and embed it into the KYC Link that gets returned.

To embed a redirect_uriin KYC Link, pass in the optional redirect_uri in the POST request:

curl --location --request POST 'https://api.bridge.xyz/v0/kyc_links' \
--header 'Content-Type: application/json' \
--header 'Api-Key: <API Key>' \
--header 'Idempotency-Key: <generate a uuid>' \
--data-raw '{
  "full_name": "John Doe",
  "email": "[email protected]",
  "type": "individual", // or "business",
  "redirect_uri": "https://bridge.xyz/example"
}'

This endpoint will respond with:

{
  "id": "kyc_link_uuid",
  "email": "[email protected]",
  "type": "individual", // or "business"
  "kyc_link": "persona.com/blah?redirect-uri=https%3A%2F%2Fbridge.xyz%2Fexample",
  "tos_link": "bridge.xyz/tos?blah=blah",
  "kyc_status": "not_started", // or "under_review", "incomplete", "approved" or "rejected"
  "tos_status": "pending", // or "approved"
  "created_at": "Wed, 14 Jun 2023 20:44:57.375900000 UTC +00:00"
}

This will result in the customer being redirected to https://bridge.xyz/example at the end of the KYC flow.

Embedding as an iframe

You can implement a kyc_link by using an iframe, which can then be embedded in a custom modal or page.

There are 2 critical steps to follow when embedding the KYC link into an Iframe:

  • Pass an iframe-origin query parameter with the value encoded as the current window.location.origin.
  • Replace the sub-path /verify with /widget.
<iframe
  allow="camera;"
  src={
    `https://bridge.withpersona.com/widget?environment=production&inquiry-template-id={template_id}&fields[iqt_token]={iqt_token}&iframe-origin=${encodeURIComponent(window.location.origin)}`
    }
  sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-top-navigation-by-user-activation"
/>

Turnaround response time

The average decision time for KYC is typically less than one minute. If a manual review is required for KYC, the decision may take until next business day. KYB reviews typically happen same business day, up to next business day.

KYC Status Transitions

All KYC flows for individual customers begin with customers in a not_started status. Once the customer has taken any action to begin the KYC process they move into an incomplete status. Based on the information provided a customer can then move to approved, rejected, or under_review.

KYC Status Transitions

KYC Status Transitions

KYB Status Transitions

KYB flows are similar to individual customers, with the additional step of collecting the KYC information for any "ultimate beneficial owners". Every business that goes through our KYB process provides information about the business, information about UBOs, goes through a manual review before being approved or rejected.

KYB Status Transitions

KYB Status Transitions

Sad Paths

While KYC/KYB generally works quickly, there are edge cases that are important to account for. Here are a few examples of how the KYC/KYB statuses of a customer could progress:

not_started -> active

  • This is our happy path. The customer information was submitted, and quickly passed via automated checks within seconds.

not_started -> under_review -> active
not_started -> under_review -> rejected
not_started -> rejected

Under Review

In this scenario, the customer starts off not_started, but after verifying the initial set of data (name, address, TIN, birth date) there was something off about the customer information. In this scenario, fetching the customer via GET /customers/:id would result in something like this:

{
  "id": "cust_john_uuid",
  // ...
  "status": "under_review",
  "requirements_due": [
    "id_verification"
  ],
  "created_at": "Thu, 04 May 2023 15:40:40.832827000 UTC +00:00",
  "updated_at": "Thu, 04 May 2023 15:40:40.832827000 UTC +00:00"
}

You can see that the customer's KYC status is in under_review and that id_verification has become an immediate requirement now. That means that id verification is necessary before Bridge can approve this customer.

After submitting your customer for id verification (government photo id like a driver's license or passport), one of two things will happen:

  • Bridge will approve your customer, and the KYC status on the customer will move to active
  • Bridge will reject your customer, and the KYC status on the customer will move to rejected.

Immediate Rejection

Sometimes, your customer could immediately move from not_started to rejected and skip under_review entirely. The primary reason this happens is when the tax identification number is entered incorrectly. Without a valid tax identification number, Bridge is unable to verify any of the other details you have sent up for your customer (birth date, address, name).

In this scenario, the customer starts off not_started, but after attempting to verify submitted information, there was an issue detected with the submission. It is possible to move directly to rejected and skip under_review entirely. In the rejected scenario, fetching the customer via [GET /customers/:id](https://apidocs.bridge.xyz/reference/get_customers-customerid) would result in something like this:

{
  "id": "kyc_link_123",
  "first_name": "John",
  "last_name": "Doe",
  "email": "[email protected]",
  "type": "individual",
  "kyc_link": "www.kyclink.com/blah",
  "tos_link": "www.toslink.com/blah",
  "kyc_status": "rejected",
  "rejection_reasons": [
    {
      "developer_reason": "Missing required ID details.",
      "reason": "Cannot validate ID -- upload a clear photo of the full ID",
      "created_at": "2020-01-02T00:00:00.000Z"
    },
    {
      "developer_reason": "Blurry face portrait.",
      "reason": "Cannot validate ID -- upload a clear photo of the full ID",
      "created_at": "2020-01-02T00:00:00.000Z"
    }
  ],
  "tos_status": "approved",
  "customer_id": "cust_123"
}

You can see that the customer's KYC status is rejected and that there are two fields shared with rejection reasons:

  • developer_reason is meant to be used by developers for internal purposes only. This field can contain sensitive information intended for only the developer and is provided to help with troubleshooting potential issues or protecting against potential abuse.
  • reason can be shared by a developer directly with their customers.

For reference, see our page on Rejection Reasons for developer_reason and reason mappings for KYC rejection reasons.