# Getting Started

Start with ComplyCube for KYC, AML, and identity verification. Explore products, integration paths, detailed guides, and testing resources.

ComplyCube is a complete identity verification and anti-fraud platform that helps businesses of all sizes automate KYC and AML flows and processes.

This documentation is your starting point. It will guide you from **setting up your account**, to **understanding our products**, selecting the **integration path** that best fits your needs, and finally running your **first identity verification**.

***

### 1. Create an account

Set up a ComplyCube account and start using our verification services right away in a secure Sandbox environment.

<a href="https://portal.complycube.com/signup" class="button primary">Create account</a> <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7DZURzLR4QSX40QG7b" class="button secondary">Explore all products</a>

{% hint style="success" %}

#### Your Sandbox environment

When you create an account, your **Sandbox environment** is set up automatically and comes preloaded with:<br>

* **Sample workflows**: Ready-made templates to explore verification flows.
* **Test data**: Pre-populated customers and checks so you can experiment safely.
* **Full feature access**: The same functionality as Live, but isolated for testing.<br>

This allows you to explore the platform, understand how workflows and verification checks operate, and gain hands-on experience before going live.
{% endhint %}

***

### 2. Verification modes

ComplyCube supports **two verification modes**, which determine how checks are executed whether you’re using the ComplyCube Web Portal out of the box or integrating via the Hosted solution, SDKs, or APIs.

<table><thead><tr><th valign="top">Workflow orchestration</th><th valign="top">Check-driven</th></tr></thead><tbody><tr><td valign="top">Define customer journeys in the <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/dKzFxEJx6m2x4dyaeydQ#designing-workflows">workflow designer</a> and verify customers through the ComplyCube Web Portal or your app. Flows can be updated or extended without redeploying, making this the <strong>recommended option for most use cases</strong>.<br><br>Customer participation is <strong>required</strong>. The customer must complete the flow to trigger the verification checks.<br></td><td valign="top">Run individual checks (e.g. <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JAF0I0xV8IXZOscPw">AML screening</a>) on an <strong>ad-hoc basis</strong> in the Portal or integrate them into your app. Flexible but more code-intensive, best suited for <strong>advanced</strong> integrations, <strong>partner use cases</strong>, or occasional <strong>one-off verifications</strong>.<br><br>Unlike workflows, checks can be run without direct customer involvement.</td></tr><tr><td valign="top"><p><strong>How it works</strong><br></p><ol><li>Select an existing <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/dKzFxEJx6m2x4dyaeydQ#creating-workflows">workflow template</a> or create a new one.</li><li>Each run creates a <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/dKzFxEJx6m2x4dyaeydQ#workflow-session">workflow session</a> with all data, documents, and results.</li><li>Results are returned at the <strong>session level</strong> via Portal, API, or webhooks.</li></ol></td><td valign="top"><p><strong>How it works</strong><br></p><ol><li>Trigger individual checks directly (e.g. <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JAF0I0xV8IXZOscPw">AML screening</a>, <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7IRKF3XH0kjZi9JFgx">document verification</a>).</li><li>You manage onboarding logic and flow changes in your app code.</li><li>Results are returned per check via the Portal, API, or webhooks.</li></ol></td></tr></tbody></table>

{% hint style="info" %}
You can combine **workflow orchestration** and **check-driven** modes, for example, running a workflow for biometric and document verification, but triggering specific extra checks (e.g. AML screening) on demand.
{% endhint %}

{% hint style="info" %}
Both modes are available directly in the Portal, so you can start running checks immediately **without writing code**. The [integration paths](#id-3.-integration-paths) below let you embed these same modes into your own systems.
{% endhint %}

***

### 3. Integration paths

All integration paths below support both [verification modes](#id-2.-verification-modes).

<table data-header-hidden><thead><tr><th width="213.0625">Path</th><th>Description</th></tr></thead><tbody><tr><td><img src="/files/-M7HpVwrtnuvcJW8mjXD" alt="" data-size="line"> <a href="/pages/-M7HJ1rh49Q6PWLATGW_"><mark style="color:blue;"><strong>Web Portal</strong></mark></a></td><td>Run checks and flows directly from the Portal without any integration. Easiest entry point and <strong>ideal for low volumes</strong>.</td></tr><tr><td><img src="/files/-MeVnbgUFqVfLY-QX1SC" alt="" data-size="line"> <a href="/pages/-MeVkD1FqGOlJlf3hwOI"><mark style="color:blue;"><strong>Hosted Solution</strong></mark></a></td><td>A secure and branded hosted KYC page that enables you to verify clients with minimal code. This is the <strong>quickest integration path</strong>.</td></tr><tr><td><img src="/files/-M7HfCT69A9g_Ngct05Z" alt="" data-size="line"> <a href="/pages/yV5uzHhJXgNgvpjwyIDc"><mark style="color:blue;"><strong>Mobile SDKs</strong></mark></a></td><td>Embed our mobile SDKs with built-in AI features to run KYC flows <strong>natively</strong> directly inside your app.<br><br>You can test the Mobile SDK immediately using the <a href="/pages/rpOERk9GcsWJGiGu7tWx">ComplyCube Mobile app</a>, without needing to integrate anything.</td></tr><tr><td><img src="/files/iLAwRx2uTap1PYl1NO61" alt="" data-size="line"> <a href="/pages/-M_0DOc7XDWVDpIcnV6L"><mark style="color:blue;"><strong>Web SDK</strong></mark></a></td><td>Drop in our verification flows directly into your <strong>web application</strong>.</td></tr><tr><td><img src="/files/-M7Ht50Rg-MH3KokHIgs" alt="" data-size="line"> <a href="/pages/-M7E-lamDL4AWzEkVzrL"><mark style="color:blue;"><strong>Pure API Integration</strong></mark></a></td><td>Bring your own UI and connect directly to ComplyCube APIs. Offers <strong>the most granular control</strong> and is suited for <strong>advanced use cases</strong> or <strong>partner implementations</strong>.</td></tr></tbody></table>

{% hint style="info" %}
Use [Model Context Protocol (MCP)](/documentation/integration-resources/model-context-protocol-mcp) to connect ComplyCube docs to **Claude**, **Cursor**, **ChatGPT**, and other **AI assistants**. This helps you search guides, inspect full pages, and draft integration code using current documentation.
{% endhint %}

***

### 4. Build & test

* [Testing data](/documentation/integration-resources/testing-data) - Use Sandbox triggers to simulate outcomes.
* [Configure webhooks](/documentation/integration-resources/webhooks) - Receive results asynchronously in real-time.
* [Integration checklist](/documentation/integration-resources/integration-checklist) - Follow our checklist to ensure your integration is production-ready.


# Web Portal Quick Guide

Use the ComplyCube Web Portal to run KYC, AML, and identity verification checks without code.

### Overview

**ComplyCube Web Portal** gives you instant access to our verification services directly from your browser. This guide will help you get started quickly, without any coding required.

The [Portal](https://portal.complycube.com/) provides a ready-to-use solution for businesses of all sizes. It extends our services, letting you manage customers, run checks, and review results with ease.

<figure><img src="/files/ArK08OQ9FkMtEQWYZtZI" alt=""><figcaption><p>Web Portal Home</p></figcaption></figure>

### Environments

Both the Portal and API provide **Sandbox** and **Live** environments.

* The Sandbox lets you explore the platform safely, without costs or real customer data.
* Once you’ve completed testing, switch to Live to run production checks.
* In the Portal, you can switch environments using the toggle in the top-right corner.

<figure><img src="/files/03jUI1rTDXjS1sZN9uo5" alt="" width="563"><figcaption><p>Environment and Project Toggle</p></figcaption></figure>

For this quick guide, ensure you are working in the **Sandbox environment**.

{% hint style="info" %}
The **Sandbox environment** does not have real data. All checks will return dummy responses. You can use our [Testing Data](/documentation/integration-resources/testing-data) to simulate scenarios.
{% endhint %}

### Running verifications

Learn how to use the Portal for common use cases.

#### **Individual checks**

Run quick, one-off checks directly in the Portal. These single-purpose verifications are manual and require no code.<br>

* <img src="/files/mZODJxM89feb5twGMAin" alt="" data-size="line"> [**AML Screening Check**](/documentation/quick-guides/web-portal-quick-guide/perform-aml-screening) - Screen global sanctions, watchlists, PEPs, and adverse media.
* <img src="/files/f3IBYWb9EecQdxeK6RW4" alt="" data-size="line"> [**Document Check**](/documentation/quick-guides/web-portal-quick-guide/perform-document-check) - Verify government-issued ID documents.
* <img src="/files/0ReUPfJ2syp0m8Noz0CV" alt="" data-size="line"> [**Multi-Bureau Check**](/documentation/quick-guides/web-portal-quick-guide/perform-multi-bureau-check) - Match client details against trusted credit and government sources.

You can also send customers a [verification link](/documentation/quick-guides/web-portal-quick-guide/send-verification-link-legacy) to complete one or more checks. This method is limited (not all checks are supported) and considered a **legacy option**. For multi-check journeys, we recommend using **workflows** instead.

#### **Workflow checks**

Use [workflows](/documentation/product-guides/compliance-studio/workflows) to guide customers through complete KYC journeys by combining multiple verification checks into a single, structured session.

From the Portal, you can generate hosted links that take customers through these verification flows seamlessly. All results are captured together in one session, making it easier to track progress, apply business rules, and maintain compliance.

[Run verification checks with workflows ->](/documentation/quick-guides/web-portal-quick-guide/send-verification-link-workflows)


# Perform AML Screening

Run AML screening in the Web Portal to support KYC and KYB by screening customers against sanctions, PEPs, and watchlists.

### Overview

This quick guide walks you through performing an [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) in the ComplyCube Web Portal for KYC and KYB checks.

### Interactive guide

{% @arcade/embed url="<https://app.arcade.software/share/sfOaqllb5zeyWMrM8GXx>" flowId="sfOaqllb5zeyWMrM8GXx" fullWidth="false" %}

### Steps explained <a href="#steps-explained" id="steps-explained"></a>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in running any check is to create a client (i.e. a customer).

Navigate to the [Clients](https://portal.complycube.com/clients) page and click the "**Add client**" button. Enter the following details and add client:

* **First Name:** John
* **Last Name:** Doe
* **Email:** <john.doe@test.com>

<img src="/files/-M8pzXSDzktZQ4u4z22y" alt="Add Client View" width="375">

{% hint style="info" %}
The more data you provide about a client, the richer and more accurate ComplyCube AML Screening Checks will be. We **highly recommend** that you provide the client's **date of birth** before conducting an AML Screening Check.
{% endhint %}
{% endstep %}

{% step %}

#### Perform AML Screening Check <a href="#perform-aml-screening-check" id="perform-aml-screening-check"></a>

To run an AML Screening Check, click the "**Perform verification**" button. A wizard will appear, allowing you to choose the type of check you want to perform.

<figure><img src="/files/d9Y7gdEWaZMNOdmPoQ6p" alt=""><figcaption></figcaption></figure>

First, select "**Verify now using existing data**".

There are two types of AML Screening Checks - [Standard AML Screening](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check#service-variants) and [Extensive AML Screening](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check#service-variants). For this example, select "**Extensive AML Screening**", then click "**Run check**".

For this guide, mark "**Enable continuous monitoring**" as "**Disabled**".
{% endstep %}

{% step %}

#### View check results <a href="#view-check-results" id="view-check-results"></a>

Once the check has concluded, you will automatically be taken to the check results page.

<figure><img src="/files/gixzVw8COY8i3LKWXnd8" alt=""><figcaption><p>AML Screening Result View</p></figcaption></figure>
{% endstep %}
{% endstepper %}

That's it! You've completed your first AML Screening Check.

If you're using the **Sandbox** environment, you can try out various scenarios using our [testing data](/documentation/integration-resources/testing-data).


# Perform Document Check

Run document verification in the Web Portal to validate identity documents and support KYC checks.

### Overview

This quick guide walks you through performing a [Document Check](/documentation/product-guides/identity-verification/document-check) in the ComplyCube Web Portal.

### Interactive guide <a href="#interactive-guide" id="interactive-guide"></a>

{% @arcade/embed url="<https://app.arcade.software/share/ViobdTBtT5GFP5NVwWGh>" flowId="ViobdTBtT5GFP5NVwWGh" fullWidth="false" %}

### Steps explained

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in running any check is to create a client (i.e. a customer).

Navigate to the [Clients](https://portal.complycube.com/clients) page and click the "**Add client**" button. Enter the following details and add client:

* **First Name:** John
* **Last Name:** Doe
* **Email:** <john.doe@test.com>

<img src="/files/-M8pzXSDzktZQ4u4z22y" alt="Add Client View" width="375">
{% endstep %}

{% step %}

#### Perform Document Check <a href="#perform-document-check" id="perform-document-check"></a>

To run a Document Check, click the "**Perform verification**" button. A wizard will appear, allowing you to choose the type of check you want to perform.

<figure><img src="/files/iywZKRXeRETjHzqoKwaj" alt=""><figcaption></figcaption></figure>

First, select "**Verify now using existing data**", then choose "**Document Check**".

#### 2a. Upload a document

Now click the "**upload a new document**" link, and enter the following details:

* **Type:** Passport
* **Issuing Country:** United Kingdom
* **Front side:** Download the sample image below. Then drag and drop.

{% file src="/files/-M8q91TB6V9P-3B1vDlT" %}
Sample - Front side of passport
{% endfile %}

<img src="/files/-MPM1HBbI8zw7KNh03Im" alt="Add Document View" width="375">

Click "Add Document" to upload the document.

#### 2b. Perform a check

Select the newly created document from the dropdown list, then click the "**Run Check**" button.

<figure><img src="/files/MCBJBffwtS9oAx5cJGPR" alt=""><figcaption><p>Select ID View</p></figcaption></figure>
{% endstep %}

{% step %}

#### View check results <a href="#view-check-results" id="view-check-results"></a>

Once the check has concluded, you will automatically be taken to the check results page.

![Displayed results are for illustrative purposes and do not reflect actual accuracy](/files/IprMXIzSFOafvUGyyoEy)
{% endstep %}
{% endstepper %}

That's it! You've completed your first Document Check.

If you're using the **Sandbox** environment, you can try out various scenarios using our [testing data](/documentation/integration-resources/testing-data).


# Perform Multi-Bureau Check

Run a multi-bureau identity verification check in the Web Portal to match customer data across bureaus.

### Overview

This quick guide walks you through performing a [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) in the ComplyCube Web Portal.

### Interactive guide <a href="#interactive-guide" id="interactive-guide"></a>

{% @arcade/embed url="<https://app.arcade.software/share/e0Nlu5oc29uXEDYx8QCl>" flowId="e0Nlu5oc29uXEDYx8QCl" fullWidth="false" %}

### Steps explained

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in running any check is to create a client (i.e. a customer).

Navigate to the [Clients](https://portal.complycube.com/clients) page and click the "**Add client**" button. Enter the following details and add client:

* **First Name:** John
* **Last Name:** Doe
* **Email:** <john.doe@test.com>

<img src="/files/-M8pzXSDzktZQ4u4z22y" alt="Add Client View" width="375">

After adding the client, click "**Edit**" to add a date of birth. Set it to "01-01-1990".

<img src="/files/-MlGOfDI5ZdgPH31vABQ" alt="Client Edit View" width="375">
{% endstep %}

{% step %}

#### Perform a Multi-Bureau Check <a href="#perform-a-multi-bureau-check" id="perform-a-multi-bureau-check"></a>

To run a Multi-Bureau Check, click the "**Perform verification**" button. A wizard will appear, allowing you to choose the type of check you want to perform.

<figure><img src="/files/TRmimID84kEOqbsLQBTD" alt=""><figcaption></figcaption></figure>

First, select "**Verify now using existing data**", then choose "**Multi-Bureau Check**".

#### 2a. Add an address

Select the "**add a new address**" link. You can then enter the following details:

* **Country**: United States
* **Line:** 47th Test Avenue 323
* **City**: Manhattan
* **State:** New York
* **Postal** **Code**: 10001

<img src="/files/-MlGERSAHDPK477P5WoF" alt="Add Address View" width="375">

#### 2b. Perform a check

Select the newly created address from the dropdown list, then click the "**Run Check**" button.

<figure><img src="/files/6K1mjyjmO4oZl8hzpW58" alt=""><figcaption><p>Select Address View</p></figcaption></figure>
{% endstep %}

{% step %}

#### View check results <a href="#view-check-results" id="view-check-results"></a>

Once the check has concluded, you will automatically be taken to the check results page.

![Multi-Bureau Screening Result View](/files/-MlGPPAU3THsp8gqKHS7)
{% endstep %}
{% endstepper %}

That's it! You've completed your first Multi-Bureau Check.

If you're using the **Sandbox** environment, you can try out various scenarios using our [testing data](/documentation/integration-resources/testing-data).


# Send Verification Link (Workflows)

Send a secure verification link from Workflows to complete KYC and identity verification remotely.

### Overview

This quick guide shows you how to send a **verification link** to your customers, using [workflows](/documentation/product-guides/compliance-studio/workflows), through the ComplyCube Web Portal, allowing them to provide their details and complete multiple verification checks in one go.

### Interactive guide

{% @arcade/embed url="<https://app.arcade.software/share/nN5GjYhoeW3NAZSv6U94>" flowId="nN5GjYhoeW3NAZSv6U94" fullWidth="false" %}

### Steps explained <a href="#steps-explained" id="steps-explained"></a>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in running any check is to create a client (i.e. a customer).

Navigate to the [Clients](https://portal.complycube.com/clients) page and click the "**Add client**" button. Enter the following details and add client:

* **First Name:** John
* **Last Name:** Doe
* **Email:** <john.doe@test.com>

<img src="/files/-M8pzXSDzktZQ4u4z22y" alt="Add Client View" width="375">
{% endstep %}

{% step %}

#### Send a verification link <a href="#send-a-verification-link" id="send-a-verification-link"></a>

Click the "**Perform verification**" button. You will then be presented with a dialogue.

<figure><img src="/files/wFtPwJq82aDGvTyFhESE" alt=""><figcaption></figcaption></figure>

Select "**Send verification link to client**", then choose "**Use an existing workflow template**".

Pick one of your existing workflow templates (or create a new one) and click "**Create link**" to generate it.

<figure><img src="/files/DdgQeARxxRrzLKrtruyR" alt=""><figcaption></figcaption></figure>

A verification link will be generated. You can either:

1. Copy it to share manually, or
2. Click "**Email link to client**" to send it directly to the customer’s inbox.

{% hint style="info" %}
The email sent to your customer will include instructions for completing the verification and will reference your **company’s legal name**. You can customize the look and feel of the verification flow through your [branding](https://portal.complycube.com/settings/branding) page.
{% endhint %}
{% endstep %}

{% step %}

#### View session results <a href="#view-session-results" id="view-session-results"></a>

After the customer completes the flow, ComplyCube processes the verification checks and automatically notifies you via [email notifications](https://portal.complycube.com/settings/notifications) or [webhook events](/documentation/integration-resources/webhooks).
{% endstep %}
{% endstepper %}

If you're using the **Sandbox** environment, you can try out various scenarios using our [testing data](/documentation/integration-resources/testing-data).


# Send Verification Link (Legacy)

Send a secure legacy verification link to complete KYC and identity verification remotely.

### Overview

This quick guide shows you how to send a **verification link** to your customers through the ComplyCube Web Portal, allowing them to provide their details and complete multiple verification checks in one go.

{% hint style="warning" %}
This is a **legacy approach**. For a more compliant and maintainable method, we recommend using [workflows](/documentation/product-guides/compliance-studio/workflows), which offer structured journeys and centralized policy enforcement. See our updated [verification link guide](/documentation/quick-guides/web-portal-quick-guide/send-verification-link-workflows) for details.
{% endhint %}

### Interactive guide

{% @arcade/embed url="<https://app.arcade.software/share/l5i7d0RyCvRZbt1ZZHfT>" flowId="l5i7d0RyCvRZbt1ZZHfT" fullWidth="false" %}

### Steps explained <a href="#steps-explained" id="steps-explained"></a>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in running any check is to create a client (i.e. a customer).

Navigate to the [Clients](https://portal.complycube.com/clients) page and click the "**Add client**" button. Enter the following details and add client:

* **First Name:** John
* **Last Name:** Doe
* **Email:** <john.doe@test.com>

<img src="/files/-M8pzXSDzktZQ4u4z22y" alt="Add Client View" width="375">

After adding the client, click "**Edit**" to add a date of birth. Set it to "01-01-1990".

<img src="/files/-MlGOfDI5ZdgPH31vABQ" alt="Client Edit View" width="375">

{% hint style="info" %}
The more data you provide about a client, the richer and more accurate ComplyCube AML Screening Checks will be. We **highly recommend** that you provide the client's **date of birth** before conducting an AML Screening Check.
{% endhint %}
{% endstep %}

{% step %}

#### Send a verification link <a href="#send-a-verification-link" id="send-a-verification-link"></a>

Click the "**Perform verification**" button. You will then be presented with a dialogue.

<figure><img src="/files/JMDvFnKHSR6wN7Crad3Q" alt=""><figcaption></figcaption></figure>

Select "**Send verification link to client**", then choose "**Select checks manually**".

Pick the check types you want to run, and click "**Create link**" to generate it.

<figure><img src="/files/KCAu60nuvc1EkawOZ0LH" alt=""><figcaption></figcaption></figure>

A verification link will be generated. You can either:

1. Copy it to share manually, or
2. Click "**Email link to client**" to send it directly to the customer’s inbox.

{% hint style="info" %}
The email sent to your customer will include instructions for completing the verification and will reference your **company’s legal name**. You can customize the look and feel of the verification flow through your [branding](https://portal.complycube.com/settings/branding) page.
{% endhint %}
{% endstep %}

{% step %}

#### View check results <a href="#view-check-results" id="view-check-results"></a>

After the customer completes the flow, ComplyCube processes the verification checks and automatically notifies you via [email notifications](https://portal.complycube.com/settings/notifications) or [webhook events](/documentation/integration-resources/webhooks).
{% endstep %}
{% endstepper %}

If you're using the **Sandbox** environment, you can try out various scenarios using our [testing data](/documentation/integration-resources/testing-data).


# Hosted Solution Guide

Build hosted KYC and identity verification flows with minimal code using ComplyCube Flow.

### Overview

**ComplyCube Flow** is our secure, fully hosted KYC and identity verification solution. It provides a customizable, branded page that allows you to verify customers quickly with minimal code.

When you initiate a Flow session, a unique ComplyCube URL is generated. Redirect your customers to this page to collect consent and complete the verification process. Once finished, they are redirected back to your chosen URL.

<figure><img src="/files/Oc59uECd4shN6l3Mcoua" alt=""><figcaption><p>ComplyCube Hosted Solution</p></figcaption></figure>

Flow makes it simple to deliver a first-class KYC experience:

* **Fast to integrate**: Go live quickly with minimal engineering effort.
* **UX-optimized**: Guided, conversion-focused flows with built-in error handling.
* **Mobile ready**: Fully responsive design that works seamlessly across devices.
* **International**: Multi-language support for global coverage.
* **Customizable**: Configure verifications, stages, colors, and branding (logo and text).
* **Data-compliant**: Simplified compliance, as sensitive PII never resides on your infrastructure.

### Interactive demo

{% @arcade/embed url="<https://app.arcade.software/share/DQYWw1OnvTXJpuguEsVp>" flowId="DQYWw1OnvTXJpuguEsVp" fullWidth="false" %}

### Integration steps

The steps below demonstrate how to add the Hosted Solution to your web application.

{% stepper %}
{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
};

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

The response will contain an `id` (the Client ID). It is required for the next step.
{% endstep %}

{% step %}

#### Generate a hosted page session

A **hosted page session** creates a unique ComplyCube URL that you can use to redirect your customer to complete their identity verification.

This solution can be integrated in two ways: through [workflows](/documentation/product-guides/compliance-studio/workflows) for complete verification journeys, or with **check-driven integration** for fine-grained control.

Sample snippets for both approaches are provided below:

{% tabs %}
{% tab title="Workflows (Recommended)" %}
**How it works**

Use workflows to run complete KYC journeys with minimal code.

For workflows, provide a **workflow template ID**. You can copy this from your [workflow templates page](https://portal.complycube.com/workflowTemplates) in the Portal. The Hosted Solution will then run the **active** version of the selected workflow automatically.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/flow/sessions \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"CLIENT_ID",
          "workflowTemplateId": "WORKFLOW_TEMPLATE_ID",
          "successUrl": "https://www.yoursite.com/success",
          "cancelUrl": "https://www.yoursite.com/cancel"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const session = await complycube.flow.createSession("CLIENT_ID", {
    workflowTemplateId: "WORKFLOW_TEMPLATE_ID",
    successUrl: "https://www.yoursite.com/success",
    cancelUrl: "https://www.yoursite.com/cancel"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

flow_session = {
    'clientId': client.id,
    'workflowTemplateId': 'WORKFLOW_TEMPLATE_ID',
    'successUrl':'https://www.yoursite.com/success',
    'cancelUrl':'https://www.yoursite.com/cancel'
}

session = cc_api.flow.create(**flow_session)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');
$session = $ccapi->flow()->createSession([
    'clientId' => $clientId,
    'workflowTemplateId' => 'WORKFLOW_TEMPLATE_ID',
    'successUrl' => 'https://www.yoursite.com/success',
    'cancelUrl' => 'https://www.yoursite.com/cancel'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.FlowSessions;

var fSession = new FlowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var flowSession = new FlowSessionRequest {
  clientId = client.id,
  workflowTemplateId = "WORKFLOW_TEMPLATE_ID",
  successUrl = "http://complycube.com",
  cancelUrl = "http://complycube.com"
};

var result = fSession.CreateAsync(flowSession).Result;
```

{% endtab %}
{% endtabs %}

**Example response**

{% code overflow="wrap" %}

```json
{
    "redirectUrl": "https://id.complycube.com/test_ODdkNjhiOTU0MzY4YmE5NjRmMDMyY2E5MWYwZjgxNjMzZTcyMWJmNzU2YjZmNDQ4NmFjMTU0ZGZhYTU5MmNhY2NiNjI3ZDE4YWJkYmU2M2M3ZWYzZTlmM2M3MzgxMmM3NzZhMjVlYmQyNDI0ODdkOWQ3M2JiMjkxZTYxNzdhYmExMGEzOGRhYmM2OTIwMjgyYmEzZGY3ZDY0NWZhMjcwN2RlMTFkOTcxZWNhOWI2Zjg0NjllZGNkODVjYzMzMDA5YjdlMWY5OGIwMmZjY2UzNGI2YTMxOGQxNGZmNGFhYjczNzU0YmYwMjFkMzU1M2FjMjQ4ZDQ2ZjJjZTY4YWY0MzIxNjVlMDRjOTIyYTExMTlmMWU3YTYwMDY1NGJmYWM0NTA2MDE5NTg5NTkxYzA4MzYyYTUyM2I0NDM4OGExNWIyMTIzYTBhNDc0NDA4NWM2ZTQwMmNjMGVjMTk2YW"
}
```

{% endcode %}
{% endtab %}

{% tab title="Check-Driven Integration" %}
**How it works**

Run specific verification checks directly for finer control.

For a check-driven integration, you specify one or more check types. The Hosted Solution will create a session that runs only the selected checks.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/flow/sessions \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"CLIENT_ID",
          "checkTypes": ["extensive_screening_check", "identity_check", "document_check"],
          "successUrl": "https://www.yoursite.com/success",
          "cancelUrl": "https://www.yoursite.com/cancel"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const session = await complycube.flow.createSession("CLIENT_ID", {
    checkTypes: [
      "extensive_screening_check",
      "identity_check",
      "document_check"
    ],
    successUrl: "https://www.yoursite.com/success",
    cancelUrl: "https://www.yoursite.com/cancel",
    theme: "light"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

flow_session = {
    'clientId': client.id,
    'checkTypes':[
        'extensive_screening_check',
        'identity_check',
        'document_check'
    ],
    'successUrl':'https://www.yoursite.com/success',
    'cancelUrl':'https://www.yoursite.com/cancel',
    'theme': 'light'
}

session = cc_api.flow.create(**flow_session)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');
$session = $ccapi->flow()->createSession([
    'clientId' => $clientId,
    'checkTypes' => [
        'extensive_screening_check',
        'identity_check',
        'document_check'
    ],
    'successUrl' => 'https://www.yoursite.com/success',
    'cancelUrl' => 'https://www.yoursite.com/cancel',
    'theme' => 'light'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.FlowSessions;

var fSession = new FlowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var flowSession = new FlowSessionRequest {
  clientId = client.id,
  checkTypes = new string[] {
    "extensive_screening_check",
    "identity_check",
    "document_check"
  },
  successUrl = "http://complycube.com",
  cancelUrl = "http://complycube.com"
};

var result = fSession.CreateAsync(flowSession).Result;
```

{% endtab %}
{% endtabs %}

**Example response**

{% code overflow="wrap" %}

```json
{
    "redirectUrl": "https://flow.complycube.com/test_ODdkNjhiOTU0MzY4YmE5NjRmMDMyY2E5MWYwZjgxNjMzZTcyMWJmNzU2YjZmNDQ4NmFjMTU0ZGZhYTU5MmNhY2NiNjI3ZDE4YWJkYmU2M2M3ZWYzZTlmM2M3MzgxMmM3NzZhMjVlYmQyNDI0ODdkOWQ3M2JiMjkxZTYxNzdhYmExMGEzOGRhYmM2OTIwMjgyYmEzZGY3ZDY0NWZhMjcwN2RlMTFkOTcxZWNhOWI2Zjg0NjllZGNkODVjYzMzMDA5YjdlMWY5OGIwMmZjY2UzNGI2YTMxOGQxNGZmNGFhYjczNzU0YmYwMjFkMzU1M2FjMjQ4ZDQ2ZjJjZTY4YWY0MzIxNjVlMDRjOTIyYTExMTlmMWU3YTYwMDY1NGJmYWM0NTA2MDE5NTg5NTkxYzA4MzYyYTUyM2I0NDM4OGExNWIyMTIzYTBhNDc0NDA4NWM2ZTQwMmNjMGVjMTk2YW?theme=light"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Redirect the customer to the URL

Redirect your customer to the `redirectUrl` generated in the previous step.

Once the customer has provided all their details on the hosted solution:

1. ComplyCube will perform all the relevant checks.
2. The customer will be redirected back to the specified `successUrl`.

You can retrieve the outcome and check details via the API or Web Portal. If you have [set up webhooks](/documentation/integration-resources/webhooks), a notification will be sent upon completing each check.
{% endstep %}
{% endstepper %}

### Next steps

Follow the full [Hosted Solution integration](/documentation/sdks/web-integrations/hosted-solution-quick-guide) guide to explore its features and **customization** options.


# Mobile SDK Guide

Integrate mobile SDKs for KYC, AML, and identity verification with native customer verification flows.

### Overview

The ComplyCube Mobile SDKs make it quick and easy to build a frictionless customer onboarding and biometric authentication experience in your mobile app.

{% hint style="info" %}
You can test the Mobile SDK immediately using the [ComplyCube Mobile app](/documentation/integration-resources/complycube-mobile-app), without needing to integrate anything.
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=n8kAGXQykkA>" fullWidth="false" %}
ComplyCube Mobile SDK Demo
{% endembed %}

The SDK offers several benefits:

* **Native flows**: Smooth mobile experience with guided capture for selfies, videos, and IDs.
* **Flexible integration**: Orchestrate full journeys with [workflows](/documentation/product-guides/compliance-studio/workflows) or configure individual stages (selfie, document, NFC).
* **Biometric checks**: Liveness via photo and video, with spoof detection.
* **Document and NFC**: OCR and chip reading for passports and other ID cards with secure cross-checks.
* **Smart auto-capture**: Real-time quality checks to reduce errors and ensure optimal input.
* **Custom branding**: Adapt colors, text, and logos to match your app.
* **Global-ready**: Multi-language support with localized UI labels.

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Preview of the Mobile SDK (iOS)</p></figcaption></figure>

### Supported SDKs

ComplyCube provides **native SDKs** to embed identity verification flows directly into your mobile app.

Choose the SDK that fits your platform. Each comes with a sample app to get you started quickly.

<table data-column-title-hidden data-view="cards" data-full-width="false"><thead><tr><th align="center"></th><th data-hidden></th><th data-hidden></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><mark style="color:blue;"><strong>iOS</strong></mark></td><td></td><td></td><td><a href="/files/CSBwOnH4qobJGtQICzP7">/files/CSBwOnH4qobJGtQICzP7</a></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/smuFLHXxPjC1DXhoMroM">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/smuFLHXxPjC1DXhoMroM</a></td></tr><tr><td align="center"><mark style="color:blue;"><strong>Android</strong></mark></td><td></td><td></td><td><a href="/files/e9zaOZFDHkkvIoMEPZFV">/files/e9zaOZFDHkkvIoMEPZFV</a></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/U3Txnp5lpawf9IReQHej">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/U3Txnp5lpawf9IReQHej</a></td></tr><tr><td align="center"><mark style="color:blue;"><strong>React Native</strong></mark></td><td></td><td></td><td><a href="/files/TLq3qZm6i2giq0w6YI9h">/files/TLq3qZm6i2giq0w6YI9h</a></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/miZB76QzZXoEXk6GtIL7">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/miZB76QzZXoEXk6GtIL7</a></td></tr><tr><td align="center"><mark style="color:blue;"><strong>Flutter</strong></mark></td><td></td><td></td><td><a href="/files/qWtI6Ifs4IoDlas7cRLE">/files/qWtI6Ifs4IoDlas7cRLE</a></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/eAVqjz94Rhh0iBmL3ULC">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/eAVqjz94Rhh0iBmL3ULC</a></td></tr></tbody></table>


# Web SDK Guide

Embed our UX-optimized web-based KYC and identity verification flows with the ComplyCube Web SDK.

### Overview <a href="#overview" id="overview"></a>

The **ComplyCube Web SDK** is a lightweight JavaScript library that lets you embed identity verification and KYC flows directly into your web applications. It provides a ready-made, user-friendly widget for capturing documents, selfies, and proof of address, while handling quality detection and fraud signals under the hood.

### Interactive demo

{% @arcade/embed url="<https://app.arcade.software/share/kjtci521jMvvMXDZIr7o>" flowId="kjtci521jMvvMXDZIr7o" fullWidth="false" %}

### Integration steps

The Web SDK can be integrated in two ways: through [workflows](/documentation/product-guides/compliance-studio/workflows) for complete verification journeys, or with **check-driven integration** for fine-grained control.

The steps below demonstrate how to add the Web SDK to your web application.

{% stepper %}
{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
};

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

The response will contain an `id` (the Client ID). It is required for the next step.
{% endstep %}

{% step %}

#### Generate an SDK Token

**Tokens** enable clients to send personal data to ComplyCube via our SDKs securely. Use the [generate token endpoint](/documentation/api-reference/other-resources/tokens) to obtain an SDK token and initialize the Web SDK next.

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"CLIENT_ID",
          "referrer": "*://*/*"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const token = await complycube.token.generate("CLIENT_ID", {
    referrer: "*://*/*"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

token = cc_api.tokens.create('CLIENT_ID','*://*/*')
```

{% endtab %}

{% tab title="PHP" %}

```php
 use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$report = $ccapi->tokens()->generate('CLIENT_ID', '*://*/*');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest  =  { clientId = "CLIENT_ID" , 
                        referrer = "*://*/*" }

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Mount the SDK

To mount our Web SDK, you need to include it on your target page, as shown below.

```html
<!DOCTYPE html>
<html>

  <head>
    <!-- Importing the JavaScript library -->
    <script src="complycube.min.js"></script>
    
    <!-- Importing the default CSS -->
    <link rel="stylesheet" href="style.css" />
  </head>
  
  <script>
    var complycube = {};
    function startVerification() {
      complycube = ComplyCube.mount({
        token: "<YOUR_WEB_SDK_TOKEN>",
        onComplete: function(data) {
          console.log("Capture complete", data)
        },
      });
    }
  </script>
  
  <body>
    <!-- This is where the Web SDK will be mounted -->
    <div id="complycube-mount"></div>

    <!-- Clicking the button will start the ComplyCube verification UI -->
    <button onClick="startVerification()">Start verification</button>
  </body>
  
</html>

```

{% hint style="info" %}
The links to `complycube.min.js` and `style.css` can be found in your [developers portal](https://portal.complycube.com/developers/webSdk).
{% endhint %}
{% endstep %}
{% endstepper %}

### Next steps

Follow the full [Web SDK integration](/documentation/sdks/web-integrations/web-sdk-quick-guide) guide to explore its features and **customization** options.


# API Quick Guide

Start integrating the ComplyCube API for KYC, AML, and identity verification.

### Overview

**ComplyCube’s API** gives you full programmatic access to our verification services. This guide will help you get started quickly, building custom integrations directly into your own systems and applications.

The API provides maximum flexibility for businesses that want **complete control** over the customer experience and orchestration logic. It exposes all of our services through predictable, resource-oriented endpoints, letting you create clients, trigger KYC checks, and retrieve results.

{% hint style="info" %}
To get started right away **without an API key**, try our [Postman Demo Collection](/documentation/integration-resources/postman#demo-collection). It lets you explore the API instantly using a mock account, with no signup required.
{% endhint %}

### Integration steps

The steps below demonstrate how to invoke the ComplyCube API:

{% stepper %}
{% step %}

#### Obtain your Sandbox API key

ComplyCube authenticates all API requests using your account’s [API keys](https://portal.complycube.com/developers). If you omit a key, or use one that is invalid or expired, the request will return an error.

Each account has two keys: one for **Sandbox** requests and one for **Live** requests. API requests always run in either [Sandbox or Live mode](/documentation/api-reference/sandbox-and-live), and objects created in one mode, such as clients, addresses, or checks, cannot be accessed or modified from the other.

{% hint style="warning" %}
Always use your **Sandbox** API keys for development and testing to avoid accidentally modifying live data.
{% endhint %}
{% endstep %}

{% step %}

#### Make a Sandbox API request

To verify that your integration is set up correctly, send a Sandbox API request with your **Sandbox key** to [create a client](/documentation/api-reference/core-resources/clients/create-a-client).

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

ComplyCube returns a [client](/documentation/api-reference/core-resources/clients) object in response to your API request.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2025-01-04T17:24:29.146Z",
    "updatedAt": "2025-01-04T17:24:29.146Z"
}
```

Once you have successfully made an API request, you’re ready to begin integrating ComplyCube.
{% endstep %}
{% endstepper %}

### Running verifications

Learn how to run verification checks using the API.<br>

* <img src="/files/mZODJxM89feb5twGMAin" alt="" data-size="line"> [**AML Screening Check**](/documentation/quick-guides/api-quick-guide/run-an-aml-screening-check) - Screen global sanctions, watchlists, PEPs, and adverse media.
* <img src="/files/f3IBYWb9EecQdxeK6RW4" alt="" data-size="line"> [**Document Check**](/documentation/quick-guides/api-quick-guide/run-a-document-check) - Verify government-issued ID documents.
* <img src="/files/zfBAn14xmkSa6r9yX4qz" alt="" data-size="line"> [**Identity Check**](/documentation/quick-guides/api-quick-guide/run-an-identity-check) - Perform liveness and biometric verification.
* <img src="/files/PONM5MXjt7ZREkcYiwjh" alt="" data-size="line"> [**Proof of Address Check**](/documentation/quick-guides/api-quick-guide/perform-proof-of-address-check) - Extract data and verify proof of address documents.
* <img src="/files/0ReUPfJ2syp0m8Noz0CV" alt="" data-size="line"> [**Multi-Bureau Check**](/documentation/quick-guides/api-quick-guide/perform-multi-bureau-check) - Match client details against trusted credit and government sources.


# Perform AML Screening

Use the API to run AML screening for KYC and KYB against sanctions, PEPs, and watchlists.

### Overview <a href="#overview" id="overview"></a>

This guide shows you how to run an AML Screening Check using the ComplyCube API for KYC and KYB checks.

{% hint style="success" %}
You can try this check right away using our [Demo Postman Collection](/documentation/integration-resources/postman#demo-collection). It’s publicly accessible and **requires no account**.
{% endhint %}

### Integration steps <a href="#integration-steps" id="integration-steps"></a>

<figure><img src="/files/lqjKH09EPidaPXXMyyCu" alt=""><figcaption><p>AML Screening API Guide</p></figcaption></figure>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in creating any check is to add a **client** from your backend server. A client can represent either a **person** or a **company**. For individuals, you must provide a **first** and **last name**, while for companies only the **name** is required.

The response will contain an `id` (the Client ID). It is required for the next step.

{% hint style="info" %}
While not strictly required, we **strongly recommend** including a customer’s **date of birth** when registering an individual.
{% endhint %}

**Example request for creating a client**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe",
               "dob": "1990-01-01"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe",
    dob: "1990-01-01"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR API KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe',
        'dob':'1990-01-01'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john.doe@example.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe',
        'dob' => '1990-01-01'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var newclient = new ClientRequest {
  type = "person",
    email = "john.doe@example.com",
    personDetails = new PersonDetails {
      firstName = "John",
        lastName = "Doe",
        dob = "1990-01-01"
    }
};

var client = await clientApi.CreateAsync(newclient);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe",
        "dob": "1990-01-01"
    },
    "createdAt": "2025-01-04T17:24:29.146Z",
    "updatedAt": "2025-01-04T17:24:29.146Z"
}
```

{% endstep %}

{% step %}

#### Create an **AML Screening Check** <a href="#create-an-aml-screening-check" id="create-an-aml-screening-check"></a>

Create an AML Screening Check by specifying the **Client ID** and the **check type**. ComplyCube supports two AML Screening types: [Standard](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check#service-variants) and [Extensive](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check#service-variants). The example below demonstrates an **Extensive AML Screening**.

The response will contain an `id` (the Check ID). It is required for the next step.

**Example request for creating a check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
               "clientId":"5eb04fcd0f3e360008035eb1",
               "type": "extensive_screening_check"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.create("5eb04fcd0f3e360008035eb1", {
    type: "extensive_screening_check"
});
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.complycube.checks.create(
    "5eb04fcd0f3e360008035eb1",
    type="extensive_screening_check"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$result = $ccapi->checks()->create(
    '5eb04fcd0f3e360008035eb1',
    ['type' => 'extensive_screening_check']
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var checkRequest = new CheckRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  type = "extensive_screening_check"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5ebd40714f23960008c81527",
    "entityName": "John Doe",
    "type": "extensive_screening_check",
    "clientId": "5eb04fcd0f3e360008035eb1",
    "status": "pending",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Retrieve results

ComplyCube will then run the check. You can retrieve its [outcome and detailed breakdown](/documentation/api-reference/check-types/aml-screening-check#result-object) via the API, or review the results in the Portal.

If you have [set up webhooks](/documentation/integration-resources/webhooks), you’ll also receive a notification once the check is complete.

**Example request for retrieving the check outcome**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/5ebd40714f23960008c81527 \
     -H 'Authorization: <YOUR_API_KEY>'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.get("5ebd40714f23960008c81527");
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.get('5ebd40714f23960008c81527')
```

{% endtab %}

{% tab title="PHP" %}

```php
$check = $ccapi->checks()->get('5ebd40714f23960008c81527');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var check = await checkApi.GetAsync("5ebd40714f23960008c81527");
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "65c12a6426d2ab000814037e",
    "entityName": "John Doe",
    "type": "standard_screening_check",
    "clientId": "5eb04fcd0f3e360008035eb1",
    "status": "complete",
    "result": {
        "outcome": "clear",
        "breakdown": {
            "summary": {
                "pep": {
                    "level1": "clear",
                    "level2": "clear",
                    "level3": "clear",
                    "level4": "clear"
                },
                "watchlist":{
                    "sanctionsLists": "clear",
                    "otherOfficialLists": "clear",
                    "warCrimes": "clear",
                    "terror": "clear",
                    "otherExclusionLists": "clear",
                    "sanctionsControlAndOwnership": "clear"
                },
                "adverseMedia": {
                    "environmentProduction": "clear",
                    "socialLabour": "clear",
                    "competitiveFinancial": "clear",
                    "regulatory": "clear"
                },
                "otherLists": {
                    "associatedEntity": "clear",
                    "organisedCrime": "clear",
                    "financialCrime": "clear",
                    "taxCrime": "clear",
                    "corruption": "clear",
                    "trafficking": "clear"
                }
            }
        }
    },
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}
{% endstepper %}


# Perform Document Check

Use the API to run document verification for KYC and identity verification workflows.

### Overview <a href="#overview" id="overview"></a>

This guide shows you how to run a Document Check using the ComplyCube API.

{% hint style="success" %}
You can try this check right away using our [Demo Postman Collection](/documentation/integration-resources/postman#demo-collection). It’s publicly accessible and **requires no account**.
{% endhint %}

### Integration steps <a href="#integration-steps" id="integration-steps"></a>

<figure><img src="/files/VqN7oUHn7UHq5JcZg8J2" alt=""><figcaption><p>Document Check API Guide</p></figcaption></figure>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in creating any check is to add a **client** from your backend server. A client can represent either a **person** or a **company**.

The response will contain an `id` (the Client ID). It is required for the next step.

**Example request for creating a client**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe",
               "dob": "1990-01-01"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe",
    dob: "1990-01-01"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR API KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe',
        'dob':'1990-01-01'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john.doe@example.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe',
        'dob' => '1990-01-01'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var newclient = new ClientRequest {
  type = "person",
    email = "john.doe@example.com",
    personDetails = new PersonDetails {
      firstName = "John",
        lastName = "Doe",
        dob = "1990-01-01"
    }
}

var client = await clientApi.CreateAsync(newclient);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe",
        "dob": "1990-01-01"
    },
    "createdAt": "2025-01-04T17:24:29.146Z",
    "updatedAt": "2025-01-04T17:24:29.146Z"
}
```

{% endstep %}

{% step %}

#### Create a document <a href="#create-a-document" id="create-a-document"></a>

Create a document by providing the **Client ID** and **document type** (e.g. passport, national ID).

The response will contain an `id` (the Document ID). It is required for the next step.

**Example request for creating a document**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/documents \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "type": "passport",
          "issuingCountry": "GB"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const document = await complycube.document.create("5eb04fcd0f3e360008035eb1", {
  type: "passport",
  issuingCountry: "GB"
});
```

{% endtab %}

{% tab title="Python" %}

```python
document = cc_api.documents.create(
    "5eb04fcd0f3e360008035eb1",
    type="passport",
    issuingCountry="GB"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$doc = $ccapi->documents()->create(
    '5eb04fcd0f3e360008035eb1',
    [
        'type' => 'passport',
        'issuingCountry' => 'GB'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var docRequest = new DocumentRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  type = "passport",
  issuingCountry = "GB"
};

var document = await docApi.CreateAsync(docRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5ebd40714f23960008c81527",
    "type": "passport",
    "issuingCountry": "GB",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Upload front side of ID

Upload a BASE64-encoded image of the front of the ID document. Depending on the [document type](/documentation/product-guides/identity-verification/document-check/document-sides-per-type) and issuing country, both sides may be required.

Images must be in **JPG**, **PNG**, or **PDF** format and between **34 KB** and **4 MB** in size.

Below is a sample BASE64-encoded file. Download it, copy its contents, and paste them into the `data` attribute when making the request.

{% file src="/files/-M7JT2lVicOTyiYsyi0k" %}
Sample - BASE64 encoded front-side of passport
{% endfile %}

**Example request for uploading the front-side image of a document**

{% tabs %}
{% tab title="cURL" %}

```bash
 curl -X POST https://api.complycube.com/v1/documents/5ebd40714f23960008c81527/upload/front \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
         "fileName": "front-test.jpg",
         "data": "<BASE64_DATA_CONTENT>"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const frontImage = await complycube.document.upload("5ebd40714f23960008c81527", {
    fileName: "front-test.jpg",
    data: "<BASE64_DATA_CONTENT>"
}, "front");
```

{% endtab %}

{% tab title="Python" %}

```python
front_image = cc_api.documents.upload(
    "5ebd40714f23960008c81527",
    "front",
    fileName="front-test.jpg",
    data="<BASE64_DATA_CONTENT>",
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$up = $ccapi->documents()->upload(
    '5ebd40714f23960008c81527', 
    'front', 
    [
        'fileName' => 'front-test.jpg',
        'data' => '<BASE64_DATA_CONTENT>'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}
{% code fullWidth="false" %}

```csharp
var docFront = new ImageRequest {
  fileName = "front-test.jpg",
  data = "<BASE64_DATA_CONTENT>"
};

var img = await docApi.UploadImageAsync(
    "5ebd40714f23960008c81527", 
    "front", 
    docFront
);
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5eb169302d868c0008828591",
    "fileName": "front-test.jpg",
    "documentSide": "front",
    "downloadLink": "/documents/5ebd40714f23960008c81527/images/5eb169302d868c0008828591/download",
    "contentType": "image/jpg",
    "size": 72716,
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Create a check

Create a check by specifying the **Client ID**, **Document ID**, and the **check type**.

The response will contain an `id` (the Check ID). It is required for the next step.

**Example request for creating a check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "documentId":"5ebd40714f23960008c81527",
          "type": "document_check"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.create("5eb04fcd0f3e360008035eb1", {
    documentId: "5ebd40714f23960008c81527",
    type: "document_check"
});
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.create(
    "5eb04fcd0f3e360008035eb1", 
    "document_check", 
    documentId="5ebd40714f23960008c81527"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$result = $ccapi->checks()->create(
    '5eb04fcd0f3e360008035eb1',
    [
        'type' => 'document_check',
        'documentId' => '5ebd40714f23960008c81527'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var checkRequest = new CheckRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  documentId = "5ebd40714f23960008c81527",
  type = "document_check"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "65c12a6426d2ab000814037e",
    "entityName": "John Doe",
    "type": "document_check",
    "clientId": "5eb04fcd0f3e360008035eb1",
    "documentId": "5ebd40714f23960008c81527",
    "status": "pending",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Retrieve results

ComplyCube will then run the check. You can retrieve its [outcome and detailed breakdown](/documentation/api-reference/check-types/document-check#result-object) via the API, or review the results in the Portal.

If you have [set up webhooks](/documentation/integration-resources/webhooks), you’ll also receive a notification once the check is complete.

**Example request for retrieving the check outcome**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/5ebd40714f23960008c81527 \
     -H 'Authorization: <YOUR_API_KEY>'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.get("5ebd40714f23960008c81527");
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.get('5ebd40714f23960008c81527')
```

{% endtab %}

{% tab title="PHP" %}

```php
$check = $ccapi->checks()->get('5ebd40714f23960008c81527');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var check = await checkApi.GetAsync("5ebd40714f23960008c81527");
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
  "id": "65c12a6426d2ab000814037e",
  "clientId": "5eb04fcd0f3e360008035eb1",
  "documentId": "5ebd40714f23960008c81527",
  "entityName": "John Doe",
  "type": "document_check",
  "status": "complete",
  "result": {
    "outcome": "clear",
    "breakdown": {
      "extractedData": {
        "documentDetails": {
          "documentType": "driving_license",
          "hasTwoSides": true,
          "issuingCountry": "GB",
          "issuingDate": {
            "day": 1,
            "month": 1,
            "year": 2015
          },
          "expirationDate": {
            "day": 1,
            "month": 1,
            "year": 2025
          },
          "documentNumber": "123456790",
          "personalNumber": "123456790"
        },
        "holderDetails": {
          "lastName": [
            "DOE"
          ],
          "firstName": [
            "JOHN"
          ],
          "dob": {
            "day": 3,
            "month": 9,
            "year": 1995
          },
          "address": {
            "addressText": "110 MAPLE ROAD, SAMPLE CITY, NC 10000-0008",
            "line": "110 MAPLE ROAD",
            "city": "SAMPLE CITY",
            "state": "North Carolina",
            "postalCode": "10000-0008",
            "country": "US"
          }
        }
      },
      "allExtractedData": {
        "visual": {
          "lastName": [
            "DOE"
          ],
          "firstName": [
            "JOHN"
          ],
          "dob": {
            "day": 3,
            "month": 9,
            "year": 1995
          },
          "age": 26,
          "gender": "male",
          "documentNumber": "123456790",
          "documentDiscriminator": "123456790",
          "issuingDate": {
            "day": 1,
            "month": 1,
            "year": 2015
          },
          "expirationDate": {
            "day": 1,
            "month": 1,
            "year": 2025
          },
          "addressText": "110 MAPLE ROAD, SAMPLE CITY, NC 10000-0008",
          "addressLine": "110 MAPLE ROAD",
          "addressCity": "SAMPLE CITY",
          "addressPostalCode": "10000-0008",
          "height": "175 cm"
        },
        "barcode": {
          "lastName": [
            "DOE"
          ],
          "firstName": [
            "JOHN"
          ],
          "dob": {
            "day": 3,
            "month": 9,
            "year": 1995
          },
          "gender": "male",
          "documentNumber": "123456790",
          "documentDiscriminator": "123456790",
          "issuingCountry": "US",
          "issuingDate": {
            "day": 15,
            "month": 11,
            "year": 2018
          },
          "expirationDate": {
            "day": 29,
            "month": 9,
            "year": 2026
          },
          "addressText": "110 MAPLE ROAD, SAMPLE CITY, NC 10000-0008",
          "addressLine": "110 MAPLE ROAD",
          "addressCity": "SAMPLE CITY",
          "addressPostalCode": "10000-0008",
          "addressState": "North Carolina",
          "addressCountry": "US",
          "height": "175 cm"
        }
      }
    },
    "mrzAnalysis": {
      "mrzFormat": "clear",
      "mrzChecksum": "clear"
    },
    "consistencyAnalysis": {
      "lastName": "clear",
      "firstName": "clear",
      "dob": "clear",
      "documentNumber": "clear",
      "personalNumber": "clear",
      "expirationDate": "clear",
      "issuingDate": "clear"
    },
    "contentAnalysis": {
      "dataIntegrity": "clear",
      "issuingDate": "clear",
      "expirationDate": "clear",
      "specimenCheck": "clear",
      "blackListCheck": "clear"
    },
    "formatAnalysis": {
      "modelIdentification": "clear",
      "countryModelValidity": "clear",
      "documentModelValidity": "clear",
      "photocopyDetected": "clear"
    },
    "forensicAnalysis": {
      "documentLivenessCheck": "clear",
      "tamperingDetected": "clear",
      "mrzVisualPlacement": "clear",
      "securityElements": "clear",
      "photoLocation": "clear",
      "mrzClassification": "clear",
      "breakdown": {
        "documentFrontLivenessScore": 100,
        "documentBackLivenessScore": 100
      }
    },
    "frontAndBackAnalysis": {
      "formatAnalysis": "clear",
      "dataConsistency": "clear"
    },
    "clientValidation": {
      "ageVerification": "clear",
      "clientDataConsistency": "clear"
    },
    "extractedImages": [{
      "type": "front_side",
      "data": "<BASE64_IMAGE_CONTENT>"
    }],
    "securityAndPatternAnalysis": [{
      "similarity": 100,
      "outcome": "clear",
      "narrative": "Clear",
      "actualImageData": "<BASE64_IMAGE_CONTENT>",
      "expectedImageData": "<BASE64_IMAGE_CONTENT>"
    }]
  },
  "createdAt": "2020-01-01T14:06:44.756Z",
  "updatedAt": "2020-01-01T14:06:44.756Z"
}
```

{% endstep %}
{% endstepper %}


# Perform Identity Check

Use the API to run identity verification checks and validate customer data for KYC.

### Overview <a href="#overview" id="overview"></a>

This guide shows you how to run an Identity Check using the ComplyCube API.

{% hint style="success" %}
You can try this check right away using our [Demo Postman Collection](/documentation/integration-resources/postman#demo-collection). It’s publicly accessible and **requires no account**.
{% endhint %}

### Integration steps <a href="#integration-steps" id="integration-steps"></a>

<figure><img src="/files/sKnyTFBkHi6tsOOSQJBF" alt=""><figcaption><p>Identity Check API Guide</p></figcaption></figure>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in creating any check is to add a **client** from your backend server. A client can represent either a **person** or a **company**.

The response will contain an `id` (the Client ID). It is required for the next step.

**Example request for creating a client**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe",
               "dob": "1990-01-01"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe",
    dob: "1990-01-01"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR API KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe',
        'dob':'1990-01-01'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john.doe@example.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe',
        'dob' => '1990-01-01'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var newclient = new ClientRequest {
  type = "person",
    email = "john.doe@example.com",
    personDetails = new PersonDetails {
      firstName = "John",
        lastName = "Doe",
        dob = "1990-01-01"
    }
}

var client = await clientApi.CreateAsync(newclient);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe",
        "dob": "1990-01-01"
    },
    "createdAt": "2025-01-04T17:24:29.146Z",
    "updatedAt": "2025-01-04T17:24:29.146Z"
}
```

{% endstep %}

{% step %}

#### Create a live photo

Upload a BASE64-encoded selfie image of the customer. The image must be in **JPG** or **PNG** and between **34 KB** and **4 MB** in size.

Below is a sample BASE64-encoded selfie image. Download it, and copy its content. Then paste into the `data` attribute when making the request.

The response will contain an `id` (the Live Photo ID). It is required later.

{% file src="/files/-M7mkOYNzzw-N0EDXgnu" %}
Sample - BASE64 encoded selfie
{% endfile %}

**Example request for uploading the live photo**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/livePhotos \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "data": "<BASE64_DATA_CONTENT>"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const livePhoto = await complycube.livePhoto.upload("5eb04fcd0f3e360008035eb1", {
    data: "<BASE64_DATA_CONTENT>"
});
```

{% endtab %}

{% tab title="Python" %}

```python
livePhoto = cc_api.livephotos.upload('5eb04fcd0f3e360008035eb1', 
                                     data='<BASE64_DATA_CONTENT>')
```

{% endtab %}

{% tab title="PHP" %}

```php
$img = $ccapi->livephotos()->upload('5eb04fcd0f3e360008035eb1',
                                   ['data' => '<BASE64_DATA_CONTENT>']);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var livePhotoRequest = new LivePhotoRequest
                    {
                        clientId = "5eb04fcd0f3e360008035eb1",
                        data= "<BASE64_DATA_CONTENT>"
                    };

var livePhoto = await livePhotoApi.UploadAsync(livePhotoRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5eb1b5f231778a0008d1c3f6",
    "clientId": "5eb04fcd0f3e360008035eb1",
    "downloadLink": "/livePhotos/5eb1b5f231778a0008d1c3f6/download",
    "contentType": "images/jpg",
    "size": 44896,
    "createdAt": "2025-01-01T14:06:44.756Z",
    "updatedAt": "2025-01-01T14:06:44.756Z"
}
```

{% endstep %}

{% step %}

#### Create a document <a href="#create-a-document" id="create-a-document"></a>

Create a document by providing the **Client ID** and **document type** (e.g. passport, national ID).

The response will contain an `id` (the Document ID). It is required for the next step.

**Example request for creating a document**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/documents \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "type": "passport",
          "issuingCountry": "GB"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const document = await complycube.document.create("5eb04fcd0f3e360008035eb1", {
  type: "passport",
  issuingCountry: "GB"
});
```

{% endtab %}

{% tab title="Python" %}

```python
document = cc_api.documents.create(
    "5eb04fcd0f3e360008035eb1",
    type="passport",
    issuingCountry="GB"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$doc = $ccapi->documents()->create(
    '5eb04fcd0f3e360008035eb1',
    [
        'type' => 'passport',
        'issuingCountry' => 'GB'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var docRequest = new DocumentRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  type = "passport",
  issuingCountry = "GB"
};

var document = await docApi.CreateAsync(docRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5ebd40714f23960008c81527",
    "type": "passport",
    "issuingCountry": "GB",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Upload front side of ID

Upload a BASE64-encoded image of the front of the ID document. Depending on the [document type](/documentation/product-guides/identity-verification/document-check/document-sides-per-type) and issuing country, both sides may be required.

Images must be in **JPG**, **PNG**, or **PDF** format and between **34 KB** and **4 MB** in size.

Below is a sample BASE64-encoded file. Download it, copy its contents, and paste them into the `data` attribute when making the request.

{% file src="/files/-M7JT2lVicOTyiYsyi0k" %}
Sample - BASE64 encoded front-side of passport
{% endfile %}

**Example request for uploading the front-side image of a document**

{% tabs %}
{% tab title="cURL" %}

```bash
 curl -X POST https://api.complycube.com/v1/documents/5ebd40714f23960008c81527/upload/front \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
         "fileName": "front-test.jpg",
         "data": "<BASE64_DATA_CONTENT>"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const frontImage = await complycube.document.upload("5ebd40714f23960008c81527", {
    fileName: "front-test.jpg",
    data: "<BASE64_DATA_CONTENT>"
}, "front");
```

{% endtab %}

{% tab title="Python" %}

```python
front_image = cc_api.documents.upload(
    "5ebd40714f23960008c81527",
    "front",
    fileName="front-test.jpg",
    data="<BASE64_DATA_CONTENT>",
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$up = $ccapi->documents()->upload(
    '5ebd40714f23960008c81527', 
    'front', 
    [
        'fileName' => 'front-test.jpg',
        'data' => '<BASE64_DATA_CONTENT>'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}
{% code fullWidth="false" %}

```csharp
var docFront = new ImageRequest {
  fileName = "front-test.jpg",
  data = "<BASE64_DATA_CONTENT>"
};

var img = await docApi.UploadImageAsync(
    "5ebd40714f23960008c81527", 
    "front", 
    docFront
);
```

{% endcode %}
{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5eb169302d868c0008828591",
    "fileName": "front-test.jpg",
    "documentSide": "front",
    "downloadLink": "/documents/5ebd40714f23960008c81527/images/5eb169302d868c0008828591/download",
    "contentType": "image/jpg",
    "size": 72716,
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Create an Identity Check

Create an Identity Check by specifying the **Client ID**, **Live Photo ID**, **Document ID**, and the **check type**.

The response will contain an `id` (the Check ID). It is required for the next step.

**Example request for creating a check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "livePhotoId":"5eb1b5f231778a0008d1c3f6",
          "documentId":"5ebd40714f23960008c81527",
          "type": "identity_check"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.create("5eb04fcd0f3e360008035eb1", {
        livePhotoId: "5eb1b5f231778a0008d1c3f6",
        documentId: "5ebd40714f23960008c81527",
        type: "identity_check"
});
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.create('5eb04fcd0f3e360008035eb1', 
                                'identity_check', 
                                livePhotoId='5eb1b5f231778a0008d1c3f6',
                                documentId='5ebd40714f23960008c81527')
```

{% endtab %}

{% tab title="PHP" %}

```php
$result = $ccapi->checks()->create('5eb04fcd0f3e360008035eb1',
                                   ['type' => 'identity_check',
                                   'livePhotoId' => '5eb1b5f231778a0008d1c3f6',
                                   'documentId' => '5ebd40714f23960008c81527']);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var checkRequest = new CheckRequest
                    {
                        clientId = "5eb04fcd0f3e360008035eb1",
                        documentId = "5ebd40714f23960008c81527",
                        livePhotoId = "5eb1b5f231778a0008d1c3f6",
                        type = "identity_check"
                    };

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Check ID). It is required for the next step.

```json
{
    "id": "65c12a6426d2ab000814037e",
    "entityName": "John Doe",
    "type": "identity_check",
    "clientId": "5eb04fcd0f3e360008035eb1",
    "livePhotoId": "5eb1b5f231778a0008d1c3f6",
    "documentId": "5ebd40714f23960008c81527",
    "status": "pending",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Retrieve results

ComplyCube will then run the check. You can retrieve its [outcome and detailed breakdown](/documentation/api-reference/check-types/identity-check#result-object) via the API, or review the results in the Portal.

If you have [set up webhooks](/documentation/integration-resources/webhooks), you’ll also receive a notification once the check is complete.

**Example request for retrieving the check outcome**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/5ebd40714f23960008c81527 \
     -H 'Authorization: <YOUR_API_KEY>'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.get("5ebd40714f23960008c81527");
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.get('5ebd40714f23960008c81527')
```

{% endtab %}

{% tab title="PHP" %}

```php
$check = $ccapi->checks()->get('5ebd40714f23960008c81527');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var check = await checkApi.GetAsync("5ebd40714f23960008c81527");
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
   "id": "5e94b88a01bce00008c86f06",
   "entityName": "John Doe",
   "type": "identity_check",
   "clientId": "5e94b75d01bce00008c86f02",
   "documentId": "5e94b87b01bce00008c86f03",
   "livePhotoId": "5e94b88901bce00008c86f05",
   "status": "complete",
   "result": {
      "outcome": "clear",
      "breakdown": {
         "faceAnalysis": {
            "faceDetection": "clear",
            "facialSimilarity": "clear",
            "breakdown": {
               "facialSimilarityScore": 100
            }
         },
         "authenticityAnalysis": {
            "spoofedImageAnalysis": "clear",
            "livenessCheck": "clear",
            "breakdown": {
               "livenessCheckScore": 100
            }
         },
         "integrityAnalysis": {
            "faceDetection": "clear"
         }
      }
   },
   "createdAt": "2025-01-04T17:25:21.116Z",
   "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}
{% endstepper %}


# Perform Proof of Address Check

Use the API to run proof of address checks and verify customer addresses for KYC.

### Overview <a href="#overview" id="overview"></a>

This guide shows you how to run a Proof of Address Check using the ComplyCube API.

{% hint style="success" %}
You can try this check right away using our [Demo Postman Collection](/documentation/integration-resources/postman#demo-collection). It’s publicly accessible and **requires no account**.
{% endhint %}

### Integration steps <a href="#integration-steps" id="integration-steps"></a>

<figure><img src="/files/byZewURlvzwPVezcVR5a" alt=""><figcaption><p>Proof of Address Check API Guide</p></figcaption></figure>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in creating any check is to add a **client** from your backend server. A client can represent either a **person** or a **company**.

The response will contain an `id` (the Client ID). It is required for the next step.

**Example request for creating a client**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe",
               "dob": "1990-01-01"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe",
    dob: "1990-01-01"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR API KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe',
        'dob':'1990-01-01'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john.doe@example.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe',
        'dob' => '1990-01-01'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var newclient = new ClientRequest {
  type = "person",
    email = "john.doe@example.com",
    personDetails = new PersonDetails {
      firstName = "John",
        lastName = "Doe",
        dob = "1990-01-01"
    }
}

var client = await clientApi.CreateAsync(newclient);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe",
        "dob": "1990-01-01"
    },
    "createdAt": "2025-01-04T17:24:29.146Z",
    "updatedAt": "2025-01-04T17:24:29.146Z"
}
```

{% endstep %}

{% step %}

#### Create an address

Create an address by providing the **Client ID** and address details.

The response will contain an `id` (the Address ID). It is required later.

**Example request for creating an address**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/addresses \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
            "clientId":"5eb04fcd0f3e360008035eb1",
            "line": "47th Test Avenue 323",
            "city": "Manhattan",
            "postalCode": "10001",
            "state": "NY",
            "country": "US"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const address = await complycube.address.create("5eb04fcd0f3e360008035eb1", {
  line: "47th Test Avenue 323",
  city: "Manhattan",
  postalCode: "10001",
  state: "NY",
  country: "US"
});
```

{% endtab %}

{% tab title="Python" %}

```python
new_address = {    
    'line': '47th Test Avenue 323',
    'city': 'Manhattan',
    'postalCode': '10001',
    'state': 'NY',
    'country': 'US'
}

address = cc_api.addresses.create('5eb04fcd0f3e360008035eb1',**new_address)
```

{% endtab %}

{% tab title="PHP" %}

```php
$address = $ccapi->address()->create(
    '5eb04fcd0f3e360008035eb1',
    [
        'line' => '47th Test Avenue 323',
        'city' => 'Manhattan',
        'postalCode' => '10001',
        'state' => 'NY',
        'country' => 'US'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var addressRequest = new AddressRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  line = "47th Test Avenue 323",
  city = "Manhattan",
  postalCode = "10001",
  state = "NY",
  country = "US"
};

var address = await addressApi.CreateAsync(addressRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5ebd40714f23960008c81528",
    "clientId":"5eb04fcd0f3e360008035eb1",
    "line": "47th Test Avenue 323",
    "city": "Manhattan",
    "postalCode": "10001",
    "state": "NY",
    "country": "US",
    "createdAt": "2021-01-04T17:25:21.116Z",
    "updatedAt": "2021-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Create a document <a href="#create-a-document" id="create-a-document"></a>

Create a document by providing the **Client ID** and **document type** (e.g. bank statement).

The response will contain an `id` (the Document ID). It is required for the next step.

**Example request for creating a document**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/documents \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "type": "bank_statement"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const document = await complycube.document.create("5eb04fcd0f3e360008035eb1", {
  type: "bank_statement"
});
```

{% endtab %}

{% tab title="Python" %}

```python
document = cc_api.documents.create(
    '5eb04fcd0f3e360008035eb1',
    type='bank_statement'
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$doc = $ccapi->documents()->create(
    '5eb04fcd0f3e360008035eb1',
    ['type' => 'bank_statement']
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var docRequest = new DocumentRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  type = "bank_statement"
};

var document = await docApi.CreateAsync(docRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Document ID). It is required for the next step.

```json
{
    "id": "5ebd40714f23960008c81527",
    "type": "bank_statement",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Upload document

Upload a BASE64-encoded image of the proof of address document.

Images must be in **JPG**, **PNG**, or **PDF** format and between **34 KB** and **4 MB** in size.

Below is a sample BASE64-encoded file. Download it, copy its contents, and paste them into the `data` attribute when making the request.

{% file src="/files/-MlKPBPcIobzntkihV3J" %}
Sample - BASE64 encoded bank statement
{% endfile %}

**Example request for uploading an image of a document**

{% tabs %}
{% tab title="cURL" %}

```bash
 curl -X POST https://api.complycube.com/v1/documents/5ebd40714f23960008c81527/upload/front \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
         "fileName": "bank-statement-sample.pdf",
         "data": "<BASE64_DATA_CONTENT>"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const frontImage = await complycube.document.upload("5ebd40714f23960008c81527", {
    fileName: "bank-statement-sample.pdf",
    data: "<BASE64_DATA_CONTENT>"
}, "front");
```

{% endtab %}

{% tab title="Python" %}

```python
front_image = cc_api.documents.upload(
    '5ebd40714f23960008c81527', 
    'front',
    fileName='bank-statement-sample.pdf',
    data='<BASE64_DATA_CONTENT>'
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$up = $ccapi->documents()->upload(
    '5ebd40714f23960008c81527', 
    'front', 
    [
        'fileName' => 'bank-statement-sample.pdf',
        'data' => '<BASE64_DATA_CONTENT>'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var docFront = new ImageRequest {
  fileName = "bank-statement-sample.pdf",
  data = "<BASE64_DATA_CONTENT>"
};

var img = await docApi.UploadImageAsync(
    "5ebd40714f23960008c81527",
    "front",
    docFront
);

```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the image ID). It is required for the next step.

```json
{
    "id": "5eb169302d868c0008828591",
    "fileName": "bank-statement-sample.pdf",
    "documentSide": "front",
    "downloadLink": "/documents/5ebd40714f23960008c81527/images/5eb169302d868c0008828591/download",
    "contentType": "application/pdf",
    "size": 182716,
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Create a Proof of Address Check

Create a Proof of Address Check by providing the **Client ID**, **Document ID**, and **check type**.

The response will contain an `id` (the Check ID). It is required for the next step.

**Example request for creating a check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "documentId":"5ebd40714f23960008c81527",
          "type": "proof_of_address_check"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.create("5eb04fcd0f3e360008035eb1", {
    documentId: "5ebd40714f23960008c81527",
    type: "proof_of_address_check"
});
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.create(
    '5eb04fcd0f3e360008035eb1',
    'proof_of_address_check',
    documentId='5ebd40714f23960008c81527'
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$result = $ccapi->checks()->create(
    '5eb04fcd0f3e360008035eb1',
    [
        'type' => 'proof_of_address_check',
        'documentId' => '5ebd40714f23960008c81527'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var checkRequest = new CheckRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  documentId = "5ebd40714f23960008c81527",
  type = "proof_of_address_check"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "65c12a6426d2ab000814037e",
    "entityName": "John Doe",
    "type": "proof_of_address_check",
    "clientId": "5eb04fcd0f3e360008035eb1",
    "documentId": "5ebd40714f23960008c81527",
    "status": "pending",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Retrieve results

ComplyCube will then run the check. You can retrieve its [outcome and detailed breakdown](/documentation/api-reference/check-types/proof-of-address-check#result-object) via the API, or review the results in the Portal.

If you have [set up webhooks](/documentation/integration-resources/webhooks), you’ll also receive a notification once the check is complete.

**Example request for retrieving the check outcome**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/5ebd40714f23960008c81527 \
     -H 'Authorization: <YOUR_API_KEY>'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.get("5ebd40714f23960008c81527");
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.get('5ebd40714f23960008c81527')
```

{% endtab %}

{% tab title="PHP" %}

```php
$check = $ccapi->checks()->get('5ebd40714f23960008c81527');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var check = await checkApi.GetAsync("5ebd40714f23960008c81527");
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
   "id": "65c12a6426d2ab000814037e",
   "entityName": "John Doe",
   "type": "proof_of_address_check",
   "clientId": "5eb04fcd0f3e360008035eb1",
   "documentId": "5ebd40714f23960008c81527",
   "status": "complete",
   "result": {
      "outcome": "clear",
      "breakdown": {
         "extractedData": {
            "holderDetails": {
               "entityName": "John Doe"
            },
            "documentDetails": {
               "documentType": "bank_statement",
               "issuer": "Barclays Bank",
               "issuingDate": {
                  "day": 25,
                  "month": 1,
                  "year": 2021
               }
            },
            "addressDetails": {
               "address": {
                  "propertyNumber": "323",
                  "line": "Common street",
                  "city": "Aldgate",
                  "state": "London",
                  "postalCode": "W99 0RD",
                  "country": "GB",
                  "latLong": "51.5136,-0.077188"
               },
               "addressLine": "323 Common Street Aldgate London W99 0RD",
               "addressCountry": "GB"
            }
         },
         "clientValidation": {
            "firstName": "clear",
            "lastName": "clear",
            "address": "clear"
         },
         "contentAnalysis": {
            "documentAge": "clear"
         },
         "geoLocationAnalysis": {
            "ipInAddressCountry": "clear",
            "ipProximityToAddress": "clear"
         }
      }
   },
   "createdAt": "2025-01-04T17:25:21.116Z",
   "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}
{% endstepper %}


# Perform Multi-Bureau Check

Use the API to run multi-bureau identity verification checks across trusted data sources.

### Overview <a href="#overview" id="overview"></a>

This guide shows you how to run a Multi-Bureau Check using the ComplyCube API.

{% hint style="success" %}
You can try this check right away using our [Demo Postman Collection](/documentation/integration-resources/postman#demo-collection). It’s publicly accessible and **requires no account**.
{% endhint %}

### Integration steps <a href="#integration-steps" id="integration-steps"></a>

<figure><img src="/files/HwbxFhuobHxDDTjbTJsz" alt=""><figcaption><p>Multi Bureau Check API Guide</p></figcaption></figure>

{% stepper %}
{% step %}

#### Create a client <a href="#create-a-client" id="create-a-client"></a>

The first step in creating any check is to add a **client** from your backend server. A client can represent either a **person** or a **company**.

For this type of check, a client of type **person** must be created.

The response will contain an `id` (the Client ID). It is required for the next step.

**Example request for creating a client**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "type": "person",
           "email": "john.doe@example.com",
           "personDetails": {
                "firstName": "John",
                "lastName": "Doe",
                "dob": "1990-01-01",
                "ssn": "123-45-6789"
            }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe",
    dob: "1990-01-01",
    ssn: "123456789"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe',
        'dob': '1990-01-01',
        'ssn': '123456789'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john.doe@example.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe',
        'dob' => '1990-01-01',
        'ssn' => '123456789'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var newClient = new ClientRequest {
  type = "person",
  email = "john.doe@example.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe",
    dob = "1990-01-01",
    ssn = "123456789"
  }
};

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe",
        "dob": "1990-01-01",
        "ssn": "123-45-6789"
    },
    "createdAt": "2025-01-04T17:24:29.146Z",
    "updatedAt": "2025-01-04T17:24:29.146Z"
}
```

{% endstep %}

{% step %}

#### Create an address

Create an address by providing the **Client ID** and address details.

The response will contain an `id` (the Address ID). It is required later.

**Example request for creating an address**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/addresses \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
            "clientId":"5eb04fcd0f3e360008035eb1",
            "line": "47th Test Avenue 323",
            "city": "Manhattan",
            "postalCode": "10001",
            "state": "NY",
            "country": "US"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const address = await complycube.address.create("5eb04fcd0f3e360008035eb1", {
  line: "47th Test Avenue 323",
  city: "Manhattan",
  postalCode: "10001",
  state: "NY",
  country: "US"
});
```

{% endtab %}

{% tab title="Python" %}

```python
new_address = {    
    'line': '47th Test Avenue 323',
    'city': 'Manhattan',
    'postalCode': '10001',
    'state': 'NY',
    'country': 'US'
}

address = cc_api.addresses.create('5eb04fcd0f3e360008035eb1',**new_address)
```

{% endtab %}

{% tab title="PHP" %}

```php
$address = $ccapi->address()->create(
    '5eb04fcd0f3e360008035eb1',
    [
        'line' => '47th Test Avenue 323',
        'city' => 'Manhattan',
        'postalCode' => '10001',
        'state' => 'NY',
        'country' => 'US'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var addressRequest = new AddressRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  line = "47th Test Avenue 323",
  city = "Manhattan",
  postalCode = "10001",
  state = "NY",
  country = "US"
};

var address = await addressApi.CreateAsync(addressRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "5ebd40714f23960008c81528",
    "clientId":"5eb04fcd0f3e360008035eb1",
    "line": "47th Test Avenue 323",
    "city": "Manhattan",
    "postalCode": "10001",
    "state": "NY",
    "country": "US",
    "createdAt": "2021-01-04T17:25:21.116Z",
    "updatedAt": "2021-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Create a check

Create a check by providing the **Client ID**, **Address ID**, and **check type**.

The response will contain an `id` (the Check ID). It is required for the next step.

**Example request for creating a check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"5eb04fcd0f3e360008035eb1",
          "addressId":"5ebd40714f23960008c81528",
          "type": "multi_bureau_check"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.create("5eb04fcd0f3e360008035eb1", {
    addressId: "5ebd40714f23960008c81528",
    type: "multi_bureau_check"
});
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.create(
    '5eb04fcd0f3e360008035eb1',
    'multi_bureau_check',
    addressId='5ebd40714f23960008c81528'
)
```

{% endtab %}

{% tab title="PHP" %}

```php
$result = $ccapi->checks()->create(
    '5eb04fcd0f3e360008035eb1',
    [
        'type' => 'multi_bureau_check',
        'addressId' => '5ebd40714f23960008c81528'
    ]
);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var checkRequest = new CheckRequest {
  clientId = "5eb04fcd0f3e360008035eb1",
  addressId = "5ebd40714f23960008c81528",
  type = "multi_bureau_check"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "id": "65c12a6426d2ab000814037e",
    "entityName": "John Doe",
    "type": "multi_bureau_check",
    "clientId": "5eb04fcd0f3e360008035eb1",
    "addressId": "5ebd40714f23960008c81528",
    "status": "pending",
    "createdAt": "2025-01-04T17:25:21.116Z",
    "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}

{% step %}

#### Retrieve results

ComplyCube will then run the check. You can retrieve its [outcome and detailed breakdown](/documentation/api-reference/check-types/multi-bureau-check#result-object) via the API, or review the results in the Portal.

If you have [set up webhooks](/documentation/integration-resources/webhooks), you’ll also receive a notification once the check is complete.

**Example request for retrieving the check outcome**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/65c12a6426d2ab000814037e \
     -H 'Authorization: <YOUR_API_KEY>'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const check = await complycube.check.get("65c12a6426d2ab000814037e");
```

{% endtab %}

{% tab title="Python" %}

```python
check = cc_api.checks.get('65c12a6426d2ab000814037e')
```

{% endtab %}

{% tab title="PHP" %}

```php
$check = $ccapi->checks()->get('65c12a6426d2ab000814037e');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
var check = await checkApi.GetAsync("65c12a6426d2ab000814037e");
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
   "id": "65c12a6426d2ab000814037e",
   "entityName": "John Doe",
   "type": "multi_bureau_check",
   "clientId": "5eb04fcd0f3e360008035eb1",
   "addressId": "5ebd40714f23960008c81528",
   "status": "complete",
   "result": {
      "outcome": "clear",
      "breakdown": {
         "name": {
            "outcome": "clear",
            "breakdown": [
               {
                  "status": "clear",
                  "source": "commercial_database",
                  "country": "US",
                  "hits": 1
               },
               {
                  "status": "clear",
                  "source": "government_authority",
                  "country": "US",
                  "hits": 1
               }
            ]
         },
         "address": {
            "outcome": "clear",
            "breakdown": [
               {
                  "status": "clear",
                  "source": "government_authority",
                  "country": "US",
                  "hits": 1
               }
            ]
         },
         "dob": {
            "outcome": "clear",
            "breakdown": [
               {
                  "status": "clear",
                  "source": "commercial_database",
                  "country": "US",
                  "hits": 1
               },
               {
                  "status": "clear",
                  "source": "government_authority",
                  "country": "US",
                  "hits": 1
               }
            ]
         },
         "idNumber": {
            "outcome": "clear",
            "breakdown": [
               {
                  "status": "clear",
                  "source": "commercial_database",
                  "country": "US",
                  "hits": 1
               }
            ]
         },
         "additionalChecks": {
            "outcome": "not_processed"
         }
      }
   },
   "createdAt": "2025-01-04T17:25:21.116Z",
   "updatedAt": "2025-01-04T17:25:21.116Z"
}
```

{% endstep %}
{% endstepper %}


# Postman Guide

Test the ComplyCube API for KYC, AML, and identity verification in Postman without writing code.

### Overview

[Postman](https://www.postman.com/) collections simplify testing with the ComplyCube API, letting you explore endpoints quickly and efficiently.

We provide two official collections that cover the full ComplyCube API.

***

### Demo collection

The demo collection provides a hands-on overview of key endpoints in a simple, **scenario-driven format**. It’s the fastest way to explore the ComplyCube API and see it in action.

It runs on a mock account, so **no setup is required**. Just click below to launch it in Postman:

[![Run Demo Collection In Postman](https://run.pstmn.io/button.svg)](https://god.gw.postman.com/run-collection/1287169-3c7d2d29-dcbe-440d-ac07-b1f686a80572?action=collection%2Ffork\&source=rip_markdown\&collection-url=entityId%3D1287169-3c7d2d29-dcbe-440d-ac07-b1f686a80572%26entityType%3Dcollection%26workspaceId%3D3a924050-35af-484a-bb31-ed767b6affc2)

You can also use our [testing data](/documentation/integration-resources/testing-data) to simulate specific responses and workflows.

***

### Development collection

The development collection provides a detailed overview of our **API resources**. It’s designed for deeper exploration of the ComplyCube API and for use alongside your integration work.

This collection leverages **environment variables** for a smoother experience, though it does require some initial setup.

To get started, launch the collection in Postman:

[![Run Development Collection In Postman](https://run.pstmn.io/button.svg)](https://god.gw.postman.com/run-collection/1287169-d3db4af6-5e51-4b2b-9191-4fc2e154ba0e?action=collection%2Ffork\&source=rip_markdown\&collection-url=entityId%3D1287169-d3db4af6-5e51-4b2b-9191-4fc2e154ba0e%26entityType%3Dcollection%26workspaceId%3D3a924050-35af-484a-bb31-ed767b6affc2)

#### Environment setup

1. Copy your [Sandbox API key](https://portal.complycube.com/developers).
2. In Postman, click on the **Manage Environment** icon (cog in the top-right corner).
3. Next to **Globals**, click **Edit** and create a new variable called `apiKey`.
4. In the **Current Value** field, paste the API key from step 1, then click **Save**.

That’s it. You can now test all ComplyCube endpoints across both **Sandbox** and **Live** environments directly in Postman.


# Webhooks Guide

Use webhooks to receive KYC, AML, and identity verification events from your ComplyCube integration.

### Overview

ComplyCube uses webhooks to notify your application when an event happens in your account. Webhooks are particularly useful for asynchronous events like when a check has concluded.

Not all ComplyCube integrations require webhooks. Keep reading to learn more about webhooks and when you should use them.

### Introduction to webhooks <a href="#what-are-webhooks" id="what-are-webhooks"></a>

Webhooks combine several elements to create a notification and reaction system within an integration.

Metaphorically, webhooks are like a phone number that ComplyCube calls to notify you of your account activity. The activity could be that a document check is complete. The webhook endpoint is the person answering that call who takes actions based on the specific information it receives.

Non-metaphorically, the webhook endpoint is just more code on your server. The webhook endpoint has an associated URL (e.g., **<https://example.com/webhooks>**). The ComplyCube notifications are [Event](https://docs.complycube.com/api-reference/other-resources/webhooks#the-event-object) objects. This object contains all the relevant information about what just happened, including the type of event and the data associated with that event. The webhook endpoint uses the event details to take required actions, such as putting a temporary hold on a customer's account or transaction.

### Webhook components <a href="#webhook-components" id="webhook-components"></a>

ComplyCube Webhooks integration includes the following:

* **Events**. An action or change in data that generates notifications. Webhooks can be used to create alerts that trigger these events. Please look at the [Webhooks API page](https://docs.complycube.com/api-reference/other-resources/webhooks) for the list of supported event types.
* **Subscriptions**. Configured in the developer portal or via API to subscribe to notifications associated with a specific event type.
* **Notification URL**. The configurable service in the application to which alerts are sent.
* **Notification body**. Details about the object associated with the event.

### When to use <a href="#when-to-use-webhooks" id="when-to-use-webhooks"></a>

Many events that occur within the ComplyCube account have synchronous results – immediate and direct – to an executed request. For example, a successful request to [create a client](/documentation/api-reference/core-resources/clients/create-a-client) immediately returns a `client` object. Such requests don't require webhooks, as the key information is already available.

On the other hand, [Checks](/documentation/api-reference/core-resources/checks) are asynchronous: happening later and not directly in response to your code's execution. With these events, ComplyCube needs to notify your integration about changes to an object's status so your integration can take subsequent steps.

The specific actions of your webhook endpoint differ based on the event. Some examples include:

* Based on a check outcome, decide to accept or reject a customer's request to be on-boarded onto your platform.
* Perform follow-up actions upon getting alerted by our real-time continuous monitoring engine that a client's status has changed.

### Signature verification

#### Using official SDKs

ComplyCube signs the webhook events it sends to your endpoints by including a signature in each event's `ComplyCube-Signature` header. This lets you verify that the events were sent by ComplyCube, not by a third party. You can verify signatures using our official libraries or manually using your own solution.

Use one of our official libraries to verify signatures. You perform the verification by providing the event payload, the `ComplyCube-Signature` header, and the endpoint's secret. If verification fails, ComplyCube returns an error.

{% tabs %}
{% tab title="Node.js" %}

```javascript
const { EventVerifier } = require('@complycube/api')

// Provide your webhook secret to the EventVerifier 
const webhookSecret = process.env.COMPLYCUBE_WEBHOOK_SECRET;
const eventVerifier = new EventVerifier(webhookSecret);

// This example uses Express to receive webhooks
const app = require('express')();

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

// Match the raw body to content type application/json
app.post('/webhook', bodyParser.json(), (request, response) => {
  const signature = request.headers['complycube-signature'];

  let event;

  try {
    event = eventVerifier.constructEvent(
      JSON.stringify(request.body),
      signature
    );
  }
  catch (err) {
    response.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Handle the event
  switch (event.type) {
    case 'check.completed': {
      const checkId = event.payload.id;
      const checkOutcome = event.payload.outcome;
      console.log(`Check ${checkId} completed with outcome ${checkOutcome}`);
      break;
    }
    case 'check.pending': {
      const checkId = event.payload.id;
      console.log(`Check ${checkId} is pending`);
      break;
    }
    // ... handle other event types
    default: {
      // Unexpected event type
      return response.status(400).end();
    }
  }

  // Return a response to acknowledge receipt of the event
  response.json({received: true});
});

app.listen(4242, () => console.log('Running on port 4242'));
```

{% endtab %}

{% tab title="Python" %}

```python
import json
import os
import flask
from flask import request, jsonify
import complycube.eventverifier as ccevnt

# Sample flask app
app = flask.Flask(__name__)

# Provide your webhook secret to the EventVerifier
ev = ccevnt.EventVerifier(os.getenv('COMPLYCUBE_WEBHOOK_SECRET'))

@app.route('/webhook', methods=['POST'])
def webhook():
    if 'complycube-signature' not in request.headers:
        return jsonify({'received':'False'}), 400
    
    signature = request.headers['complycube-signature']
    try:
        event = ev.construct_event(request.get_data(),signature)
        check_id = event.payload.id
        if event.type == 'check.completed':
            check_outcome = event.payload.outcome
            print('Check %s completed with outcome %s' % 
                  (check_id, check_outcome))
        elif event.type == 'check.pending':
            print('Check %s is pending' % check_id)
        # ... Handle other expected events
        else:
            return jsonify({'received':'False'}), 400      
    except VerificationError:
        return jsonify({'received':'False'}), 400 
    
    return jsonify({'received':'True'}), 200

app.run()
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;
use ComplyCube\Model\Event;
use ComplyCube\EventVerifier;
use ComplyCube\Exception\VerificationException;

header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Complycube-Signature, X-Requested-With");
define("SIGNATURE_KEY", 'complycube-signature');

$data = file_get_contents('php://input');
$verifier = new \ComplyCube\EventVerifier('WEBHOOK_SECRET');
$headers = apache_request_headers();

try {
    if (!isset($headers[SIGNATURE_KEY])) {
        http_response_code(400);
        return;
    }
    $event = $verifier->constructEvent($data, $headers[SIGNATURE_KEY]);
    switch ($event->type) {
        case "check.completed":
            $outcome = $event->payload->outcome;
            # do completed check processing
            break;
        case "check.pending":
            # do pending check processing
            break;
        default:
            http_response_code(400);
            return;
    }
    http_response_code(200);
    return;
} catch (\ComplyCube\Exception\VerificationException $e) {
    http_response_code(400);
    return;
}
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using System.Text;
using System.Text.Json;
using ComplyCube.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;

namespace CCSimpleDotNetSample.Controllers {
 [ApiController]
 [Route("[controller]")]
 public class SimpleEventListenerController: ControllerBase {
  [HttpPost]
  public async Task < IActionResult > Post() {
   var re = Request;
   StringValues payloadSignature;
   re.Headers.TryGetValue("complycube-signature", out payloadSignature);

   // Replace WEBHOOK_SECRET with the secret from your dev console
   var evr = new EventVerifier("WEBHOOK_SECRET");

   // Use StreamReader to read the entire body of the event
   using(var reader = new StreamReader(Request.Body, Encoding.UTF8)) {
    var payloadText = await reader.ReadToEndAsync();
    
    if (string.IsNullOrWhiteSpace(payloadText)){
     return StatusCode(400);
    }
    
    try {
     // Build the Event object and confirm its signature
     var receivedEvent = evr.ConstructEvent(payloadText, payloadSignature);
     if (receivedEvent != null) {
      var payloadObject = JsonSerializer.Deserialize<Dictionary<string, object>>(
       payloadText
      );
      
      // process the payload and action accordingly
      if (payloadObject.TryGetValue("type", out var eventTypeObj) &&
       payloadObject.TryGetValue("payload", out var eventPayloadObj)) {
       var eventType = eventTypeObj.ToString();
       var eventPayload = JsonSerializer.Serialize(eventPayloadObj);

       switch (eventType) {
        case "check.completed":
         if (eventPayloadObj is Dictionary < string, object > payloadDict &&
          payloadDict.TryGetValue("outcome", out var outcome)) {
           // Do completed check processing
          }
         break;
        case "check.pending": {
          // Do pending check processing
         }
         break;
        default:
         return StatusCode(400);
       }
       return StatusCode(200, receivedEvent);
      }
     }
    } catch (ComplyCube.Net.Exceptions.VerificationException) {
     return StatusCode(400);
    }
    return StatusCode(400);
   }
  }
 }
}
```

{% endtab %}
{% endtabs %}

#### Verify manually

ComplyCube generates signatures using a hash-based message authentication code ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) with [SHA-256](https://en.wikipedia.org/wiki/SHA-2). Although using our official libraries to verify webhook event signatures is recommended, you can create a custom solution by following these steps.

1. Extract the `complycube-signature` from the HTTP headers.
2. Determine the expected signature by computing an HMAC with the SHA256 hash function. Use your webhook's secret as the key, and use the `request body` string as the message.
3. Compare the signature in the header to the expected signature.

### Best practices <a href="#best-practices" id="best-practices"></a>

#### Event types

You should configure your webhook endpoints to receive only the types of events required by your integration. Listening to extra events (or all events) will put undue strain on your server and is not recommended.

You can [change the events](/documentation/api-reference/other-resources/webhooks#event-types) a webhook endpoint will receive in the Dashboard or the API.

#### Handle duplicate events <a href="#duplicate-events" id="duplicate-events"></a>

Webhook endpoints might occasionally receive the same event more than once. We advise you to guard against duplicated event receipts by making your event processing [idempotent](https://en.wikipedia.org/wiki/Idempotence). One way of doing this is by logging the events you've processed and not processing already-logged events.

#### Order of events

ComplyCube does not guarantee the delivery of events in the order they are generated. Your endpoint should not expect delivery of events in a given order and should handle this accordingly. You can also use the API to fetch any missing objects.

#### Webhooks over HTTPS

If you use an HTTPS URL for your webhook endpoint, ComplyCube will validate that your server's connection is secure before sending your webhook data. For this to work, you must correctly configure your server to support HTTPS with a valid server certificate.


# Mobile App

Test KYC, AML, and identity verification flows instantly with the ComplyCube mobile app.

### Overview

The **ComplyCube for Business Mobile** app lets you run verification flows instantly without writing a single line of code. You can preview our demo flows or load and test your own workflows directly from your account, making it easy to validate configurations, experiment with settings, and share flows with your team.

This allows you to test end-to-end journeys in seconds, before you start integrating.

<figure><img src="/files/JI2WbmzX15AfBwP5tzxx" alt="" width="375"><figcaption><p>ComplyCube for Business Mobile App</p></figcaption></figure>

The ComplyCube mobile app makes it easy to test and refine your verification flows:

* **Instant testing**: Run your Live and Sandbox verification flows instantly.
* **Demo-ready**: Explore pre-built identity, liveness, and AML flows for internal demos and reviews.
* **Real user journey preview**: See exactly what your customers will experience.
* **Device-agnostic**: Test flows across different iOS and Android devices.
* **Rapid iteration**: Update a workflow in the ComplyCube Web Portal and test changes immediately in the app.
* **Easy troubleshooting**: Reproduce issues, test device variations, and review behavior end-to-end.

### Getting started

{% stepper %}
{% step %}

#### Download the app

<details>

<summary><i class="fa-apple">:apple:</i> iOS App Store</summary>

<div data-with-frame="true"><figure><img src="/files/n3ypFwaLNmXcD7AfkQtV" alt="" width="169"><figcaption></figcaption></figure></div>

Scan the QR code or visit [ComplyCube on the App Store](https://apps.apple.com/gb/app/complycube-for-business/id6756886861).

</details>

<details>

<summary><i class="fa-android">:android:</i> Android Play Store</summary>

<div align="center" data-with-frame="true"><figure><img src="/files/xp9UPKfmsAdq4RdKPsE3" alt="" width="165"><figcaption></figcaption></figure></div>

Scan the QR code or visit [ComplyCube on the Android Play Store](https://play.google.com/store/apps/details?id=com.complycube.kycaml.app).

</details>
{% endstep %}

{% step %}

#### Connect your ComplyCube account

To connect your ComplyCube account, simply scan your unique QR code when prompted. Your QR code is available on the [Mobile App page](https://portal.complycube.com/developers/mobile) on the Portal.
{% endstep %}

{% step %}

#### Start testing

Once your account is connected, you can test any verification workflow available in your Live or Sandbox environment.
{% endstep %}
{% endstepper %}

### Troubleshooting

<details>

<summary><strong>Workflow not loading</strong></summary>

* Check you are using the correct environment (Sandbox vs Live).
* Verify that the [workflow status](/documentation/product-guides/compliance-studio/workflows#workflow-statuses) is **Active**.
* Ensure you have [Workflows](/documentation/product-guides/compliance-studio/workflows) included in your [plan](https://portal.complycube.com/settings/plan).

</details>

<details>

<summary><strong>Verification step missing</strong></summary>

* Confirm that the workflow version you’re testing has been saved and activated.
* Ensure that the check type is included in your [plan](https://portal.complycube.com/settings/plan).

</details>

### Frequently asked questions

<details>

<summary><strong>Does the app store any personal data?</strong></summary>

No. The app only runs verification flows using your workflow. All data is processed through ComplyCube and stored according to your retention settings.

</details>

<details>

<summary><strong>Can I see the results of the verification flow?</strong></summary>

Yes, you can view the results of all verification flows via the [Workflow Sessions](https://portal.complycube.com/workflowSessions) page in the Portal.

</details>

<details>

<summary><strong>The QR code link is not working in the Portal?</strong></summary>

Only Account Owners, Administrators, and Developers can connect accounts to the app.

</details>

<details>

<summary><strong>Can end-customers use this app?</strong></summary>

No. It is strictly for internal testing and demo purposes.

</details>

<details>

<summary><strong>Are Live workflows available in the app?</strong></summary>

Yes, once you log in, you will be able to run any of your Sandbox or Live workflows.

</details>


# Model Context Protocol (MCP)

Connect the ComplyCube MCP server to Claude, Cursor, ChatGPT, and other AI assistants for grounded access to ComplyCube documentation and integration guides.

### Overview

Use the **ComplyCube Model Context Protocol (MCP) server** to connect **Claude**, **Cursor**, **ChatGPT**, **Gemini**, **Perplexity**, **VS Code extensions,** **Windsurf**, and other **MCP-compatible AI assistants** to ComplyCube documentation.

Use it to search ComplyCube docs, read full pages, and **generate code** grounded in current ComplyCube guidance.

This guide explains how ComplyCube MCP works, how to connect it, and how to use it for API, SDK, workflow, and webhook integrations.

{% hint style="info" %}
The ComplyCube MCP server provides read-only access to publicly available documentation. It cannot view or interact with your API keys, Portal account, client records, or verification data.
{% endhint %}

### What is MCP?

[Model Context Protocol](https://modelcontextprotocol.io/) is an open standard that lets AI assistants connect to external tools and data sources.

The ComplyCube MCP server gives your AI assistant access to this documentation. Once connected, the assistant can search the docs and read full pages while it answers questions or drafts code.

This helps your assistant use current ComplyCube documentation instead of relying only on older training data.

The ComplyCube MCP server is read-only. It only serves documentation. It does not have access to your API keys, Portal, clients, checks, cases, or Sandbox and Live account data.

{% hint style="info" %}
Use the MCP server to give your AI assistant access to ComplyCube documentation. It provides product knowledge and API context, while your application and backend continue to handle business logic and verification workflows.
{% endhint %}

### Works with every ComplyCube product

The MCP server covers the full ComplyCube documentation, so you can use it across the platform.

#### Verification checks

Ask about specific checks and verification flows:

* [Extensive AML screening](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEPs, and adverse media checks.
* [Document checks](/documentation/product-guides/identity-verification/document-check) for document authenticity and data extraction.
* [Identity checks](/documentation/quick-guides/api-quick-guide/run-an-identity-check) for liveness and biometric face match.
* [Proof of address checks](/documentation/quick-guides/api-quick-guide/perform-proof-of-address-check) for address document validation.
* [Multi-bureau checks](/documentation/product-guides/identity-verification/multi-bureau-check) for bureau and trusted data-source matching.

#### Integration paths

Use MCP to compare integration options and implementation details:

* [Hosted Solution](/documentation/quick-guides/hosted-solution-quick-guide) for a fully hosted flow.
* [Web SDK](/documentation/quick-guides/web-sdk-quick-guide) and [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide) for embedded experiences.
* [API Reference](https://docs.complycube.com/documentation/api-reference/) for an API integrations with granular controls.

#### Developer tools and operations

Use MCP to find exact implementation details fast:

* [Webhooks](/documentation/integration-resources/webhooks) for event handling and async updates.
* [Postman](/documentation/integration-resources/postman) and [testing data](/documentation/integration-resources/testing-data) for sandbox testing and debugging.
* [Compliance guidance](/documentation/trust-and-compliance/compliance) for trust, controls, and privacy coverage.

You can ask your AI assistant about any of these areas and it will search the right pages for you.

### What you can do

* Search the docs in plain language.
* Read full pages when a snippet is not enough.
* Draft integration code grounded in current ComplyCube guides.
* Debug headers, webhook payloads, and parameter names without leaving your editor.

In most AI clients, you do not need to call these directly. Ask your question normally and let the assistant choose when to **search** or **read**.

### Connect your AI assistant to the ComplyCube MCP server

You do not need to install anything locally. The ComplyCube MCP server runs online.

Copy this URL into your MCP client:

{% code title="Server URL" %}

```
https://docs.complycube.com/documentation/~gitbook/mcp
```

{% endcode %}

Most MCP-compatible clients let you add a remote server from their settings or connector menu.

Use these connection details:

* **Name:** ComplyCube Docs
* **Authentication:** None

Then:

1. Open your AI assistant's **MCP**, **connectors**, or **integrations** settings.
2. Add a new **remote MCP server**.
3. Enter the **ComplyCube Docs** name and URL.
4. **Save** the connection.
5. **Enable** the server in the workspace or chat where you want to use it.

{% hint style="info" %}
MCP setup steps vary by client and change often. If your assistant supports remote MCP servers, use the server URL above and follow that client's current setup flow.
{% endhint %}

### How to use the ComplyCube MCP server

After you connect the server, ask your assistant questions in **plain language**. You do not need to call the documentation tools yourself.

#### Find information in ComplyCube docs

Try prompts like:

* "How do I create a client and run a document check in Sandbox?"
* "Which ComplyCube integration path fits a hosted onboarding flow with minimal code?"
* "Which webhook events should I handle after a check completes?"

#### Generate ComplyCube integration code

Ask for code grounded in **current docs**, for example:

* "Write Node.js code that creates a client and starts a hosted verification flow".
* "Write a Python example that creates a check and retrieves the result".

For concrete implementation patterns, start with the [API Quick Guide](/documentation/quick-guides/api-quick-guide), [Hosted Solution Guide](/documentation/quick-guides/hosted-solution-quick-guide), [Web SDK Guide](/documentation/quick-guides/web-sdk-quick-guide), or [Mobile SDK Guide](/documentation/quick-guides/mobile-sdk-guide).

#### Debug your ComplyCube integration

Use the MCP server to inspect exact **field names** and **flows**:

* "Why does my webhook signature validation fail?"
* "Which parameters are required when I generate an SDK token?"

### Best practices for better prompts

* State whether you want a **workflow-based** or **check-based** integration path.
* Be specific about whether you use [Hosted Solution](/documentation/quick-guides/hosted-solution-quick-guide), [Web SDK](/documentation/quick-guides/web-sdk-quick-guide), [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide), or [direct API integration](/documentation/quick-guides/api-quick-guide).
* Ask for exact endpoint names, payload fields, and sequence steps.
* Keep **API keys**, **secrets**, and **personal data** out of prompts.
* Search first, then ask for full-page detail when needed.
* Always review generated code before you ship it.

### Privacy and scope

The MCP server only serves content from [ComplyCube documentation](/documentation).

It does not have access to your **Portal**, **sessions**, **API keys**, or **customer data**.

Your prompts and the returned documentation flow through your AI assistant provider. Check your provider's data policy before sharing sensitive information.


# Integration Checklist

Use this checklist to launch your KYC, AML, and identity verification integration from Sandbox to Live.

### Overview

When you’ve finished development and testing, use this checklist to confirm your integration is production-ready.

### Setup

* [ ] [Activate your account](https://portal.complycube.com/activate) in the Web Portal and obtain your **Live** API key.
* [ ] Use our [testing data](/documentation/integration-resources/testing-data) to simulate scenarios for all services you plan to use. Ensure your integration handles both success and error responses correctly.
* [ ] Ensure your integration is configured to use the correct environment by supplying the appropriate [API key](https://portal.complycube.com/developers/key).

### Validation

* [ ] If you have integrated our native [Mobile SDKs](/documentation/sdks), install and test the ComplyCube [iOS and Android mobile apps](/documentation/integration-resources/complycube-mobile-app) to validate your workflows.
* [ ] Handle `4xx` and `5xx` errors gracefully: validate inputs, retry transient errors, and provide helpful user feedback.
* [ ] Respect [rate limits](https://docs.complycube.com/api-reference/rate-limits) and [service quotas](https://docs.complycube.com/api-reference/service-quota) to avoid throttling or service denials in production.

### Webhooks

* [ ] Configure [webhook](https://portal.complycube.com/developers/webhooks) endpoints in the Live environment (note that Sandbox and Live webhooks are separate).
* [ ] Ensure your endpoint [verifies authenticity](/documentation/integration-resources/webhooks#signature-verification), handles retries or missed deliveries, and is idempotent (safe to process the same event more than once).

### Monitoring and security

* [ ] If using **continuous monitoring** (e.g. AML Screening Checks), ensure it is **enabled** only for active clients and **disabled** when no longer needed.
* [ ] Subscribe to our [status page](https://status.complycube.com) so your team is notified of any service disruptions or planned maintenance.
* [ ] If you use our SDKs, subscribe to [ComplyCube on GitHub](https://github.com/complycube) to stay informed about SDK updates and notifications.
* [ ] Store API keys securely, [rotate](https://portal.complycube.com/developers/key) them regularly, and never expose them in client-side code.


# Testing Data

Simulate KYC, AML, and identity verification outcomes with test data before going live.

### Overview

Use the ComplyCube [Sandbox](https://docs.complycube.com/api-reference/sandbox-and-live) to simulate specific service responses during testing.

### Test scenarios <a href="#test-scenarios" id="test-scenarios"></a>

<table><thead><tr><th width="180.72265625">Resource</th><th>Scenario</th><th>Trigger</th></tr></thead><tbody><tr><td>Workflow Sessions</td><td>Return <code>clear</code> as the outcome.</td><td>Default.</td></tr><tr><td>Workflow Sessions</td><td>Return <code>attention</code> as the outcome.</td><td>Run a workflow session on a client with the last name '<strong>attention</strong>'.</td></tr><tr><td>All Checks</td><td>Return <code>clear</code> as the outcome.</td><td>Default.</td></tr><tr><td>All Checks</td><td>Return <code>attention</code> as the outcome.</td><td>Run a check on a client with the last name '<strong>attention</strong>'.</td></tr><tr><td>All Checks</td><td>Return <code>not_processed</code> as the outcome.</td><td>Run a check on a client with the last name '<strong>failed</strong>'.</td></tr><tr><td>Risk Profile</td><td>Return overall risk score of <code>low</code>.</td><td>Add an <strong>address</strong>, <strong>nationality</strong>, <strong>birth country</strong>, or <strong>incorporation country</strong> to a client.</td></tr><tr><td>Risk Profile</td><td>Return overall risk score of <code>medium</code>.</td><td>Add an <strong>address</strong>, <strong>nationality</strong>, <strong>birth country</strong>, or <strong>incorporation country</strong> to a client with a middle name '<strong>medium-risk</strong>'.</td></tr><tr><td>Risk Profile</td><td>Return overall risk score of <code>high</code>.</td><td>Add an <strong>address</strong>, <strong>nationality</strong>, <strong>birth country</strong>, or <strong>incorporation country</strong> to a client with a middle name '<strong>high-risk</strong>'.</td></tr><tr><td>OTP (Email &#x26; SMS)</td><td>Return a successful OTP verification result.</td><td>Pass "123456" as the OTP.</td></tr><tr><td>Live Photos</td><td>Return an HTTP <code>200 OK</code> response.</td><td>Default. Only done via API.</td></tr></tbody></table>


# Teams and User Roles

Manage team access, roles, and permissions for your ComplyCube KYC and identity verification operations.

### Overview

You can invite team members to collaborate on your ComplyCube account and assign them specific roles to control what they can see and do.

[User roles](#user-roles) help protect sensitive information and ensure that each member only has access to the features they need.

Team members can be added and managed through the [team members page](https://portal.complycube.com/settings/team). From there, you can invite new users, assign roles, and update permissions at any time.

{% hint style="info" %}
Further controls can be applied to our [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) service using [User Groups](/documentation/product-guides/due-diligence-tools/advanced-case-management#user-groups).
{% endhint %}

### User roles

ComplyCube provides five predefined user roles to assign when adding team members to your account. Each role carries different levels of access and restrictions.

{% hint style="info" %}
The **Account Owner** role is automatically assigned to the person who created the account. Please contact [support](https://support.complycube.com/) to reassign the owner.
{% endhint %}

<table><thead><tr><th width="169.92578125">Role</th><th>Description</th></tr></thead><tbody><tr><td><strong>Administrator</strong></td><td>Full administrative privileges similar to the <strong>Account Owner</strong>, including managing API keys, account settings, and inviting new users.</td></tr><tr><td><strong>Developer</strong></td><td>Designed for technical users. Developers can access and manage API keys, but cannot manage team members.</td></tr><tr><td><strong>Analyst</strong></td><td>Suitable for compliance or risk teams. Analysts can view reports and update checks, but cannot view or refresh API keys.</td></tr><tr><td><strong>Support Specialist</strong></td><td>Intended for support teams. They can view and process client checks, but cannot change workflow and check configurations or validate results (approve/reject).</td></tr><tr><td><strong>View Only</strong></td><td>This role provides read-only access to all clients, workflows, sessions, and checks. View Only users cannot access account settings, automation rules, or API keys.</td></tr></tbody></table>

### Permissions table

Owner (**O**), Admin (**A**), Developer (**D**), Analyst (**AN**), Support Specialist (**SS**), View Only (**VO**).

<table data-full-width="false"><thead><tr><th width="278.94140625"></th><th width="74.52734375" align="center">O</th><th width="75.05859375" align="center">A</th><th width="74.80078125" align="center">D</th><th width="74.59765625" align="center">AN</th><th width="74.96484375" align="center">SS</th><th width="74.7265625" align="center">VO</th></tr></thead><tbody><tr><td><strong>Clients</strong> -<br>Create, Update, Export</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td></tr><tr><td><strong>Clients</strong> -<br>Bulk Imports</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Clients</strong> -<br>Delete</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Clients</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td></tr><tr><td><strong>Checks</strong> -<br>Create, Update, Import, Export</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td></tr><tr><td><strong>Checks</strong> -<br>Validate</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Checks</strong> -<br>Batch Processing</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Checks</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td></tr><tr><td><strong>Workflows and Templates</strong> -<br>Create, Update, Import, Export</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Workflows and Templates</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td></tr><tr><td><strong>Workflow Sessions</strong> -<br>Create, Update, Import, Export</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td></tr><tr><td><strong>Workflow Sessions</strong> -<br>Validate</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Workflow Sessions</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td></tr><tr><td><strong>Advanced Case Management</strong> -<br>Create, Update</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td></tr><tr><td><strong>Advanced Case Management</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td></tr><tr><td><strong>Advanced Case Management</strong> -<br>Delete</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Access Restriction Lists</strong> -<br>Create, Read, Update, Delete</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Banned Faces</strong> -<br>Create, Read, Update, Delete</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>AML Risk</strong> -<br>Update</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>AML Risk</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td></tr><tr><td><strong>Analytics &#x26; Insights</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td></tr><tr><td><strong>User Activity Log</strong> -<br>Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Automation</strong> -<br>Read, Update</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Developers</strong> -<br>Create, Update, Read</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>User Groups</strong> -<br>Create, Read, Update, Delete</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Brand Customization</strong> -<br>Update</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Team Member</strong> -<br>Invite, Read, Update, Delete</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Single Sign-On</strong> -<br>Read, Update</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Custom Lists</strong> -<br>Create, Read, Update, Delete</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr><tr><td><strong>Billing</strong> -<br>Invoices, Payments</td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center"><span data-gb-custom-inline data-tag="emoji" data-code="2714">✔️</span></td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr></tbody></table>


# Single Sign-On (SSO)

Set up SSO to secure access to the ComplyCube Web Portal for your KYC and identity verification teams.

### Overview

ComplyCube allows you to add team members and govern access to our **ComplyCube Web Portal** by easily integrating with your chosen **Identity Provider (IdP)** via **SAML**.

This integration ensures your team members benefit from a single sign-on (SSO) experience. It allows them to access ComplyCube using the same credentials and sign-in interface as your other service providers, enabling a **secure and cohesive user experience**.

Using SSO, your team members will be redirected to your IdP for authentication and authorization. Upon successful access verification, they will be seamlessly redirected back to ComplyCube.

{% hint style="warning" %}
When SSO is enabled, the standard ComplyCube sign-in flow will be disabled for all team members except the **Account Owner**. This safeguard ensures that, if the identity provider (IdP) becomes unavailable, the Account Owner can still access the Portal and deactivate SSO, restoring direct sign-in access for the rest of the team.
{% endhint %}

{% hint style="info" %}
This service is available through our **Enterprise Plan**. Get in touch with your Account Manager or [contact us](https://www.complycube.com/sales) to enable it.
{% endhint %}

### Just-in-Time (JIT) provisioning

ComplyCube supports JIT provisioning, allowing accounts for new team members to be created automatically at first sign-in. By default, all new members are assigned the '[Analyst](https://docs.complycube.com/documentation/guides/roles-and-permissions#user-roles)' role. The **ComplyCube Account Owner** or **Administrators** can later adjust this role through the [team members settings page](https://portal.complycube.com/settings/team).

{% hint style="info" %}
Should the number of **allocated seats** for an account be fully utilized, ComplyCube will stop provisioning new accounts. In such instances, your team member will get a message prompting them to contact their Account Owner.
{% endhint %}

### User roles with SSO

[User roles and permissions](/documentation/access-management/teams-and-user-roles) can be set via the [team members settings page](https://portal.complycube.com/settings/team) through the Portal.

### Removing accounts <a href="#removing-end-user-accounts" id="removing-end-user-accounts"></a>

Removing a team member from the IdP will prevent them from being able to sign in to ComplyCube. However, it will not remove their account from ComplyCube. **Accounts must be removed** from the ComplyCube [team members settings page](https://portal.complycube.com/settings/team).

### Requirements for SSO

* Your IdP must support the **SAML 2.0** standard.
* Your IdP must support **SHA256** for signatures.
* You must have **administrative permission** on the IdP.
* You must be an **Account Owner** or **Administrator** on ComplyCube.


# SSO with Okta

Configure Okta SSO for secure access to the ComplyCube Web Portal and your KYC operations.

### Overview

[Okta](https://www.okta.com) is an identity and access management platform that provides SSO solutions for organizations. It allows users to access multiple applications and services using a single set of credentials, aiming to simplify the user authentication experience. Okta operates on a **cloud platform** and **supports SAML 2.0**.

This guide outlines the steps to configure SSO using **Okta**.

{% hint style="info" %}
You must be an **Account Owner** or **Administrator** on ComplyCube and have **administrative permission** on Okta to set up SSO.
{% endhint %}

{% hint style="info" %}
**ComplyCube** does not send an email confirmation when the SSO setup is complete.
{% endhint %}

### Setup steps

{% stepper %}
{% step %}

#### Create an Okta account

The first step is to [create an account](https://www.okta.com) with Okta. When this guide was written, Okta offered a **free trial account** to assist with the initial setup.

You can follow their instructions to register an account and download their app on your phone to complete the setup.
{% endstep %}

{% step %}

#### Add integration to Okta and configure **SAML-based SSO**

Once your account is set up, log in and click **Admin** to switch to Admin mode.

<figure><img src="/files/e8ULB5fJIdIRShaNCYz9" alt="" width="563"><figcaption></figcaption></figure>

In admin mode, click **Applications → Create App Integration**.

<figure><img src="/files/zHuQfDy80xdY3JMosILd" alt="" width="563"><figcaption></figcaption></figure>

Select **SAML 2.0** as the sign-in method.

<figure><img src="/files/vtfbV6OhcLdwvIh9SaJT" alt="" width="563"><figcaption></figcaption></figure>

Add the App name "**ComplyCube**", then click **Next**.

<figure><img src="/files/0gGm2nwSrRCUGnR4LLaS" alt="" width="563"><figcaption></figcaption></figure>

Copy the **Audience** and **ACS Consumer URL** values from your ComplyCube [SSO settings page](https://portal.complycube.com/settings/sso) onto the SAML Settings of the application in Okta.

Also, as shown in the image below, please ensure the following **Attribute Statements** are mapped in Okta - '***firstName***', '***lastName***', and '***email***', as they will be used to update the user profile details in ComplyCube on every sign-in.

<figure><img src="/files/RhftNvpFevPjZrnYiR7m" alt=""><figcaption></figcaption></figure>

Click **Next**, then **Finish**.
{% endstep %}

{% step %}

#### People and group assignments

Once the application is added, the next step is to assign **people** or **groups** to that application. We recommend that assignments be made at a group level.

First, add the individual user to your Okta directory, **Directory → People**. Upon adding your users, you can create a group, **Directory → Group**, and assign the individuals to the group.

Now, navigate to the application, **Applications → ComplyCube**, click on **Assignments**, and assign your group.

<figure><img src="/files/iuI8LCytLqZOeIOequHO" alt="" width="563"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Update SSO settings in ComplyCube

Finally, navigate to your ComplyCube [SSO settings page](https://portal.complycube.com/settings/sso), update the **Sign-In URL,** and upload your **Signing Certificate** (i.e., X.509 certificate).

You can find the **Sign-In URL** in Okta — **Applications → ComplyCube**. On the **General** tab, copy the **Embed Link** and paste it into ComplyCube.

Then click the **Sign On** tab and scroll to the bottom to find the **Signing Certificates**. Download the **SHA-2** certificate, upload it into ComplyCube, and save your settings.

<figure><img src="/files/gqDBUKErtD4Xy8LzK51F" alt=""><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

That's it. You can now sign in to the ComplyCube Web Portal using SSO through Okta.


# SSO with Microsoft Entra ID

Configure Microsoft Entra ID SSO for secure access to the ComplyCube Web Portal and KYC operations.

### Overview

[Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id), formerly **Azure Active Directory (Azure AD)**, is a cloud-based identity and access management service. It allows organizations to manage users and groups, facilitating secure access to internal and external resources. Microsoft Entra ID supports SAML 2.0.

This guide outlines the steps to configure SSO using **Microsoft Entra ID**.

{% hint style="info" %}
You must be an **Account Owner** or **Administrator** on ComplyCube and have **administrative permission** on Entra ID to set up SSO.
{% endhint %}

{% hint style="info" %}
**ComplyCube** does not send an email confirmation when the SSO setup is complete.
{% endhint %}

### Setup steps

{% stepper %}
{% step %}

#### Create an Azure account

The first step is to [create an account](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id) with Microsoft Azure. When this guide was written, Microsoft Entra ID offered a **free trial account** to assist with the initial setup.

You can follow their instructions to register an account.
{% endstep %}

{% step %}

#### Register an application

1. Once your account is set up, you can go to the [Azure portal](https://portal.azure.com/) and sign in with your account.
2. Search for "Microsoft Entra ID" on the top navigation panel, and select the service.
3. Go to **Enterprise applications → New application**.
4. Select **Create your own application**, name your application "ComplyCube", select the **Non-gallery** option, and click **Create**.

<figure><img src="/files/QXfpuU82xd0mCZIcEHe7" alt="" width="375"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Configure SAML-based SSO

Select your newly created application under **Enterprise applications**.

Then, under **Manage**, in the application's left navigation menu, select **Single sign-on** and choose **SAML** as the method.

Now, set up the **Basic SAML Configuration** using values from your ComplyCube [SSO settings page](https://portal.complycube.com/settings/sso):

* **Identifier (Entity ID)**: An identifier for the application. Use the value of **Audience** from ComplyCube.
* **Reply URL (Assertion Consumer Service URL)**: The location where Microsoft Entra ID sends SAML responses. Use the **ACS Consumer URL** from ComplyCube.
* **Sign-on URL**: URL where users will sign in. Use the **ACS Consumer URL** from ComplyCube.

<figure><img src="/files/KeYhh5OhDYekiloAc2tH" alt=""><figcaption></figcaption></figure>

The next step is to configure your **Attributes & Claims** settings. As shown in the image below, please ensure the following **Attribute Statements** are mapped in Microsoft Entra ID - '***firstName***', '***lastName***', and '***email***', as they will be used to update the user profile details in ComplyCube on every sign-in.

<figure><img src="/files/3JvVHRUEn3k9y56r3yLY" alt="" width="563"><figcaption></figcaption></figure>

Click **Edit** on **SAML Certificate** and download the **Certificate (Base64)**.

<figure><img src="/files/Z4vJK2cHpDVkseE4ZFNJ" alt="" width="563"><figcaption></figcaption></figure>

**Edit** the **Token signing certificate** and ensure the **Signing Option** is "*Sign SAML Response and assertion*".

<figure><img src="/files/b1G4zmxFkiX14L6HJIRx" alt="" width="563"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Update SSO settings in ComplyCube

Now, go to your ComplyCube [SSO settings page](https://portal.complycube.com/settings/sso), update the **Sign-In URL,** and upload your **Signing Certificate** (i.e., X.509 certificate).

You can find the **Sign-In URL** in the **Single Sign-On** section of your **Application** in Microsoft Entra ID.

<figure><img src="/files/4Ps598uK4Omqm9fJsV3D" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### User and group assignments

Once the application is added and SSO is set up, the next step is to assign Microsoft Entra ID **users** or **groups** to the application. We recommend that assignments be made at the group level.

Under **Users and Groups**, select **Add user/group** to add the users or groups that should have access to this application in Microsoft Entra ID.

Once the assignment is complete, you can sign in to the ComplyCube Web Portal using SSO through Microsoft Entra ID.
{% endstep %}
{% endstepper %}


# Compliance

Review ComplyCube compliance certifications, security controls, data processing, and privacy standards for identity verification, KYC, KYB, and AML.

### Overview

ComplyCube helps regulated businesses meet identity verification, KYC, KYB, AML, and fraud prevention requirements through one platform.

This page outlines ComplyCube compliance certifications, security controls, data processing practices, and privacy coverage.

{% hint style="info" %}
For current documentation and evidence, visit the [ComplyCube Trust Center](https://trust.complycube.com).
{% endhint %}

### Compliance certifications and frameworks

ComplyCube maintains and supports the following certifications, standards, and privacy frameworks:

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th>Standard or framework</th><th>Coverage</th></tr></thead><tbody><tr><td><strong>ISO 27001:2022</strong></td><td>Information security management.</td></tr><tr><td><strong>ISO 9001:2015</strong></td><td>Quality management systems.</td></tr><tr><td><strong>UK Cyber Essentials</strong></td><td>Baseline cybersecurity controls.</td></tr><tr><td><strong>UK DIATF</strong></td><td>UK Digital Identity and Attributes Trust Framework alignment.</td></tr><tr><td><strong>ISO 30107-3</strong></td><td>Presentation attack detection testing.</td></tr><tr><td><strong>ACCS 4:2020</strong></td><td>Technical requirements for age check systems.</td></tr><tr><td><strong>GDPR</strong></td><td>EU data protection and privacy requirements.</td></tr><tr><td><strong>CCPA</strong></td><td>California privacy requirements.</td></tr></tbody></table>

### Security control areas

ComplyCube publishes controls across the following domains:

| Control area                     | Coverage                                                                                          |
| -------------------------------- | ------------------------------------------------------------------------------------------------- |
| **Infrastructure security**      | Privileged access restrictions, MFA, secure authentication, and network access controls.          |
| **Organizational security**      | Asset disposal, anti-malware, confidentiality agreements, password policy, and employee controls. |
| **Product security**             | Encryption at rest, control self-assessments, and penetration testing.                            |
| **Internal security procedures** | BC/DR planning, secure development lifecycle, whistleblower processes, and governance oversight.  |
| **Data and privacy**             | Data classification, retention, and customer data deletion procedures.                            |

### Data processing and privacy

ComplyCube applies the following data handling practices across verification and compliance workflows:

| Area                         | How ComplyCube handles it                                                                                                                                                                             |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Data minimization**        | Only data needed for the configured verification flow is collected and processed.                                                                                                                     |
| **Processing and residency** | Processing and storage follow the region selected for your account and use case. For regional handling and storage options, see [Data Residency](/documentation/trust-and-compliance/data-residency). |
| **Retention**                | Retention periods can be configured, with deletion workflows to support regulatory and business requirements.                                                                                         |
| **Subprocessors**            | Subprocessors are documented and bound by appropriate security and data protection obligations.                                                                                                       |
| **Data subject requests**    | Privacy requests are handled through documented processes, including export and deletion workflows where applicable.                                                                                  |

### Audit trail

Every action and verification produces a detailed evidence trail that helps organizations understand how decisions are made and demonstrate compliance when needed.

Depending on the verification type, the available evidence may include:

* Verification events and processing timeline.
* Identity document images and extracted data.
* Biometric verification results, including liveness and face match outcomes.
* AML screening findings and verification outcomes.
* Reviewer actions and decision history, where applicable.
* Downloadable reports and supporting evidence.

All evidence is securely retained and governed by configurable access permissions and retention settings, helping organizations meet internal governance and regulatory requirements.

### Security measures

ComplyCube protects customer data through multiple layers of technical, operational, and organizational security controls.

Depending on your deployment and configuration, these safeguards include:

* Encryption for data in transit and at rest.
* Secure key management and tightly controlled access to sensitive systems.
* Signed webhooks, IP allowlists, and network security controls.
* Continuous vulnerability assessments and regular penetration testing.
* Business continuity, disaster recovery, and incident response processes.

Together, these measures help protect sensitive information, maintain platform resilience, and support industry security and compliance requirements.


# Data Residency

Learn what ComplyCube stores for KYC, AML, and identity verification, and review available data residency options.

### Overview

ComplyCube supports data residency for KYC, AML, and identity verification workflows across multiple regions.

{% hint style="info" %}
Data residency configurations apply to both processing and data at rest within the supported region you select.
{% endhint %}

{% hint style="info" %}
For more information about data handling, processing, and security documentation, visit the [ComplyCube Trust Center](https://trust.complycube.com).
{% endhint %}

### What data ComplyCube stores

ComplyCube stores the following data categories as part of identity verification and compliance workflows:

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Data type</th><th>Description</th></tr></thead><tbody><tr><td>Customer personally identifiable information</td><td>Customer data collected from user input, documents, and verification workflows, such as name, date of birth, address, and document details.</td></tr><tr><td>Business information</td><td>Business and company data used for account management, KYB workflows, and related compliance checks where applicable.</td></tr><tr><td>Biometric data</td><td>Selfie images, video frames, and liveness signals used to confirm user presence and prevent spoofing.</td></tr><tr><td>Verification data</td><td>Data generated during verification workflows, including check inputs, results, and related decisioning signals.</td></tr><tr><td>API logs</td><td>Request and response data used for platform operations, monitoring, and troubleshooting.</td></tr></tbody></table>

### Available data residency options

ComplyCube offers the following data residency options for customers with regional storage or processing requirements:

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th>Region</th><th>Description</th><th>Availability</th></tr></thead><tbody><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ea-1f1fa">🇪🇺</span> EU</td><td>Default for EU registrations.</td><td>All customers</td></tr><tr><td>🇺🇸 United States</td><td>Default for US registrations.</td><td>All customers</td></tr><tr><td>🇬🇧 United Kingdom</td><td>Default for UK registrations.</td><td>All customers</td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1e6">🇨🇦</span> Canada</td><td>Data stored within Canada.</td><td>Growth plan and beyond</td></tr><tr><td>🇦🇪 United Arab Emirates</td><td>Data stored within the UAE.</td><td>Growth plan and beyond</td></tr><tr><td>🇸🇬 Singapore</td><td>Data stored within Singapore.</td><td>Growth plan and beyond</td></tr><tr><td>🇦🇺 Australia</td><td>Data stored within Australia.</td><td>Growth plan and beyond</td></tr><tr><td>🇧🇷 Brazil</td><td>Data stored within Brazil.</td><td>Growth plan and beyond</td></tr><tr><td>🌍 Custom</td><td>Data stored within needs.</td><td>Enterprise plans</td></tr></tbody></table>

For **sub-processors**, **certifications**, and **security documentation**, visit the [ComplyCube Trust Center](https://trust.complycube.com).


# Service Status

Monitor ComplyCube service status, uptime, incidents, and scheduled maintenance updates in real time.

### Overview

Use the ComplyCube status page to monitor real-time service status, uptime, incidents, and maintenance updates.

{% hint style="success" %}
ComplyCube has maintained **100% uptime** across all regions for the past 5 years.
{% endhint %}

{% hint style="info" %}
View live status, incident history, and maintenance notices on the [ComplyCube Status Page](https://status.complycube.com).
{% endhint %}

### Platform status and uptime

The status page helps you track:

* Current platform and service availability.
* Incident updates and resolution progress.
* Scheduled maintenance notices.

### Incident updates

When a service issue affects availability or performance, updates are posted on the status page as the incident progresses.

Published updates may include:

* Incident identification and affected services.
* Ongoing status updates.
* Resolution confirmation and follow-up details.

### Scheduled maintenance notices

Planned maintenance is announced on the status page in advance whenever possible.

Maintenance notices help you prepare for:

* Expected service impact.
* Planned maintenance windows.
* Completion updates after work finishes.

### Support and escalation

If you see an issue that is not reflected on the status page, contact your usual ComplyCube support channel or account manager.


# KYC, AML & Identity Verification

ComplyCube KYC, AML screening, and identity verification for faster customer onboarding, KYB, biometric liveness, fraud prevention, and compliance automation.

ComplyCube provides a comprehensive suite of verification solutions to help businesses automate **KYC and KYB onboarding**, meet **AML compliance requirements**, and reduce **fraud risk**.

Our platform combines identity verification, sanctions and watchlist screening, compliance automation, and fraud detection tools to support secure customer onboarding and ongoing monitoring.

Use the guides below to explore each service and understand how it supports your compliance and verification workflows.

{% hint style="info" %}
If you’re new to ComplyCube, start with [Workflows](/documentation/product-guides/compliance-studio/workflows) to design and automate your verification journeys.
{% endhint %}

### Compliance Studio

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><img src="/files/skl5VTgdjZX7J15zwrqN" alt="Workflows icon" data-size="line"> <mark style="color:blue;"><strong>Workflows</strong></mark></td><td>Build end-to-end KYC onboarding journeys. Orchestrate identity verification, AML screening, and policy decisions in one flow.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/dKzFxEJx6m2x4dyaeydQ">/spaces/KyFKMqftsmT6qln9zo5y/pages/dKzFxEJx6m2x4dyaeydQ</a></td></tr><tr><td><img src="/files/6KioXZ5ifk8FtQhVh7gR" alt="Smart Forms icon" data-size="line"> <mark style="color:blue;"><strong>Smart Forms</strong></mark></td><td>Dynamic KYC questionnaires. Collect customer data, declarations, and supporting documents inside verification flows.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/iN9Cw8m1MY4Tcv1J6PkC">/spaces/KyFKMqftsmT6qln9zo5y/pages/iN9Cw8m1MY4Tcv1J6PkC</a></td></tr><tr><td><img src="/files/CaM6IW2ree3YFk62chG7" alt="" data-size="line"> <mark style="color:blue;"><strong>eSignatures</strong></mark></td><td>Capture eIDAS-recognized electronic signatures for agreements and compliance documents, including SES, AdES, and QES.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/Ddynl9Su1AknvMkyslIF">/spaces/KyFKMqftsmT6qln9zo5y/pages/Ddynl9Su1AknvMkyslIF</a></td></tr><tr><td><img src="/files/NMq8I7dWZJ1v0VPAtbuL" alt="Compliance Policies icon" data-size="line"> <mark style="color:blue;"><strong>Compliance Policies</strong></mark></td><td>Automate KYC/AML decisioning with regulatory and custom rules. Generate audit-ready evidence inside workflows.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/yMBB2O5f9jvxt8wSiXgd">/spaces/KyFKMqftsmT6qln9zo5y/pages/yMBB2O5f9jvxt8wSiXgd</a></td></tr></tbody></table>

### Watchlist, PEP & Adverse Media

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><img src="/files/I8cEts9MPIEiiC5rsMlx" alt="AML Screening icon" data-size="line"> <mark style="color:blue;"><strong>AML Screening</strong></mark></td><td>Sanctions, PEP, and adverse media screening with continuous AML monitoring for KYC and KYB.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JAF0I0xV8IXZOscPw">/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JAF0I0xV8IXZOscPw</a></td></tr><tr><td><img src="/files/o9GBxkVE0k1bsx2Mfq1x" alt="Custom Lists icon" data-size="line"> <mark style="color:blue;"><strong>Custom Lists</strong></mark></td><td>Extend AML screening and continuous monitoring using internal watchlists and custom data sources.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-MVvn2s46XsSTMJqh5ip">/spaces/KyFKMqftsmT6qln9zo5y/pages/-MVvn2s46XsSTMJqh5ip</a></td></tr><tr><td><img src="/files/nUzcfXWzBcLD7qH9hIHR" alt="Bulk Processing icon" data-size="line"> <mark style="color:blue;"><strong>Bulk Processing</strong></mark></td><td>Run batch AML screening checks with ease through the Portal or SFTP integration.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-MbgD2CpsScoZlm8QhSv">/spaces/KyFKMqftsmT6qln9zo5y/pages/-MbgD2CpsScoZlm8QhSv</a></td></tr></tbody></table>

### Identity Verification

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><img src="/files/B6jtqeXYXH3Gwi99f7AH" alt="Document Check icon" data-size="line"> <mark style="color:blue;"><strong>Document Check</strong></mark></td><td>Verify government-issued ID documents for KYC and extract structured identity data using OCR and MRZ analysis.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7IRKF3XH0kjZi9JFgx">/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7IRKF3XH0kjZi9JFgx</a></td></tr><tr><td><img src="/files/CZhFBeaChJU7lsaqm5jn" alt="eID Check icon" data-size="line"> <mark style="color:blue;"><strong>eID Check</strong></mark></td><td>Electronic identity verification (eID) via schemes like BankID, MitID, and others.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/f01skoLpT64xSYVCFAYc">/spaces/KyFKMqftsmT6qln9zo5y/pages/f01skoLpT64xSYVCFAYc</a></td></tr><tr><td><img src="/files/OnKfTgv9n9d8FvVu2hPh" alt="Multi-Bureau Check icon" data-size="line"> <mark style="color:blue;"><strong>Multi-Bureau Check</strong></mark></td><td>Verify customer identity and address details against authoritative data sources to enable no-document KYC identity verification.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mklreu0640dY_tPEH4X">/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mklreu0640dY_tPEH4X</a></td></tr><tr><td><img src="/files/sxvsIeO3pRHi1ha4xJn6" alt="Driving License Check icon" data-size="line"> <mark style="color:blue;"><strong>Driving License Check</strong></mark></td><td>Driving licence verification against issuing authorities. Retrieve status, entitlement, and restriction details.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/x9Gf1ZB1FuN7Qep14wXS">/spaces/KyFKMqftsmT6qln9zo5y/pages/x9Gf1ZB1FuN7Qep14wXS</a></td></tr><tr><td><img src="/files/CcBEdACKukBMHoMv8aEl" alt="Identity Fraud Check icon" data-size="line"> <mark style="color:blue;"><strong>Identity Fraud Check</strong></mark></td><td>UK identity fraud check for KYC. Verify customer details against authoritative sources and fraud risk databases. <span data-gb-custom-inline data-tag="emoji" data-code="1f1ec-1f1e7">🇬🇧</span></td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/vOcx7R9AW5wq3oY8dEf7">/spaces/KyFKMqftsmT6qln9zo5y/pages/vOcx7R9AW5wq3oY8dEf7</a></td></tr><tr><td><img src="/files/xOA5nvD3cOCD25LThWzx" alt="SSN Check icon" data-size="line"> <mark style="color:blue;"><strong>SSN Check</strong></mark></td><td>US Social Security Number (SSN) verification for KYC. Validate SSNs against official records. <span data-gb-custom-inline data-tag="emoji" data-code="1f1fa-1f1f8">🇺🇸</span></td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/U3YNpumSqf5p73XTFXxC">/spaces/KyFKMqftsmT6qln9zo5y/pages/U3YNpumSqf5p73XTFXxC</a></td></tr></tbody></table>

### Biometric & Liveness Verification

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><img src="/files/QjoKxqYemvzbioMjLTF7" alt="Identity Check icon" data-size="line"> <mark style="color:blue;"><strong>Identity Check</strong></mark></td><td>PAD-certified selfie liveness detection and face matching for biometric identity verification.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JB4mPJysdnVjAxEF8">/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JB4mPJysdnVjAxEF8</a></td></tr><tr><td><img src="/files/PuYuX7Y5en8HfUtlz1wn" alt="Enhanced Identity Check icon" data-size="line"> <mark style="color:blue;"><strong>Enhanced Check</strong></mark></td><td>Video liveness verification with active challenges, advanced spoof detection, and face matching.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-MV16zEk-kfNM774oXLU">/spaces/KyFKMqftsmT6qln9zo5y/pages/-MV16zEk-kfNM774oXLU</a></td></tr><tr><td><img src="/files/sGeAr9qCZ0Ik6VH7gYb7" alt="Age Estimation icon" data-size="line"> <mark style="color:blue;"><strong>Age Estimation</strong></mark></td><td>Biometric age estimation from a selfie. Useful for age-gated onboarding and access control.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/o2NLY5oxNIhTMrLfhuhJ">/spaces/KyFKMqftsmT6qln9zo5y/pages/o2NLY5oxNIhTMrLfhuhJ</a></td></tr><tr><td><img src="/files/1iYCFJFK9PCS3QzyEdBX" alt="Face Authentication icon" data-size="line"> <mark style="color:blue;"><strong>Face Authentication</strong></mark></td><td>Facial biometric authentication for passwordless login, account recovery, and more.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/9sc1OvbzpsInx2QW007B">/spaces/KyFKMqftsmT6qln9zo5y/pages/9sc1OvbzpsInx2QW007B</a></td></tr></tbody></table>

### Digital Fraud Intelligence

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><img src="/files/0ncZGAmV4aDGPW4mJ9yj" alt="Device Intelligence icon" data-size="line"> <mark style="color:blue;"><strong>Device Intelligence</strong></mark></td><td>Analyze customer devices for tampering signals, suspicious activity, and other high-risk indicators.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/zYpqVfej1Y68f0GKp2xo">/spaces/KyFKMqftsmT6qln9zo5y/pages/zYpqVfej1Y68f0GKp2xo</a></td></tr><tr><td><img src="/files/Z1ZMfid1JHTdFz3eh4R9" alt="Email Intelligence icon" data-size="line"> <mark style="color:blue;"><strong>Email Intelligence</strong></mark></td><td>Email address risk checks. Detect disposable emails, breach exposure, and fraud signals.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/RNnRTspQyoWpQsfdbZrP">/spaces/KyFKMqftsmT6qln9zo5y/pages/RNnRTspQyoWpQsfdbZrP</a></td></tr><tr><td><img src="/files/sHD2Jwh802TG3Rz4zMBl" alt="Mobile Intelligence icon" data-size="line"> <mark style="color:blue;"><strong>Mobile Intelligence</strong></mark></td><td>Phone number risk checks. Detect anomalies, abuse, and fraud signals.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/IByxrgzuLdoe9EFWgmnJ">/spaces/KyFKMqftsmT6qln9zo5y/pages/IByxrgzuLdoe9EFWgmnJ</a></td></tr></tbody></table>

### KYC Automation Services

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><img src="/files/2RAXREWmYeGw0h4CAXTT" alt="Proof of Address Check icon" data-size="line"> <mark style="color:blue;"><strong>Proof of Address Check</strong></mark></td><td>Extract and match address data from PoA documents like utility bills and bank statements.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mkl3mo1hHWaOCsJ6k38">/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mkl3mo1hHWaOCsJ6k38</a></td></tr><tr><td><img src="/files/YL9hzw8sc61z5zRT8b9T" alt="Company Search &#x26; Insights icon" data-size="line"> <mark style="color:blue;"><strong>Company Insights</strong></mark></td><td>KYB company search and business verification. Retrieve company, director, and beneficial ownership (UBO) information.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/KLcWJLLDy4tMqSPGh044">/spaces/KyFKMqftsmT6qln9zo5y/pages/KLcWJLLDy4tMqSPGh044</a></td></tr><tr><td><img src="/files/Fh1e3fmscOwsqinF5XYn" alt="Address Search icon" data-size="line"> <mark style="color:blue;"><strong>Address Search</strong></mark></td><td>Check, correct, and format customer addresses for cleaner KYC data.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/a4AWQS7NFvhXGmTwYbSy">/spaces/KyFKMqftsmT6qln9zo5y/pages/a4AWQS7NFvhXGmTwYbSy</a></td></tr><tr><td><img src="/files/XG7iyXwbjz8F2VoRh4Ds" alt="Autofill icon" data-size="line"> <mark style="color:blue;"><strong>Autofill</strong></mark></td><td>Identity document OCR and data extraction. Parse MRZ/VIZ and barcodes to prefill onboarding forms.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/yo8bgTCLMlg3TKDOMVct">/spaces/KyFKMqftsmT6qln9zo5y/pages/yo8bgTCLMlg3TKDOMVct</a></td></tr><tr><td><img src="/files/MejJryIQ2OSoGvDdsqDJ" alt="SMS Verification icon" data-size="line"> <mark style="color:blue;"><strong>SMS Verification</strong></mark></td><td>SMS OTP verification for confirming phone ownership during customer onboarding.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/kFSTtdTYhcX1llAMrUG1">/spaces/KyFKMqftsmT6qln9zo5y/pages/kFSTtdTYhcX1llAMrUG1</a></td></tr><tr><td><img src="/files/Z1ZMfid1JHTdFz3eh4R9" alt="Email Verification icon" data-size="line"> <mark style="color:blue;"><strong>Email Verification</strong></mark></td><td>Email OTP verification for confirming inbox ownership during customer onboarding.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/DOso1ATepbXnzied4sMs">/spaces/KyFKMqftsmT6qln9zo5y/pages/DOso1ATepbXnzied4sMs</a></td></tr></tbody></table>

### Due Diligence Tools

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><img src="/files/JO0WMNgSpKjXLXbAyXrh" alt="AML Risk Scoring icon" data-size="line"> <mark style="color:blue;"><strong>AML Risk Scoring</strong></mark></td><td>Customer AML risk scoring for KYC and KYB. Combine screening and risk factors to trigger CDD/EDD.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7OGRAusRJo7dNJckV8">/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7OGRAusRJo7dNJckV8</a></td></tr><tr><td><img src="/files/aksYCEEC4YaehWWPe8Iz" alt="Advanced Case Management icon" data-size="line"> <mark style="color:blue;"><strong>Case Management</strong></mark></td><td>Manage compliance cases with tasks, lifecycle stages, and a full audit trail for reviews and escalations.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/ciKS5UilutT3y936hJex">/spaces/KyFKMqftsmT6qln9zo5y/pages/ciKS5UilutT3y936hJex</a></td></tr><tr><td><img src="/files/QIw6HGjFIzXg0WiQCK7E" alt="Automation icon" data-size="line"> <mark style="color:blue;"><strong>Automation</strong></mark></td><td>Automate verification checks with custom rules tailored to your risk appetite.</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M9-Bt40ZMwrWuEtTDB5">/spaces/KyFKMqftsmT6qln9zo5y/pages/-M9-Bt40ZMwrWuEtTDB5</a></td></tr></tbody></table>


# United Kingdom KYC, AML and verification coverage

Verify individuals and businesses in the United Kingdom with ComplyCube’s KYC, KYB, AML screening, document verification, proof of address and biometric verification services.

Use this guide to understand UK coverage across data sources, identity documents, verification checks, AML screening, business verification and compliance policy workflows.

This guide is useful for **compliance**, **product** and **onboarding teams** building **UK customer verification**, **AML screening** or **business verification flows**.

### UK coverage snapshot

{% hint style="success" icon="circle-check" %}
ComplyCube supports UK verification journeys across **individuals**, **businesses**, **AML screening**, **address verification** and **biometric checks** using local and global data sources.
{% endhint %}

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th width="246.79296875">Area</th><th>UK coverage</th></tr></thead><tbody><tr><td><strong>Population coverage</strong></td><td>95%+ of the adult population.*</td></tr><tr><td><strong>Identity and address data sources</strong></td><td>Government, credit agencies, utility authorities and commercial databases.</td></tr><tr><td><strong>Supported ID documents</strong></td><td>Passport, driving licence and residence permit.</td></tr><tr><td><strong>Address verification</strong></td><td>Proof of address documents, bureau data and address validation.</td></tr><tr><td><strong>AML screening</strong></td><td>Sanctions, PEPs, watchlists, adverse media and ongoing monitoring.</td></tr><tr><td><strong>Business verification</strong></td><td>Companies House data, company profiles, directors, ownership and connected-party screening.</td></tr></tbody></table>

<sup>\* Coverage depends on the input fields provided, enabled checks and account setup.</sup>

### Why use ComplyCube for UK verification?

* Verify individuals and businesses using one platform.
* Combine document, biometric, address, bureau and AML checks in a single workflow.
* Apply Compliance Policies to standardise risk-based decisions and reduce manual review effort.
* Monitor customers and businesses continuously for changes in risk.
* Preserve audit-ready evidence across checks, workflows and policy decisions.

### What you can verify in the UK

Choose the verification path that matches your UK onboarding, AML or business verification use case.

#### Individual checks

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th width="286.2705078125">Verification need</th><th>Recommended service</th><th>Use it to</th></tr></thead><tbody><tr><td>Verify a person’s identity</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JB4mPJysdnVjAxEF8">Identity Check</a> and <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7IRKF3XH0kjZi9JFgx">Document Check</a></td><td>Check ID documents, selfies and liveness.</td></tr><tr><td>Verify an address</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mkl3mo1hHWaOCsJ6k38">Proof of Address Check</a> and <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mklreu0640dY_tPEH4X">Multi-Bureau Check</a></td><td>Confirm UK address data using documents and bureau-backed sources.</td></tr><tr><td>Verify without a document</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mklreu0640dY_tPEH4X">Multi-Bureau Check</a> or <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/vOcx7R9AW5wq3oY8dEf7">Identity Fraud Check</a></td><td>Corroborate customer details against UK data sources.</td></tr><tr><td>Driving licence verification</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/x9Gf1ZB1FuN7Qep14wXS">Driving License Check</a></td><td>Run entitlement checks, validate DVLA records, and return infractions where available.</td></tr></tbody></table>

#### AML and monitoring

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th width="286.2705078125">Verification need</th><th>Recommended service</th><th>Use it to</th></tr></thead><tbody><tr><td>Screen AML risk</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JAF0I0xV8IXZOscPw">AML Screening Check</a></td><td>Screen sanctions, PEPs, watchlists and adverse media.</td></tr><tr><td>Extend screening with internal lists</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-MVvn2s46XsSTMJqh5ip">Custom Lists</a></td><td>Screen UK customers and businesses against your internal watchlists and proprietary datasets.</td></tr><tr><td>Monitor ongoing risk</td><td><a href="/pages/-M7JAF0I0xV8IXZOscPw">Continuous Monitoring</a></td><td>Monitor individuals and businesses for changes in real-time.</td></tr><tr><td>Score customer or business risk</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7OGRAusRJo7dNJckV8">AML Risk Scoring</a></td><td>Apply country, screening and verification risk factors.</td></tr></tbody></table>

#### Business and workflow controls

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th width="286.2705078125">Verification need</th><th>Recommended service</th><th>Use it to</th></tr></thead><tbody><tr><td>Verify a business</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/KLcWJLLDy4tMqSPGh044">Company Search &#x26; Insights</a></td><td>Retrieve UK company profile, director and ownership data.</td></tr><tr><td>Capture signed approvals</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/Ddynl9Su1AknvMkyslIF">eSignatures</a></td><td>Collect signed declarations, approvals and consent during UK onboarding flows.</td></tr><tr><td>Build a risk-based journey</td><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/dKzFxEJx6m2x4dyaeydQ">Workflows</a> and <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/yMBB2O5f9jvxt8wSiXgd">Compliance Policies</a></td><td>Apply KYC, AML, Right to Work, Right to Rent or enhanced due diligence rules.</td></tr></tbody></table>

### UK individual verification

For UK individual onboarding, ComplyCube lets you combine document verification, biometric checks, bureau-backed identity corroboration, proof of address and fraud signals in one risk-based journey.

#### Supported checks

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th>Check</th><th>What it does</th></tr></thead><tbody><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7IRKF3XH0kjZi9JFgx">Document Check</a></td><td>Verifies passports, driving licences, residence permits and supported document variants.</td></tr><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JB4mPJysdnVjAxEF8">Identity Check</a></td><td>Matches the customer’s selfie to their ID document and performs passive liveness checks.</td></tr><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-MV16zEk-kfNM774oXLU">Enhanced Identity Check</a></td><td>Adds video-based liveness challenges for higher-assurance verification flows.</td></tr><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/9sc1OvbzpsInx2QW007B">Face Authentication</a></td><td>Re-checks a returning user’s face for sign-in, recovery or step-up verification.</td></tr><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mklreu0640dY_tPEH4X">Multi-Bureau Check</a></td><td>Corroborates name, date of birth, address or ID data against UK bureau and reference sources.</td></tr><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-Mkl3mo1hHWaOCsJ6k38">Proof of Address Check</a></td><td>Extracts address data from proof of address documents and compares it with submitted details.</td></tr><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/vOcx7R9AW5wq3oY8dEf7">Identity Fraud Check</a></td><td>Screens identity and address attributes against fraud-related datasets.</td></tr><tr><td><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/x9Gf1ZB1FuN7Qep14wXS">Driving License Check</a></td><td>Validates UK driving licence details against DVLA records.</td></tr></tbody></table>

#### Supported identity and address documents

**Identity documents**

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Document type</th><th>UK coverage</th></tr></thead><tbody><tr><td>Passport</td><td>UK passports, including national, international, diplomatic, ePassport and passport card variants.</td></tr><tr><td>Driving licence</td><td>UK driving licences.</td></tr><tr><td>Residence permit</td><td>UK residence permits.</td></tr></tbody></table>

{% hint style="success" icon="circle-check" %}
**NFC checks for UK government IDs**

For compatible government-issued identity documents in the UK, [NFC chip verification](/documentation/product-guides/identity-verification/document-check/nfc-chip-verification) can verify the embedded **NFC chip**. This adds a **higher level of assurance** by helping confirm that the physical document is genuine, chip-enabled, and consistent with the submitted identity information.
{% endhint %}

**Proof of address documents**

Proof of Address Check supports common UK proof of address documents, including:

* Bank statements
* Utility bills
* Driving licences
* Tax documents

Proof of Address Check extracts address data, compares it to the submitted customer details and can evaluate additional geolocation signals where available.

### UK data sources and matching

ComplyCube can verify UK customers using **data-led checks**, even when a document-first journey is not required. Depending on the check type, submitted customer attributes and account configuration, ComplyCube may use a range of local and global sources to corroborate identity and address details.

#### Attributes that can be corroborated

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Attribute</th><th>Used for</th></tr></thead><tbody><tr><td>Name</td><td>Confirms the customer’s identity details against trusted records</td></tr><tr><td>Date of birth</td><td>Helps distinguish between individuals with similar names</td></tr><tr><td>Address</td><td>Confirms the customer’s residential address and supports proof of address checks</td></tr></tbody></table>

#### Source categories

ComplyCube may use the following source categories for UK identity and address corroboration:

* Government data
* Credit agency data
* Utility data
* Postal data
* Telecom data
* Commercial data
* Proprietary data

{% hint style="success" %}
Source availability and matching behaviour can vary depending on the check, submitted customer details, enabled data sources and account setup.
{% endhint %}

#### Bureau-based verification

Multi-Bureau Check can verify UK customers using bureau and reference data.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Matching rule</th><th>Description</th></tr></thead><tbody><tr><td>Default matching</td><td>Verifies when the customer’s name matches plus one additional attribute, such as date of birth, address or ID number.</td></tr><tr><td>Optional 2+2 matching</td><td>Checks two matching identity attributes across two separate trusted data sources, where enabled.</td></tr></tbody></table>

{% hint style="success" icon="circle-check" %}
**2+2 matching**

2+2 matching is an optional UK bureau rule. It adds another layer of corroboration by checking two identity attributes across two separate trusted data sources.
{% endhint %}

### UK AML screening and monitoring

Use AML Screening Check to screen UK individuals and businesses at onboarding and monitor them for changes over time.

#### AML coverage

{% hint style="success" icon="circle-check" %}
[AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) screens individuals and businesses against more than 3,000 international, regional and local sources, with support for onboarding checks and continuous monitoring.
{% endhint %}

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="373.4873046875">Capability</th><th>Coverage</th></tr></thead><tbody><tr><td>Sanctions screening</td><td>UK and global lists, including HM Treasury, OFSI, United Nations, OFAC and other sources.</td></tr><tr><td>PEP screening</td><td>Senior political figures, public officials, regional officials and international organisation roles.</td></tr><tr><td>Watchlist screening</td><td>Global, regional and internal watchlists.</td></tr><tr><td>Adverse media</td><td>Curated adverse media from verified global sources.</td></tr><tr><td>Ongoing monitoring</td><td>Continuous monitoring with alerts when risk changes.</td></tr><tr><td>AML Risk Scoring</td><td>Risk scoring using screening, country and customer or business risk factors.</td></tr></tbody></table>

### UK Fraud and intelligence checks

Use digital fraud signals to strengthen UK onboarding and detect risky behaviour across email, phone, device and document channels.

<table><thead><tr><th width="319.048828125">Check</th><th>Description</th></tr></thead><tbody><tr><td><a href="/pages/RNnRTspQyoWpQsfdbZrP">Email Intelligence</a></td><td>Detect disposable, risky, breached and low-trust email accounts.</td></tr><tr><td><a href="/pages/IByxrgzuLdoe9EFWgmnJ">Mobile Intelligence</a></td><td>Review phone number activity, abuse, carrier and reputation signals.</td></tr><tr><td><a href="/pages/zYpqVfej1Y68f0GKp2xo">Device Intelligence</a></td><td>Detect device tampering, emulator use, VPN or proxy use and other high-risk device signals.</td></tr><tr><td><a href="/pages/kFSTtdTYhcX1llAMrUG1">SMS Verification</a></td><td>Send a one-time passcode to verify phone ownership.</td></tr><tr><td><a href="/pages/-M7IRKF3XH0kjZi9JFgx#analysis-performed">Security Element Verification</a></td><td>Check built-in document security features, such as holograms and format protections.</td></tr><tr><td><a href="/pages/-M7IRKF3XH0kjZi9JFgx">Document Tamper Detection</a></td><td>Detect image manipulation, photocopies, portrait swaps and other document forgeries.</td></tr></tbody></table>

### UK driving licence verification

Use Driving License Check to validate UK driving licence details against DVLA records.

Driving License Check can support:

* DVLA entitlement checks.
* Licence validity and format checks.
* Fraud and tampering detection.
* Comparison of official driver records with submitted customer details.
* Return of entitlements, restrictions, endorsements, disqualifications, infractions or penalties where available.

### UK business verification

Use Company Search & Insights to verify UK companies, review ownership and screen connected parties.

UK Business Verification combines business data retrieval with entity review, ownership review and AML screening for the business and related people.

<table><thead><tr><th width="315.7822265625">Business verification task</th><th>What ComplyCube supports</th></tr></thead><tbody><tr><td>Company lookup</td><td>Retrieve company profile data from official business registers, including legal name, registration number, status and registered address.</td></tr><tr><td>Director and officer review</td><td>Access officer and director information where available.</td></tr><tr><td>Ownership review</td><td>Review shareholder and UBO data where available.</td></tr><tr><td>Entity screening</td><td>Screen the company against sanctions, PEP, watchlist and adverse media sources.</td></tr><tr><td>Connected-party screening</td><td>Screen directors, officers, shareholders and beneficial owners.</td></tr><tr><td>Business risk scoring</td><td>Build a business risk score using AML Risk Scoring.</td></tr><tr><td>Continuous monitoring</td><td>Monitor businesses and connected parties for changes in risk.</td></tr></tbody></table>

{% hint style="success" %}
UK business verification uses Companies House data and can be combined with AML Screening Check, AML Risk Scoring, Workflows and Compliance Policies.
{% endhint %}

### UK compliance policies and regulatory alignment

With [Compliance Policies](/documentation/product-guides/compliance-studio/policies), you can define risk-based rules, apply policy assurance across checks, trigger additional verification steps, and preserve audit-ready evidence for each decision.

<table data-header-hidden="false" data-header-sticky data-search="false"><thead><tr><th>Framework or authority</th><th>How ComplyCube supports policy assurance</th></tr></thead><tbody><tr><td>HM Treasury Money Laundering Regulations</td><td>Configure customer due diligence, enhanced due diligence, AML screening and ongoing monitoring policies</td></tr><tr><td>FCA Customer Due Diligence</td><td>Apply identity verification, proof of address, AML screening and risk scoring rules inside structured workflows</td></tr><tr><td>FCA Enhanced Due Diligence</td><td>Trigger additional checks for higher-risk customers, such as enhanced identity verification, AML screening, risk scoring or manual review</td></tr><tr><td>DSIT Digital Identity and Attributes Trust Framework</td><td>Support digital identity journeys with document verification, biometric checks, liveness and evidence capture</td></tr><tr><td>Home Office Right to Work</td><td>Build identity and document verification flows for employment-related checks</td></tr><tr><td>Home Office Right to Rent</td><td>Build identity and document verification flows for tenancy-related checks</td></tr><tr><td>FATF-aligned AML guidance</td><td>Apply risk-based controls for sanctions, PEPs, adverse media, beneficial ownership and ongoing monitoring</td></tr></tbody></table>

{% hint style="success" icon="circle-check" %}
**Policy assurance across checks**

Compliance Policies let you apply your organisation’s verification rules across ComplyCube workflows and verification journeys. This helps standardise decisioning, enforce risk-based controls and retain audit-ready evidence.
{% endhint %}

{% hint style="warning" %}
ComplyCube provides verification, screening, workflow and policy configuration tools. Your organisation remains responsible for configuring policies, thresholds and review procedures according to its regulatory obligations.
{% endhint %}

### FAQs

<details>

<summary>Do you support KYC and AML in the UK?</summary>

Yes. ComplyCube supports UK KYC and AML workflows, including identity verification, document checks, biometrics, proof of address, AML screening, ongoing monitoring and business verification.

</details>

<details>

<summary>Which UK identity documents are supported?</summary>

ComplyCube supports UK passports, driving licences and residence permits. Passport coverage includes national, international, diplomatic, ePassport and passport card variants.

</details>

<details>

<summary>Can I verify a customer in the UK without a document?</summary>

Yes. Multi-Bureau Check and Identity Fraud Check support data-led identity and address verification using UK bureau and reference sources.

</details>

<details>

<summary>Do you support proof of address checks in the UK?</summary>

Yes. Proof of Address Check supports common UK proof of address documents, including bank statements, utility bills, driving licences and tax documents.

</details>

<details>

<summary>Do you support biometric verification in the UK?</summary>

Yes. Identity Check supports selfie verification with face match and passive liveness. Enhanced Identity Check adds video-based liveness challenges.

</details>

<details>

<summary>Do you support UK business verification?</summary>

Yes. Company Search & Insights supports UK business verification using company profile data, director and ownership information, and connected-party screening.

</details>

<details>

<summary>What does UK AML screening cover?</summary>

AML Screening Check supports sanctions screening, PEP screening, watchlist screening, adverse media checks and ongoing monitoring for individuals and businesses.

</details>

<details>

<summary>Do you support ongoing AML monitoring in the UK?</summary>

Yes. AML Screening Check supports continuous monitoring and alerts when customer or business risk changes.

</details>

<details>

<summary>Do you support UK driving licence verification?</summary>

Yes. Driving License Check validates UK driving licence details against DVLA records and can return available licence validity, entitlement, restriction and infraction data.

</details>

<details>

<summary>Can I configure UK-specific compliance rules?</summary>

Yes. You can use Compliance Policies and Workflows to apply risk-based rules for AML, KYC, Right to Work, Right to Rent and enhanced due diligence journeys.

</details>

<details>

<summary>Which UK frameworks can this support?</summary>

ComplyCube can support workflows aligned with UK identity, AML, tenancy, employment and enhanced due diligence requirements.

Relevant UK frameworks and requirements include HM Treasury Money Laundering Regulations, FCA customer due diligence, FCA enhanced due diligence, Home Office Right to Work, Home Office Right to Rent and DSIT digital identity frameworks.

</details>

<details>

<summary>Can I screen individuals and businesses in the UK?</summary>

Yes. AML Screening Check supports screening and ongoing monitoring for both individuals and businesses. Company Search & Insights can also be used to review UK company data, ownership and connected parties.

</details>

### Next steps

Start by [signing up](https://portal.complycube.com/signup) for the **ComplyCube sandbox** to test UK verification checks and build a sample onboarding flow.

If you need help confirming coverage or configuring a production-ready setup, [contact us](http://www.complycube.com/contact) to discuss supported UK data sources, Compliance Policy setup for KYC, AML, KYB, Right to Work or Right to Rent workflows.


# Workflows

Build KYC onboarding flows with integrated AML screening. Orchestrate identity verification, liveness checks, dynamic questionnaires, and more in a single verification journey.

### Workflows Overview

ComplyCube Workflows let you design and run complete, compliant **KYC onboarding workflows with integrated AML screening**.

They act as an end-to-end KYC onboarding workflow builder, orchestrating multiple verification checks within a single flow. This enables businesses to run consistent, audit-ready customer verification journeys across web, mobile, and other channels.

For example, a workflow might include [ID document verification](/documentation/product-guides/identity-verification/document-check), [biometric liveness detection](/documentation/product-guides/biometric-and-liveness-verification/identity-check), and [AML screening](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check). Each time you onboard a customer, a workflow session automatically runs the entire verification journey.

Workflows can also include [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) (dynamic questionnaires) and [Compliance Policies](/documentation/product-guides/compliance-studio/policies) for automated decisioning, allowing you to guide customers through a complete verification journey from start to finish.

{% hint style="info" %}
With ComplyCube, you can verify customers through **Workflows** or **Direct Checks**. We **recommend** Workflows for most use cases, particularly regulated onboarding flows.

[Learn more about Workflows and Direct Checks.](https://docs.complycube.com/documentation/product-guides/compliance-studio/spaces/sw26JqCBnT6AEIbxAYyk/pages/-M7DZURzLR4QSX40QG7b#id-2.-verification-modes)
{% endhint %}

{% hint style="info" %}
If you're on a **legacy plan**, you may need to contact your Account Manager or [support](https://www.complycube.com/sales) to enable Workflows.
{% endhint %}

### Interactive guide

{% @arcade/embed url="<https://app.arcade.software/share/a569Rd2mrj6TumeLFIrq>" flowId="a569Rd2mrj6TumeLFIrq" %}

### Benefits

Workflows make it easier to stay aligned with regulatory requirements. They offer a number of key benefits:

* **Faster setup**: Launch quickly using ready-made templates tailored to your use case.
* **Low and no-code integrations:** Integrate once through the Hosted Solution, SDKs, or API, and keep flows up to date without rework.
* **Flexible journey design**: Add questionnaires ([Smart Forms](/documentation/product-guides/compliance-studio/smart-forms)), dynamic flows, and eSignatures to tailor onboarding journeys to your compliance and business needs.
* **Policy-driven compliance**: [Compliance policies](#compliance-policies) can be attached to workflows so that checks always meet the right regulatory framework (e.g., UK DIATF Right to Work, Singapore MAS, Germany BaFin, FATF) or your own custom requirements.
* **Future-proof**: Add new verification steps or update policies without code changes.
* **Data protection by design**: Collect only the data required for processing, ensuring GDPR and broader data privacy compliance.
* **Oversight and auditability**: Monitor, review, and evidence entire customer journeys from one place.

### Creating workflows

You can create complete workflows in seconds using the ComplyCube Portal. When starting a new workflow, you’ll be prompted to choose from a wide range of templates, each preconfigured with **predefined steps** and **compliance policies** aligned to common use cases and regulatory requirements.

<figure><img src="/files/LTVdSkImJG5xJA4cjwIt" alt="Workflow template selection in the ComplyCube Portal for creating KYC/AML onboarding workflows"><figcaption><p>Workflow Template Selection</p></figcaption></figure>

You can customize a template during setup or **build a workflow from scratch** to suit your specific needs.

### Designing workflows

The **workflow designer** is the tool for building verification journeys in ComplyCube.

You begin by selecting the verification checks required for your use case. From there, ComplyCube’s smart engine automatically assembles the necessary capture steps, ensuring customers are shown only the screens required to complete those checks.

All flows follow a privacy-by-design approach, so customers are only asked for the information required to complete the selected checks, avoiding any unnecessary data capture.

<div data-full-width="false"><figure><img src="/files/YecCzdOi1pCg9S0gg3HZ" alt="Workflow designer used to build KYC onboarding flows and identity verification journeys"><figcaption><p>ComplyCube Workflow Designer</p></figcaption></figure></div>

With the designer, you can:

* **Drag and drop checks** to build a sequence.
* **Configure each verification step** with separate **Capture** and **Processing** settings:
  * **Capture**: Defines the customer-facing experience, including inputs, documents, images, and journey steps.
  * **Processing**: Defines how the check runs, including evaluation rules, processing options, and other backend settings.
* **Preview workflows** before publishing, so you can test the journey end-to-end, validate [policy alignment](#compliance-policies), and ensure the customer experience is as intended.

This lets you focus on designing the right flow, while ComplyCube handles the underlying compliance and data minimization.

### Workflow versions

When you create a workflow, its first version is generated automatically. Each time you update the workflow, a new version is created to preserve a full audit trail. Existing versions cannot be edited.

Version history lets you track every change over time and decide which version should be active.

<figure><img src="/files/372QkgZmbAAfYIvo9L9F" alt="Workflow versions in the ComplyCube workflow builder showing version history for auditability"><figcaption><p>Workflow Versions</p></figcaption></figure>

New versions are created in an **inactive state**, giving you control over when to **activate** them. This allows you to safely test or review changes before they go live.

At any point, only one version of a workflow can be active.

### Workflow statuses

Workflow statuses are manual settings on each workflow version. They don’t follow an automatic lifecycle. You can switch a version between **Active** and **Inactive** at any time.

<table><thead><tr><th width="107.12890625">Status</th><th>Description</th></tr></thead><tbody><tr><td><strong>Draft</strong></td><td>The workflow is being created or modified and has not yet been published.</td></tr><tr><td><strong>Inactive</strong></td><td>A published workflow that has been disabled or superseded by a newer version.</td></tr><tr><td><strong>Active</strong></td><td>The current published version of the workflow that is available for use.</td></tr></tbody></table>

### Workflow session

A workflow session is created each time a customer enters a workflow journey. Sessions capture the customer’s progress, results, and audit trail.

<figure><img src="/files/Hn535y0aQZfKdIn91tw1" alt="Workflow session results in the ComplyCube Portal showing KYC/AML verification outcomes"><figcaption><p>Workflow Session Results</p></figcaption></figure>

You can start sessions in several ways, depending on your integration approach:

* **Web Portal** (*by sending a verification link to your customer*)
* **Hosted Solution**
* **Mobile SDK**
* **Web SDK**
* **API**

{% hint style="info" %}
[Learn about the Workflow Sessions API.](/documentation/api-reference/core-resources/workflow-sessions)
{% endhint %}

### Session tracking

Workflow sessions can be monitored in real time through the ComplyCube Portal. The Portal provides full visibility into each customer’s verification journey, making it easy to track progress, identify issues, and manage outcomes.

When tracking sessions, you can:

* **View session details**: Inspect customer progress, including completed stages, uploaded documents, and captured biometrics.
* **Monitor session status**: See whether a session is [started](#session-lifecycle), [processing](#session-lifecycle), [complete](#session-lifecycle), [abandoned](#session-lifecycle), or [cancelled](#session-lifecycle).
* **Track in-progress verifications**: Follow checks as they move from submission to completion, with status updates reflected instantly.
* **Identify drop-offs**: Spot abandoned sessions to understand where customers are leaving the journey and improve the user experience.
* **Audit trails**: Access timestamps and metadata for compliance and internal review.

<figure><img src="/files/WeKaB1aVhYDc2MKOnMiP" alt="Workflow session activity timeline used for tracking customer onboarding and verification status"><figcaption><p>Workflow Session - Activities</p></figcaption></figure>

### Session lifecycle

A workflow session represents the customer’s progress through a verification journey. Each session moves through a defined lifecycle, with its status reflecting the customer’s activity and the processing state.

<table><thead><tr><th width="154.09375">Lifecycle State</th><th>Description</th></tr></thead><tbody><tr><td><strong>Started</strong></td><td>The session has been initiated by the customer, and the verification flow is available to navigate. At this stage, no checks have started. If the customer exits the flow, refreshes the browser, or closes the app, they can later resume the session from where they left off.</td></tr><tr><td><strong>Processing</strong></td><td>The customer has finished the verification flow, and the captured data has been submitted. One or more verification checks are actively being processed. The session will remain in this state until all checks are complete.</td></tr><tr><td><strong>Complete</strong></td><td>All verification checks have finished, and the session is fully complete. Results are now available via the Portal, API and webhooks, and no further customer actions can be performed on the session.</td></tr><tr><td><strong>Abandoned</strong></td><td>The session was started but left incomplete for an extended period of time. Once abandoned, the session cannot be resumed and must be restarted if the client wishes to continue. Abandoned sessions are useful for tracking drop-offs and optimizing customer journeys.</td></tr><tr><td><strong>Cancelled</strong></td><td>The session was explicitly cancelled before completion, typically by an administrative action by you or a team member. A cancelled session cannot be resumed, and no further checks will be run.</td></tr></tbody></table>

### Session results

Once a workflow session is completed, ComplyCube processes all of the verification checks and makes the **results available in real time**. These results include detailed outcomes for each check, overall workflow status, and a full audit trail.

{% hint style="info" %}
You can apply conditional rules and post-processing rules to tailor session outcomes. Contact your **Account Manager** to enable or configure them.
{% endhint %}

<figure><img src="/files/NCVOeTb7qyPKNKTHLA9U" alt="Workflow session verification result breakdown for identity verification and AML screening checks"><figcaption><p>Workflow Session - Verification Result Breakdown</p></figcaption></figure>

The overall outcome of a workflow session is derived from its verification checks and policies. Outcomes update in real time as checks are processed or reviewed by your team.

<table><thead><tr><th width="300.41796875">Condition</th><th width="163.92578125">Session Outcome</th><th>Notes</th></tr></thead><tbody><tr><td>All checks and policies return <strong>Clear</strong></td><td>Clear</td><td>No issues detected.</td></tr><tr><td>Any check or policy returns <strong>Attention</strong></td><td>Attention</td><td>Requires manual review.</td></tr><tr><td>Any check is returned as <strong>Not processed</strong></td><td>Attention</td><td>Treated as Attention until resolved.</td></tr><tr><td>A check is <strong>Rejected</strong> (reviewer decision)</td><td>Rejected</td><td>Outcome of the session is set to Rejected.</td></tr><tr><td>Screening check <strong>confirmed</strong> as a <strong>sanction</strong> or <strong>watchlist match</strong></td><td>Rejected</td><td>Outcome is Rejected once a match to a sanctioned entity or watchlist entry is reviewed and confirmed.</td></tr><tr><td>Screening check matches other types (e.g. PEP, adverse media)</td><td>Attention</td><td>Even when the match is reviewed and confirmed, the outcome remains Attention. The session outcome will only change if a team member explicitly overrides it.</td></tr><tr><td>Session outcome manually overridden by a team member</td><td><p>Clear</p><p>Attention</p><p>Rejected</p></td><td>Manual overrides always take precedence over automated outcomes and should be applied once all checks and policies have been reviewed.</td></tr></tbody></table>

You can access results in several ways:

* **Web Portal**: View customer progress, verification outcomes, and supporting evidence directly in the Portal.
* **Webhooks**: Receive results automatically as soon as a session is completed, enabling real-time decisioning in your systems.
* **API**: Retrieve results programmatically for deeper integrations, reporting, or custom workflows.

Results are stored securely and can be **exported as reports** to support audits and regulatory reporting.

### Compliance policies

Compliance [policies](/documentation/product-guides/compliance-studio/policies) are a core part of ComplyCube Workflows. They define the regulatory and business rules that must be applied to every verification journey, ensuring that each workflow session is compliant by design.

A workflow template will show any **compliance policies** assigned to it, and the corresponding evaluation results will appear in each workflow session. Not all templates will have policies attached.

<figure><img src="/files/clsNyJ8QOttDkiWxsWPS" alt="Compliance policies attached to a workflow template for KYC/AML rule-based decisioning"><figcaption><p>Workflow - Compliance Policies</p></figcaption></figure>

By incorporating a policy into a workflow template, you remove the need to configure checks per jurisdiction.

A policy can reflect:

* **National standards** such as UK DIATF Right to Work, Singapore MAS, or Germany BaFin.
* **International frameworks** such as FATF guidance.
* **Custom business rules and corporate policies**, allowing you to adapt workflows to your own risk and compliance requirements.

When a customer completes a verification flow that includes compliance policies, ComplyCube automatically evaluates each policy against the verification data. The results are then presented in the **Policy Assurance** section of the workflow session.

<figure><img src="/files/ubC6ubkGzUB74w7d2jp4" alt="Policy assurance results in a workflow session showing compliance policy evaluation outcomes"><figcaption><p>Workflow Session - Policy Assurance</p></figcaption></figure>

{% hint style="info" %}
[Learn about ComplyCube Policies](/documentation/product-guides/compliance-studio/policies).
{% endhint %}

### Dynamic workflows

Advanced dynamic workflows let you build adaptive **KYC onboarding** and **identity verification** journeys. Combine [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms), check configuration, and **verification processing rules** to tailor each workflow session to the customer.

This helps you collect only the right data, run the right checks, and support more complex compliance requirements without rebuilding the full workflow.

Common use cases include:

* **Rule-based customer routing**: Place customers into different verification journeys based on your own business or compliance rules.
* **Conditional data capture**: Show additional questions, declarations, or supporting document requests only when the selected journey requires them.
* **Enhanced due diligence flows**: Route higher-risk customers into more advanced onboarding and jurisdiction-specific verification paths.

{% hint style="info" %}
Contact your **Account Manager** to enable or configure advanced dynamic workflow rules.
{% endhint %}

### Monitoring performance

Workflows should evolve as regulations, fraud patterns, and customer expectations change.

ComplyCube provides **built-in analytics** to help you monitor performance and identify areas for improvement.

<figure><img src="/files/19rnQny7ymHsbiFrz4SF" alt="Workflow analytics dashboard showing completion rate, abandonment rate, and average verification time"><figcaption><p>Workflow Stats and Performance</p></figcaption></figure>

By analyzing metrics such as completion rates, abandonment rates, failure rates, and average verification time, you can understand how customers move through your verification journeys.

These insights allow you to:

* Refine workflows to reduce friction.
* Optimize check configurations to better match your target demographics.
* Add or remove checks as risks evolve.
* Improve decisioning speed.
* Enhance customer experience.

### **Best practices**

Designing workflows is about building journeys that are compliant, efficient, and easy to maintain. The following best practices will help you get the most out of ComplyCube Workflows:

* **Start with a template**: Use pre-defined templates as your foundation, where possible. They reflect industry standards and compliance policies, saving you time and reducing the risk of missing key requirements.
* **Keep flows simple**: Avoid unnecessary steps. Only include the checks relevant to your use case, which helps reduce friction for customers and speeds up completion.
* **Test before publishing**: Preview and test workflows end-to-end to confirm the customer experience, policy alignment, and data capture settings are correct.
* **Manage versions carefully**: Review each new version before activating it. This maintains a clear audit trail and ensures changes don’t disrupt ongoing onboarding journeys.
* **Automate with webhooks**: Use webhooks to trigger downstream actions, such as account creation, case management, or alerts, as soon as verification results are available.

### Frequently asked questions

<details>

<summary>When should I use Workflows instead of Direct Checks?</summary>

Use Workflows when you need a complete onboarding journey rather than a single standalone verification.

They are usually the better fit for regulated onboarding, multi-step KYC flows, and cases where you need policy-driven decisioning.

Use Direct Checks when you only need to run one check without the wider workflow layer.

</details>

<details>

<summary>What verification checks can I include in a workflow?</summary>

You can include any ComplyCube verification checks in a workflow.

Common examples include [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms), and [Compliance Policies](/documentation/product-guides/compliance-studio/policies).

</details>

<details>

<summary>Can I customize a workflow for different countries or risk levels?</summary>

Yes.

You can create multiple workflows to fit different use cases, countries, or risk levels.

For more complex requirements, you can use **dynamic workflows**, conditional rules, and policy logic to route customers into different verification paths based on jurisdiction, risk profile, or use case.

</details>

<details>

<summary>How do workflow sessions work?</summary>

A workflow session is created each time a customer starts a workflow journey.

It tracks customer progress, captured data, verification results, and the audit trail for that journey.

</details>

<details>

<summary>Can customers resume an incomplete workflow?</summary>

Yes, while the session is still active.

A customer can resume a **started** session from where they left off.

Once a session becomes **abandoned** or **cancelled**, it cannot be resumed and must be restarted.

</details>

<details>

<summary>How are workflow results and decisions returned?</summary>

Workflow results are available in the **Portal**, through the **API**, and through **webhooks**.

This supports both manual review and real-time downstream decisioning.

</details>

<details>

<summary>Can I add compliance policies and questionnaires to a workflow?</summary>

Yes.

You can add [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to collect extra customer data and declarations, and [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply rule-based evaluation inside the same journey.

</details>

### Related topics

* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) for KYC data capture and declarations.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) for policy evaluation and rule-based decisioning.


# Smart Forms

Dynamic questionnaires for KYC onboarding. Capture customer data, compliance declarations, and supporting documents inside verification workflows.

### Smart Forms Overview

Smart Forms (dynamic questionnaires) let you extend verification [Workflows](/documentation/product-guides/compliance-studio/workflows) with fully customizable data capture steps. Use them to collect extra KYC onboarding data, declarations, and supporting documents in the same journey.

Each Smart Form is built from configurable components and input fields. You can tailor screens to your compliance process and adapt the journey using conditional logic.

{% hint style="info" %}
Please get in touch with your **Account Manager** to enable this feature.
{% endhint %}

### Common use cases

Typical use cases for Smart Forms include:

* **KYC and CDD declarations**: Collect customer attestations and regulatory declarations during onboarding, verification, or periodic review flows.
* **Enhanced due diligence questionnaires**: Trigger additional questions for higher-risk customers to support EDD requirements.
* **Source of funds and source of wealth checks**: Gather structured information about how customers obtained their funds or assets.
* **Regulatory disclosures, consent capture, and eSignatures**: Capture legally required disclosures, customer acknowledgements, consent confirmations, and electronic signatures for contractual or regulatory workflows.
* **Suitability assessments**: Capture information required to determine product suitability, such as investment appropriateness.
* **Employment and residency verification**: Collect declarations and evidence for employment status or residency requirements (e.g. Right to Work or Right to Rent).

### How smart form works

Smart Forms run as steps inside a workflow session. They capture structured customer data during the verification journey. Each form can be dynamically shown based on your conditional logic.

All responses are securely stored and linked to the workflow session. You can access results in real time via the Portal, API, or webhooks.

<div><figure><img src="/files/Q7ncPfNCArqHzlGwaE8s" alt="Smart Forms step in a ComplyCube workflow for KYC data capture" width="563"><figcaption></figcaption></figure> <figure><img src="/files/fBT53zdj82xIl5uMIstZ" alt="Smart Forms preview showing a dynamic questionnaire in a customer verification journey" width="563"><figcaption><p>Smart Forms - Preview</p></figcaption></figure> <figure><img src="/files/uHWIyFW1G4HmMy3k03hv" alt="Smart Forms screen used to collect compliance declarations and supporting documents" width="563"><figcaption></figcaption></figure></div>

### Designing smart forms

You can design Smart Forms directly in the [workflow designer](/documentation/product-guides/compliance-studio/workflows#designing-workflows). Each form can be tailored to match your compliance requirements or business process and can include a wide range of input types:<br>

* **Structured data fields** such as employment details or financial information.
* **Conditional logic** that adapts the flow based on previous answers.
* **Customer declarations**, **consent confirmations**, and **electronic signatures** required for regulatory or contractual compliance.
* **Segmented sections** to logically group questions and guide customers through forms step by step.
* **File uploads**, for example income statements, payslips, or supporting identity documents.
* **Dropdowns**, **date pickers**, and **free-text inputs** to capture responses in the appropriate format.
* **Full localization support**, including customizable labels, placeholders, and tooltips to ensure clarity across languages, contexts, and audiences.

<figure><img src="/files/7JYt9MnU6lo76j6pzApf" alt="Smart Forms designer in the ComplyCube workflow builder for creating dynamic questionnaires"><figcaption><p>Smart Forms - Designer</p></figcaption></figure>

### Frequently asked questions

<details>

<summary>What is a Smart Form in a KYC workflow?</summary>

Smart Forms are dynamic questionnaires used inside a verification workflow.

They help you collect extra customer data, declarations, and supporting evidence as part of the same KYC journey.

</details>

<details>

<summary>Can Smart Forms show different questions based on earlier answers?</summary>

Yes.

Smart Forms support **conditional logic**, so questions and sections can change based on previous answers, selected journeys, or other workflow conditions.

</details>

<details>

<summary>Can Smart Forms collect supporting documents and declarations?</summary>

Yes.

You can use Smart Forms to capture declarations, acknowledgements, signatures, and supporting files such as payslips, bank statements, or contracts.

</details>

<details>

<summary>Where can I access Smart Form responses?</summary>

Responses are linked to the workflow session and stored securely.

You can review them in the **Portal**, retrieve them through the **API**, or receive them through **webhooks** for downstream processing.

</details>

<details>

<summary>Can Smart Forms be used for enhanced due diligence and ongoing KYC reviews?</summary>

Yes.

Smart Forms are well suited for **enhanced due diligence (EDD)** questionnaires, **source of funds** checks, **source of wealth** questions, and **customer due diligence refresh** flows.

</details>

<details>

<summary>Do Smart Forms work with workflows and compliance policies?</summary>

Yes.

Smart Forms run inside [Workflows](/documentation/product-guides/compliance-studio/workflows) and can support rule-based decisions alongside [Compliance Policies](/documentation/product-guides/compliance-studio/policies).

</details>

### Related topics

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to build end-to-end KYC/AML verification journeys.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to evaluate regulatory and business rules during workflows.


# eSignatures

Electronic signatures for KYC, AML, and customer onboarding workflows. Create document templates, capture legally binding signatures, and support eIDAS signature levels including SES, AdES, and QES.

### eSignatures Overview

ComplyCube eSignatures enables businesses to collect legally binding electronic signatures as part of **KYC**, **AML**, and customer onboarding workflows.

Create signature document templates from uploaded **PDFs** or generate them dynamically through Smart Forms. These templates can later be used to generate signature envelopes for a live signing journey.

This lets you combine identity verification, compliance declarations, agreement capture, and electronic signing within a single verification journey.

ComplyCube supports **Simple Electronic Signatures (SES)**, **Advanced Electronic Signatures (AdES)**, and **Qualified Electronic Signatures (QES)**, allowing you to select the appropriate level of assurance and legal weight for each use case.

Under the **EU eIDAS Regulation**, SES, AdES, and QES are all legally recognized electronic signatures, offering increasing levels of identity assurance, security, and evidential value.

Integrated with [Workflows](/documentation/product-guides/compliance-studio/workflows) and [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms), eSignatures supports end-to-end onboarding, compliance, and agreement execution processes.

{% hint style="info" %}
Please get in touch with your **Account Manager** to enable this feature.
{% endhint %}

### Common use cases

Use eSignatures to capture legally relevant agreements, declarations, and approvals as part of onboarding and compliance journeys:

* **Customer onboarding agreements**: Send terms, mandates, account opening forms, and customer agreements for signature.
* **KYC and AML declarations**: Capture attestations, source of funds statements, risk disclosures, and regulatory acknowledgements.
* **Identity verification workflows**: Combine verification, declarations, and electronic signing within a single customer journey.
* **Dynamic signing flows**: Generate agreements and signature steps from Smart Form responses and business rules.

### How eSignatures work

eSignatures follows a workflow-based template flow. You define the document template inside the workflow first, then the live envelope is created when a workflow session starts and the customer reaches the signing step.

The process works as follows:

1. Choose the **signature level** (**SES**, **AdES**, or **QES**).
2. Create a document template from a **PDF** or dynamically using a [Smart Form](/documentation/product-guides/compliance-studio/smart-forms).
3. Configure the Smart Form and any additional verification or compliance steps within the workflow.
4. When a workflow session is created and the customer reaches the signing step, ComplyCube generates a live signature request from the document template.
5. Present documents, clauses, and signature steps to the customer.
6. Capture the signature and supporting evidence.
7. Store signed documents and audit records as part of the verification journey.

{% hint style="info" %}
For the lifecycle after creation, see [envelope statuses](#envelope-statuses).
{% endhint %}

***

<figure><img src="/files/cmZSiQW7DDe26Q7D9Jz4" alt="eSignatures document template builder"><figcaption><p>eSignatures - Signing Configuration</p></figcaption></figure>

***

<figure><img src="/files/nKEnBOKtZHhL3wJ2Ay6H" alt="eSignatures signing configuration"><figcaption><p>eSignatures - Document Template Builder</p></figcaption></figure>

### Signature levels

ComplyCube supports multiple signature levels to accommodate different legal, regulatory, and evidential requirements.

<table><thead><tr><th width="130.953125">Signature level</th><th>What it is</th><th>Typical use cases</th></tr></thead><tbody><tr><td><strong>SES</strong></td><td>A simple electronic signature suitable for most business and onboarding scenarios.</td><td>Customer onboarding, agreements, declarations, acknowledgements, and consent capture.</td></tr><tr><td><strong>AdES</strong><br>(or AES)</td><td>An electronic signature with additional evidential measures and signer linkage.</td><td>Compliance documentation, regulated onboarding, and higher-assurance signing flows.</td></tr><tr><td><strong>QES</strong></td><td>A qualified electronic signature designed for use cases requiring qualified signing frameworks.</td><td>Jurisdictions or processes that mandate qualified signatures or maximum legal assurance.</td></tr></tbody></table>

### Envelope statuses

An envelope moves through a defined lifecycle from creation to completion or closure.

<table><thead><tr><th width="131.2421875">Status</th><th>Description</th></tr></thead><tbody><tr><td><strong>Created</strong></td><td>The envelope has been generated, but signing has not started yet.</td></tr><tr><td><strong>In progress</strong></td><td>The envelope is active and the customer is reviewing or signing it.</td></tr><tr><td><strong>Completed</strong></td><td>The signing process finished successfully.</td></tr><tr><td><strong>Failed</strong></td><td>The signing flow did not complete because of a system or delivery failure.</td></tr><tr><td><strong>Declined</strong></td><td>The signer actively refused to sign the envelope.</td></tr><tr><td><strong>Expired</strong></td><td>The envelope was not completed before its validity window ended.</td></tr></tbody></table>

### Audit trail and evidence

When signing is completed, ComplyCube links the signed document and supporting signature evidence to both the **client** and **workflow session** records.

This gives teams a clear audit trail for:

* Compliance reviews and regulatory audits.
* Customer investigations and dispute handling.
* Internal approvals and record-keeping.

<figure><img src="/files/AAQzJL1lD1StiWVBkdN1" alt=""><figcaption><p>eSignatures - Workflow Session View</p></figcaption></figure>

### Frequently asked questions

<details>

<summary>What is an eSignature envelope?</summary>

An envelope is the live document package sent for signature.

It is generated from a document template and used within the signing journey.

</details>

<details>

<summary>Can I create document templates from PDFs and Smart Forms?</summary>

Yes.

eSignatures supports **PDF-based** templates and **Smart Form-based** templates.

This gives you a fixed-document option and a dynamic questionnaire-driven option before generating envelopes later in the flow.

</details>

<details>

<summary>What is the difference between a document template and an envelope?</summary>

A document template defines the document, fields, clauses, and signing structure in advance.

An envelope is the live signature package generated from that template for a specific signing journey.

</details>

<details>

<summary>What is the most common type of electronic signature?</summary>

For most customer onboarding and agreement flows, **SES** is the most commonly used option.

It is typically the right fit for general agreements, acknowledgements, declarations, and other common use cases.

</details>

<details>

<summary>How do eSignatures fit into KYC and AML onboarding?</summary>

Yes.

eSignatures can sit alongside identity verification, AML screening, declarations, and policy evaluation in the same [workflow](/documentation/product-guides/compliance-studio/workflows).

This helps you move from verification to agreement capture and approval in one journey.

</details>

<details>

<summary>Can the documents or clauses change based on customer answers?</summary>

Yes.

[Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) supports **conditional logic**, so documents, clauses, and signature steps can change based on previous answers or workflow conditions.

</details>

<details>

<summary>What evidence is stored after signing?</summary>

ComplyCube stores the signed output and links signature evidence to the verification journey.

This supports audit, review, and downstream compliance processes.

</details>

### Related topics

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate eSignatures with verification and compliance steps.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to generate dynamic signing journeys and agreement content.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply rule-based evaluation around signed journeys.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) and [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) to combine verification and signing in one customer journey.


# Compliance Policies

Automate KYC/AML compliance with regulatory and custom policies inside workflows. Get real-time policy evaluation, rule-based decisions, and audit-ready evidence.

### Compliance Policies Overview

Policies let you apply **regulatory rules**, **industry frameworks**, and **internal controls** inside a [workflow](/documentation/product-guides/compliance-studio/workflows). Each policy is a **rule set** evaluated during the verification journey.

This helps you enforce consistent **KYC/AML decisioning** across every workflow session.

{% hint style="info" %}
Compliance Policies are designed for businesses operating in **regulated industries**. They provide **audit-ready evidence** that your workflows align with applicable **compliance requirements**.
{% endhint %}

#### Supported regulatory and industry frameworks

ComplyCube supports **an extensive set of policies** across **global frameworks**, **jurisdiction-specific regulations**, and **industry requirements**.

Coverage includes major **KYC**, **AML**, **CDD**, **EDD**, and **sanctions compliance** obligations across leading frameworks and regulators.

Common examples include:

* **Financial Action Task Force (FATF)** recommendations for global **AML**, **CTF**, **beneficial ownership**, and risk-based due diligence standards.
* **U.S. Financial Crimes Enforcement Network (FinCEN)** rules for **Customer Identification Program (CIP)**, **Customer Due Diligence (CDD)**, and beneficial ownership requirements.
* **UK Home Office** requirements for tenancy and employment verification journeys.
* **Monetary Authority of Singapore (MAS) Notice 626** for **AML/CFT** controls and customer due diligence requirements in Singapore.
* **Australian Transaction Reports and Analysis Centre (AUSTRAC)** **AML/CTF** obligations for reporting entities in Australia.

For the full framework and jurisdiction breakdown, see [Regulatory coverage](/documentation/product-guides/compliance-studio/policies/regulatory-coverage).

#### Custom policies and policy assurance

You can also create **custom policies** to reflect your own compliance framework, internal rules, and risk controls. This gives you **policy assurance** across each verification journey.

Every session is evaluated against defined requirements, which strengthens your audit trail and supporting evidence for regulators, auditors, and internal review teams.

Results are available in the **Portal**, through the **API**, and through **webhooks** for real-time decisioning.

{% hint style="info" %}
Contact your **Account Manager** to confirm support for specific policies in your jurisdiction, or to request implementation of bespoke internal policies.
{% endhint %}

### Policy evaluation in workflows

Policies are attached to [workflow templates](/documentation/product-guides/compliance-studio/workflows#creating-workflows). Not all templates will include them.

When a customer completes a workflow session, captured data and checks undergo **policy evaluation**. Evaluation runs against the policies assigned to the template. Results are generated in real time. They show whether the session meets requirements or requires further review.

In the Portal, outcomes appear under **Policy Assurance**. This is your compliance policy engine’s evidence for each decision.

This delivers consistent, repeatable policy enforcement across verification journeys. It reduces manual interpretation by compliance teams. It also improves auditability for KYC and AML programs.

<figure><img src="/files/clsNyJ8QOttDkiWxsWPS" alt="ComplyCube workflow template showing assigned compliance policies for KYC/AML decision rules"><figcaption><p>Workflow Template with Compliance Policies</p></figcaption></figure>

***

<figure><img src="/files/ubC6ubkGzUB74w7d2jp4" alt="Workflow session policy assurance results showing real-time policy evaluation outcomes"><figcaption><p>Workflow Session with Policy Evaluation Results</p></figcaption></figure>

### KYC and AML policy use cases

Use policies when you need consistent, auditable decisions across onboarding and compliance journeys:

* **KYC onboarding**: Apply jurisdiction-specific identity, verification, and eligibility rules without rebuilding each workflow.
* **AML compliance**: Enforce policy decisions against frameworks such as **FATF**, **FinCEN**, and local **AML/CFT** regulations.
* **CDD and EDD**: Escalate higher-risk customers into stricter **Customer Due Diligence** and **Enhanced Due Diligence** requirements.
* **Beneficial ownership and business checks**: Support rule-based reviews for **UBO**, business verification, and higher-risk entity structures.
* **Industry and regulatory controls**: Enforce framework-specific requirements such as **MiFID II**, **Right to Rent**, and other regulated onboarding obligations.

### Frequently asked questions

<details>

<summary>How are compliance policies applied in a workflow?</summary>

Compliance policies are attached to a [workflow template](/documentation/product-guides/compliance-studio/workflows).

When a customer completes a workflow session, ComplyCube evaluates the captured data and check results against those assigned policies in real time.

</details>

<details>

<summary>What does a policy evaluation result mean?</summary>

A policy evaluation result shows whether the workflow session meets the defined compliance requirements or needs further review.

These outcomes appear under **Policy Assurance** and give teams clear, auditable evidence for each decision.

</details>

<details>

<summary>Can I use my own internal compliance rules?</summary>

Yes.

You can implement **custom policies** alongside supported regulatory and industry policies to reflect your internal compliance framework, risk rules, and review requirements.

</details>

<details>

<summary>Do compliance policies replace AML screening or identity checks?</summary>

No.

Compliance policies evaluate the outputs of a verification journey. They do not replace the underlying checks used to collect evidence.

You typically use them with services like [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), [Document Check](/documentation/product-guides/identity-verification/document-check), and [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms).

</details>

<details>

<summary>Can compliance policies support jurisdiction-specific KYC and AML requirements?</summary>

Yes.

Policies can be aligned to local regulations and industry frameworks, which helps you apply jurisdiction-specific KYC and AML rules without rebuilding each workflow from scratch.

</details>

<details>

<summary>Where can compliance teams review policy decisions?</summary>

Teams can review policy outcomes in the **Portal**, retrieve them through the **API**, or receive them through **webhooks** for downstream decisioning and audit workflows.

</details>

### Related topics

* [Regulatory coverage](/documentation/product-guides/compliance-studio/policies/regulatory-coverage) to explore supported frameworks and jurisdictions.
* [AML Risk Scoring](/documentation/product-guides/due-diligence-tools/risk-profile) for AML risk profiling and customer risk assessment.
* [Workflows](/documentation/product-guides/compliance-studio/workflows) to attach policies to workflow templates.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to capture declarations and supporting documents.


# Regulatory coverage

Explore ComplyCube’s compliance policy coverage across global frameworks, national regulations, and industry requirements, with support for policies across KYC, IDV, AML, CDD, and EDD.

ComplyCube supports **compliance policies** aligned with **global frameworks**, **jurisdiction-specific regulations**, and **industry requirements**

Policies can be applied within **onboarding workflows** to automate **KYC**, **AML**, **CDD**, **EDD**, **sanctions compliance**, and **identity verification** requirements, helping organizations enforce consistent compliance controls and generate **audit-ready decision evidence**.

{% hint style="info" %}
Contact your **Account Manager** if any listed policy is not available on your account, or to request a bespoke internal policy.
{% endhint %}

## Global frameworks

ComplyCube supports compliance policies aligned with internationally recognized AML, KYC, CDD, sanctions, and financial crime prevention standards.

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Framework</th><th>Description</th></tr></thead><tbody><tr><td>Financial Action Task Force (FATF) Recommendations</td><td>International standards for anti-money laundering (AML), counter-terrorist financing (CTF), and financial crime prevention.</td></tr><tr><td>FATF Customer Due Diligence (CDD) Requirements</td><td>Customer identification, verification, and risk assessment requirements.</td></tr><tr><td>FATF Enhanced Due Diligence (EDD) Requirements</td><td>Enhanced controls for higher-risk customers, jurisdictions, and business relationships.</td></tr><tr><td>FATF Beneficial Ownership Requirements</td><td>Requirements for identifying and verifying ultimate beneficial owners (UBOs).</td></tr><tr><td>FATF High-Risk Jurisdiction Controls</td><td>Enhanced onboarding requirements for customers linked to high-risk or monitored jurisdictions.</td></tr><tr><td>United Nations Sanctions Frameworks</td><td>Global sanctions obligations relating to designated individuals, entities, and jurisdictions.</td></tr><tr><td>CRS (Common Reporting Standard)</td><td>International standard for collecting tax residency information, tax identification numbers (TINs), and customer self-certifications to support tax reporting obligations.</td></tr></tbody></table>

## Jurisdictional frameworks

ComplyCube supports compliance policies aligned with **regulations**, **supervisory authorities**, **government frameworks**, and **industry requirements** across major global jurisdictions.

{% hint style="info" %}
This is **not an exhaustive list** of supported compliance policies.
{% endhint %}

### Europe

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Regulation / Framework</th><th>Jurisdiction</th><th>Authority</th></tr></thead><tbody><tr><td>Anti-Money Laundering Directive 6 (AMLD6)</td><td>🇪🇺 European Union</td><td>EU</td></tr><tr><td>Anti-Money Laundering Directive 5 (AMLD5)</td><td>🇪🇺 European Union</td><td>EU</td></tr><tr><td>Anti-Money Laundering Regulation (AMLR)</td><td>🇪🇺 European Union</td><td>EU</td></tr><tr><td>Markets in Financial Instruments Directive II (MiFID II)</td><td>🇪🇺 European Union</td><td>ESMA</td></tr><tr><td>Electronic Identification, Authentication and Trust Services (eIDAS)</td><td>🇪🇺 European Union</td><td>EU</td></tr><tr><td>Digital Identity and Attributes Trust Framework (DIATF)</td><td>🇬🇧 United Kingdom</td><td>DSIT</td></tr><tr><td>Right to Work (RTW)</td><td>🇬🇧 United Kingdom</td><td>Home Office</td></tr><tr><td>Right to Rent (RTR)</td><td>🇬🇧 United Kingdom</td><td>Home Office</td></tr><tr><td>Money Laundering Regulations (MLR)</td><td>🇬🇧 United Kingdom</td><td>HM Treasury</td></tr><tr><td>Customer Due Diligence Requirements</td><td>🇬🇧 United Kingdom</td><td>Financial Conduct Authority (FCA)</td></tr><tr><td>Enhanced Due Diligence Requirements</td><td>🇬🇧 United Kingdom</td><td>Financial Conduct Authority (FCA)</td></tr><tr><td>Prepaid SIM Registration Law</td><td>🇧🇪 Belgium</td><td>Belgian Institute for Postal Services and Telecommunications (BIPT / IBPT)</td></tr><tr><td>Anti-Money Laundering Act (AMLA)</td><td>🇨🇭 Switzerland</td><td>Swiss Financial Market Supervisory Authority (FINMA)</td></tr><tr><td>Mandatory Prepaid SIM Registration Requirements</td><td>🇨🇭 Switzerland</td><td>Federal Office of Communications (OFCOM)</td></tr><tr><td>German Anti-Money Laundering Act (GwG)</td><td>🇩🇪 Germany</td><td>Federal Financial Supervisory Authority (BaFin)</td></tr><tr><td>Telecommunications Act (TKG) Subscriber Verification Requirements</td><td>🇩🇪 Germany</td><td>Federal Network Agency (BNetzA)</td></tr><tr><td>AML Requirements</td><td>🇫🇷 France</td><td>Autorité de Contrôle Prudentiel et de Résolution (ACPR)</td></tr><tr><td>Telecom Subscriber Identification Requirements</td><td>🇫🇷 France</td><td>ARCEP</td></tr><tr><td>Criminal Justice AML Acts</td><td>🇮🇪 Ireland</td><td>Central Bank of Ireland</td></tr><tr><td>AML Requirements</td><td>🇮🇹 Italy</td><td>Bank of Italy</td></tr><tr><td>SIM Registration &#x26; Subscriber Identification Requirements</td><td>🇮🇹 Italy</td><td>AGCOM</td></tr><tr><td>AML/CFT Requirements</td><td>🇱🇺 Luxembourg</td><td>CSSF</td></tr><tr><td>Dutch Anti-Money Laundering and Anti-Terrorist Financing Act (Wwft)</td><td>🇳🇱 Netherlands</td><td>Dutch Central Bank (DNB)</td></tr><tr><td>Subscriber Identification Requirements</td><td>🇳🇴 Norway</td><td>Norwegian Communications Authority (Nkom)</td></tr><tr><td>AML Requirements</td><td>🇪🇸 Spain</td><td>SEPBLAC</td></tr><tr><td>Subscriber Registration Requirements</td><td>🇪🇸 Spain</td><td>National Commission on Markets and Competition (CNMC)</td></tr><tr><td>Prepaid SIM Registration Requirements</td><td>🇸🇪 Sweden</td><td>Swedish Post and Telecom Authority (PTS)</td></tr></tbody></table>

### North America

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Regulation / Framework</th><th>Jurisdiction</th><th>Authority</th></tr></thead><tbody><tr><td>Proceeds of Crime (Money Laundering) and Terrorist Financing Act (PCMLTFA)</td><td>🇨🇦 Canada</td><td>FINTRAC</td></tr><tr><td>Know Your Client Requirements</td><td>🇨🇦 Canada</td><td>FINTRAC</td></tr><tr><td>Customer Due Diligence Rule (CDD Rule)</td><td>🇺🇸 United States</td><td>FinCEN</td></tr><tr><td>Beneficial Ownership Rule</td><td>🇺🇸 United States</td><td>FinCEN</td></tr><tr><td>Customer Identification Program (CIP) Requirements</td><td>🇺🇸 United States</td><td>FinCEN</td></tr><tr><td>OFAC Sanctions Requirements</td><td>🇺🇸 United States</td><td>OFAC</td></tr><tr><td>Foreign Account Tax Compliance Act (FATCA)</td><td>🇺🇸 United States</td><td>IRS</td></tr></tbody></table>

### Asia-Pacific

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Regulation / Framework</th><th>Jurisdiction</th><th>Authority</th></tr></thead><tbody><tr><td>AML/CTF Act</td><td>🇦🇺 Australia</td><td>Australian Transaction Reports and Analysis Centre (AUSTRAC)</td></tr><tr><td>Customer Identification Procedures</td><td>🇦🇺 Australia</td><td>Australian Transaction Reports and Analysis Centre (AUSTRAC)</td></tr><tr><td>Biometric SIM Registration Regulations</td><td>🇧🇩 Bangladesh</td><td>Bangladesh Telecommunication Regulatory Commission (BTRC)</td></tr><tr><td>AML/CFT Guideline</td><td>🇭🇰 Hong Kong</td><td>Hong Kong Monetary Authority (HKMA)</td></tr><tr><td>Customer Due Diligence Requirements</td><td>🇭🇰 Hong Kong</td><td>Hong Kong Monetary Authority (HKMA)</td></tr><tr><td>KYC Master Direction</td><td>🇮🇳 India</td><td>Reserve Bank of India (RBI)</td></tr><tr><td>Telecom Subscriber Identity Verification Framework</td><td>🇮🇳 India</td><td>Telecom Regulatory Authority of India (TRAI)</td></tr><tr><td>Criminal Proceeds Act</td><td>🇯🇵 Japan</td><td>Financial Services Agency (JFSA)</td></tr><tr><td>AML/CFT Requirements</td><td>🇰🇷 South Korea</td><td>Financial Services Commission (FSC)</td></tr><tr><td>AML/CFT Act</td><td>🇳🇿 New Zealand</td><td>Department of Internal Affairs (DIA)</td></tr><tr><td>Biometric SIM Verification Regulations</td><td>🇵🇰 Pakistan</td><td>Pakistan Telecommunication Authority (PTA)</td></tr><tr><td>Notice 626</td><td>🇸🇬 Singapore</td><td>Monetary Authority of Singapore (MAS)</td></tr><tr><td>Customer Due Diligence Requirements</td><td>🇸🇬 Singapore</td><td>Monetary Authority of Singapore (MAS)</td></tr><tr><td>Enhanced Due Diligence Requirements</td><td>🇸🇬 Singapore</td><td>Monetary Authority of Singapore (MAS)</td></tr><tr><td>SIM Card Registration Framework</td><td>🇸🇬 Singapore</td><td>Infocomm Media Development Authority (IMDA)</td></tr></tbody></table>

### Middle East

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Regulation / Framework</th><th>Jurisdiction</th><th>Authority</th></tr></thead><tbody><tr><td>AML/CFT Rulebook</td><td>🇦🇪 United Arab Emirates</td><td>Dubai Financial Services Authority (DFSA)</td></tr><tr><td>AML Rulebook</td><td>🇦🇪 United Arab Emirates</td><td>Abu Dhabi Global Market (ADGM)</td></tr><tr><td>UAE AML/CFT Requirements</td><td>🇦🇪 United Arab Emirates</td><td>Central Bank of the UAE (CBUAE)</td></tr><tr><td>AML/CFT Module</td><td>🇧🇭 Bahrain</td><td>Central Bank of Bahrain (CBB)</td></tr><tr><td>AML/CFT Requirements</td><td>🇶🇦 Qatar</td><td>Qatar Central Bank (QCB)</td></tr><tr><td>AML Law</td><td>🇸🇦 Saudi Arabia</td><td>Saudi Central Bank (SAMA)</td></tr></tbody></table>

### Latin America

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Regulation / Framework</th><th>Jurisdiction</th><th>Authority</th></tr></thead><tbody><tr><td>AML Framework</td><td>🇧🇷 Brazil</td><td>Central Bank of Brazil (BCB)</td></tr><tr><td>Federal AML Law (LFPIORPI)</td><td>🇲🇽 Mexico</td><td>Financial Intelligence Unit (UIF)</td></tr></tbody></table>

### Africa

<table data-header-hidden="false" data-header-sticky><thead><tr><th>Regulation / Framework</th><th>Jurisdiction</th><th>Authority</th></tr></thead><tbody><tr><td>SIM Registration Regulations</td><td>🇰🇪 Kenya</td><td>Communications Authority of Kenya (CAK)</td></tr><tr><td>SIM Registration Regulations</td><td>🇳🇬 Nigeria</td><td>Nigerian Communications Commission (NCC)</td></tr><tr><td>SIM Registration Requirements</td><td>🇷🇼 Rwanda</td><td>Rwanda Utilities Regulatory Authority (RURA)</td></tr><tr><td>Financial Intelligence Centre Act (FICA)</td><td>🇿🇦 South Africa</td><td>Financial Intelligence Centre (FIC)</td></tr><tr><td>RICA</td><td>🇿🇦 South Africa</td><td>Independent Communications Authority of South Africa (ICASA)</td></tr><tr><td>SIM Registration Regulations</td><td>🇹🇿 Tanzania</td><td>Tanzania Communications Regulatory Authority (TCRA)</td></tr><tr><td>SIM Card Registration Regulations</td><td>🇺🇬 Uganda</td><td>Uganda Communications Commission (UCC)</td></tr></tbody></table>

## Custom policies

In addition to supported global and regulatory frameworks, organizations can implement custom compliance policies tailored to internal risk frameworks, onboarding requirements, [customer risk models](/documentation/product-guides/due-diligence-tools/risk-profile), operational controls, and regulatory obligations.


# AML Screening Check

AML screening for KYC and KYB, including sanctions, watchlists, PEP, adverse media, continuous monitoring, and real-time alerts.

### AML Screening Overview

ComplyCube’s AML Screening Check helps you meet AML and KYC compliance requirements through real-time customer and business screening.

Use it for **sanctions screening**, **watchlist screening**, **PEP (Politically Exposed Person) screening**, **adverse media screening**, and **ongoing AML monitoring**.

Powered by a **proprietary graph network**, **entity resolution system**, **multilingual matching engine**, and **global partner network**, AML Screening covers 3,000+ [international, regional, and local lists](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check/lists-included).

It can also surface **relatives**, **associates**, and **business relations**, whether they are linked to the matched subject or the listed person connected to that subject.

AML Screening supports **real-time screening**, **continuous monitoring**, **instant alerts**, and **KYB screening** for both **individuals** and **businesses**.

Choose between two AML Screening variants: [Standard](#service-variants) and [Extensive](#service-variants).

{% hint style="info" %}
[Learn about the AML Screening Checks API.](/documentation/api-reference/check-types/aml-screening-check)
{% endhint %}

### Common use cases

Use AML screening to reduce compliance risk across key customer journeys:

* **KYC and KYB onboarding**: Screen individuals, businesses, directors, shareholders, and beneficial owners against sanctions, watchlists, and PEP lists during account opening.
* **Transaction screening**: Screen parties involved in payments and transfers to detect sanctions, watchlist, and financial crime exposure.
* **CDD and EDD**: Apply risk-based screening for higher-risk customers, products, jurisdictions, and business relationships.
* **Ongoing monitoring**: Rescreen customers continuously and trigger alerts when sanctions, watchlist, PEP, or adverse media status changes.
* **Periodic reviews**: Refresh screening results as part of scheduled customer due diligence and risk review workflows.

### How AML screening works

AML Screening Check combines a proprietary graph network with a multilingual matching engine to identify potential sanctions, PEP, watchlist, enforcement, and adverse media matches.

#### Data sources

Screening data comes from **ComplyCube’s own data**, **regulatory publications**, and **leading global data providers**.

This includes more than **3,000 data points** across **sanctions lists**, **PEP records**, **watchlists**, **adverse media**, **enforcement datasets**, and **regulatory sources** from **government authorities**, **international organizations**, **trusted commercial partners**, and ComplyCube’s continuously maintained data network.

Records are continuously **standardized**, **enriched**, and **maintained** to support consistent AML screening across regions, jurisdictions, and languages.

Matched records will also return comprehensive source-backed data, images, and notes to support alert review and investigation.

<figure><img src="/files/ZeOFdbVlzh80OIsss5Xd" alt=""><figcaption><p>Sample view of a potential match (full result not displayed)</p></figcaption></figure>

#### Graph network and entity resolution

ComplyCube’s screening data is prepared in advance through a **proprietary graph network** that continuously structures and resolves entity data across global datasets.

Before any screening check runs, this process helps to:

* Remove **duplicate records** across multiple sources.
* Link **aliases** and **alternative identities**.
* Normalize inconsistent **formatting** and **naming structures**.
* Connect **relatives**, **associates**, **business relations**, and **ownership links**.
* Consolidate fragmented records into **unified entity profiles**.

<figure><img src="/files/437r9DSn3Z2mSDWGFpBf" alt=""><figcaption><p>Sample association graph showing how related entities connect to a subject across screening datasets</p></figcaption></figure>

This means screening runs against cleaner, already-resolved entity data, which reduces **duplicate alerts** and improves the quality of **potential match results**.

#### Multilingual matching

The matching engine compares **names** and **entity attributes** across **languages**, **scripts**, and **regional naming conventions**.

It accounts for:

* **Phonetic similarity**
* **Transliterations** between scripts
* **Linguistic** and **regional spelling variations**
* **Cultural** and **regional** naming structures
* **Non-Latin scripts**
* **Patronymics** and **compound names**
* **Honorifics** and **titles**

This supports screening across **Latin**, **Arabic**, **Chinese**, **Cyrillic**, **Japanese**, **Korean**, **Thai**, and other major writing systems.

{% hint style="info" %}
Combining **graph-based entity resolution** with **multilingual matching** helps improve **match consistency** while eliminating **duplicate noise** and **unnecessary false positives**.

This allows **compliance teams** to review **cleaner** and more **relevant screening results** across global datasets.
{% endhint %}

#### Match explainability

Screening results include structured match metadata to help compliance teams understand why a potential match was returned and how closely it aligns with the screened entity.

Common match signals include:

* **Name-based**: Exact, partial, alias, transliteration, former name, and alternative spelling matches.
* **Attribute-based**: Date of birth, nationality, country, address, passport, or company registration matches.

This supports alert review, investigations, and regulatory reporting.

<figure><img src="/files/Epnxs3KtXEagSJTD4OL0" alt="Placeholder for a match explainability visual"><figcaption><p>Sample explanation for a match score on hover</p></figcaption></figure>

### Screening configuration

{% columns %}
{% column %}

<figure><img src="/files/wXCpDonrEsdfxun518oT" alt=""><figcaption></figcaption></figure>
{% endcolumn %}

{% column %}
AML Screening is configurable. Adjust it to your policy, risk appetite, and review capacity.

You can configure:

* **Scope coverage**: Select which datasets and list types to screen, such as sanctions, PEP, adverse media, and other official lists.
* **Continuous monitoring**: Enable ongoing monitoring and real-time alerts when new potential matches are identified.
* **Match thresholds**: Define score bands that suppress weak matches, auto-reject lower-confidence matches, and route stronger matches for review.
* **Search mode**: Choose between **Precise** and **Fuzzy** matching, depending on how strictly you want names and attributes to match.
* **Exclusion rules**: Exclude inactive entities, deceased persons, low-quality aliases, and matches missing key attributes such as date of birth, gender, nationality, or incorporation country.
  {% endcolumn %}
  {% endcolumns %}

{% hint style="info" %}
More granular AML screening controls and settings are available for **Enterprise** customers.
{% endhint %}

### Continuous monitoring

AML Screening continuously monitors **individuals** and **businesses** against updated sanctions, politically exposed person (PEP), watchlist, and adverse media data. Rather than relying on one-time screening, ongoing monitoring automatically identifies new matches and changes to existing records throughout the **customer lifecycle**.

When monitoring is **enabled**, ComplyCube screens your clients **continuously throughout the day** and generates alerts whenever a potential new match or material risk change is detected. Notifications can be delivered in **real time through webhooks or email**, allowing your compliance team to review changes and take appropriate action quickly.

Continuous monitoring is ideal for organizations that must meet ongoing AML obligations, maintain up-to-date customer risk assessments, and respond promptly to evolving financial crime risks.

To make monitoring more effective over time, teams can validate potential matches and feed those decisions back into future alert handling.

### Match validation

Potential matches can be validated as **confirmed** or **rejected**.

This improves ongoing monitoring. Teams can distinguish true exposure changes from previously rejected false positives.

It also strengthens auditability and gives you a stronger monitoring posture over time.

<figure><img src="/files/Q4Cnn3KMpsBZPy4XHdwr" alt=""><figcaption><p>Validation of a match</p></figcaption></figure>

### Service variants

We offer two levels of AML Screening, <mark style="color:blue;">**Standard**</mark> and <mark style="color:blue;">**Extensive**</mark>, designed to support different risk profiles and compliance requirements.

#### Comparison at a glance

<table><thead><tr><th valign="top">Feature</th><th valign="top">Standard AML Screening</th><th valign="top">Extensive AML Screening</th></tr></thead><tbody><tr><td valign="top"><strong>Sanctions coverage</strong></td><td valign="top"><ul class="contains-task-list"><li><input type="checkbox" checked>Sanctions lists</li><li><input type="checkbox" checked>Other official lists</li><li><input type="checkbox" checked>War crime</li><li><input type="checkbox" checked>Sanctions control</li></ul></td><td valign="top"><ul class="contains-task-list"><li><input type="checkbox" checked>Sanctions lists</li><li><input type="checkbox" checked>Other official lists</li><li><input type="checkbox" checked>War crime</li><li><input type="checkbox" checked>Sanctions control</li><li><input type="checkbox" checked>Child sexual exploitation</li><li><input type="checkbox" checked>Terror</li><li><input type="checkbox" checked>Other exclusion lists</li></ul></td></tr><tr><td valign="top"><strong>PEP coverage</strong></td><td valign="top"><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JAF0I0xV8IXZOscPw#pep-levels-explained">Level 1</a></td><td valign="top"><a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-M7JAF0I0xV8IXZOscPw#pep-levels-explained">Levels 1-4</a></td></tr><tr><td valign="top"><strong>Adverse media coverage</strong></td><td valign="top">Not included</td><td valign="top"><ul class="contains-task-list"><li><input type="checkbox" checked>Environment &#x26; production</li><li><input type="checkbox" checked>Social &#x26; labor</li><li><input type="checkbox" checked>Competitive &#x26; financial</li><li><input type="checkbox" checked>Regulatory</li></ul></td></tr><tr><td valign="top"><strong>Other lists</strong></td><td valign="top">Not included</td><td valign="top"><ul class="contains-task-list"><li><input type="checkbox" checked>Organized crime</li><li><input type="checkbox" checked>Financial crime</li><li><input type="checkbox" checked>Tax crime corruption</li><li><input type="checkbox" checked>Trafficking</li><li><input type="checkbox" checked>Associated entity</li></ul></td></tr></tbody></table>

#### PEP levels explained

ComplyCube's PEP levels are outlined below.

<table><thead><tr><th width="108" valign="top">Level</th><th valign="top">PEP Coverage</th></tr></thead><tbody><tr><td valign="top">1</td><td valign="top"><ul><li>Heads and Deputies Heads of State or National Government</li><li>National Government Ministers</li><li>Members of the National Legislature</li></ul></td></tr><tr><td valign="top">2</td><td valign="top"><ul><li>Heads and Deputy Heads of Regional Government</li><li>Senior Civil Servants-National Government</li><li>Senior Civil Servants-Regional Government</li><li>Senior Members of the Armed Forces</li><li>Senior Members of the Police Services</li><li>Senior Members of the Secret Services</li><li>Senior Members of the Judiciary</li><li>Embassy and Consular Staff</li><li>Regional Government Ministers</li><li>Religious Leaders</li></ul></td></tr><tr><td valign="top">3</td><td valign="top"><ul><li>State Corporation Executives</li><li>State Agency Officials</li><li>Political Party Officials</li></ul></td></tr><tr><td valign="top">4</td><td valign="top"><ul><li>International Organization Officials</li><li>City Mayors</li><li>Political Pressure and Labor Group Officials</li><li>Local Public Officials</li><li>International Sporting Organization Officials</li><li>Other</li></ul></td></tr></tbody></table>

### Sample result

The example below shows a representative AML Screening Check result for sanctions, watchlist, PEP, and adverse media screening.

Use it to see how potential matches, screening categories, outcomes, and supporting match context may appear in an AML screening report.

<figure><img src="/files/CxBXqqquu8QRYW4MRWS5" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

An AML Screening Check takes **under 1 second** to complete.

### Frequently asked questions

<details>

<summary>What information is needed for an AML screening check?</summary>

You can run AML screening with a name alone, but match quality improves when you add more identifying data.

For individuals, use details like **date of birth**, **nationality**, and **country**. For businesses, use **registered name**, **registration number**, and **incorporation country**.

</details>

<details>

<summary>Can AML screening be used for both KYC and KYB?</summary>

Yes.

AML Screening supports both **individual screening** and **business screening**.

You can screen customers, companies, directors, shareholders, and beneficial owners in the same compliance flow.

</details>

<details>

<summary>How does AML screening reduce false positives?</summary>

AML Screening reduces false positives through **entity resolution**, **multilingual matching**, and configurable screening controls.

You can tune **match thresholds**, choose **Precise** or **Fuzzy** search, and exclude weak matches missing key attributes.

</details>

<details>

<summary>What happens after a potential sanctions or PEP match is found?</summary>

Each potential match includes **match metadata**, **source-backed details**, and supporting context for review.

Compliance teams can investigate the alert, then mark it as **confirmed** or **rejected** to improve future monitoring outcomes.

</details>

<details>

<summary>Can I combine AML screening with custom lists and workflows?</summary>

Yes.

You can extend screening with [Custom Lists](/documentation/product-guides/watchlist-pep-and-adverse-media/custom-lists), automate decision flows in [Workflows](/documentation/product-guides/compliance-studio/workflows), and add downstream scoring with [AML Risk Scoring](/documentation/product-guides/due-diligence-tools/risk-profile).

This helps you move from screening results to consistent KYC and KYB decisioning.

</details>

<details>

<summary>How does continuous monitoring work?</summary>

Continuous monitoring keeps screened individuals and businesses under active review after the initial AML check.

Once enabled, ComplyCube actively monitors the client against sanctions, PEP, watchlist, and adverse media updates, then notifies you when something changes.

</details>

<details>

<summary>How are continuous monitoring alerts delivered?</summary>

Alerts are delivered in real-time through **webhooks** or **email**.

This lets you route changes directly into your case management, review queues, or internal notification workflows.

</details>

<details>

<summary>What changes trigger a continuous monitoring alert?</summary>

Alerts can be triggered when a new potential match appears or when an existing matched record changes.

This includes updated sanctions, watchlist, PEP, and adverse media exposure that affects the monitored client.

</details>

### Related checks

Combine AML screening with other KYC and fraud checks, such as:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for biometric liveness verification.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for identity and address verification.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) for device-level fraud signals (VPN, emulator, root/jailbreak).

### Related topics

Use these to configure screening coverage, run it at scale, and manage outcomes:

* [Custom Lists](/documentation/product-guides/watchlist-pep-and-adverse-media/custom-lists) to extend screening with your own internal lists.
* [Bulk Processing](/documentation/product-guides/watchlist-pep-and-adverse-media/bulk-processing) to run screening across many customers.
* [AML Risk Scoring](/documentation/product-guides/due-diligence-tools/risk-profile) to add risk indicators to your AML decisions.
* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate screening inside an onboarding journey.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent decision rules across journeys.


# Screening data coverage

Explore AML screening data coverage across 3,000+ sanctions lists, watchlists, PEP, and adverse media sources for KYC and KYB compliance.

ComplyCube sources data exclusively from **authoritative**, **verified sources** and **strategic partners**. Datasets are refreshed continuously throughout the day to ensure the screening engine operates on the most current information available.

For **Politically Exposed Persons (PEPs)** and **Adverse Media**, data is curated from thousands of reputable global sources and undergoes expert human verification and auditing to ensure accuracy, integrity, and completeness. ComplyCube does not rely on unverified or crowd-sourced public data sources.

Our **Sanctions and Watchlist** data is aggregated, structured, and normalized, eliminating duplicates across **3,000+ global, regional, and local sources**. Below is a ***non-exhaustive sample*** of notable sources, organized by jurisdiction:

### :earth\_asia: International

* United Nations Security Council
* European Union Consolidated List
* INTERPOL
* African Development Bank

### :flag\_us: United States

* Bureau of Industry and Security (BIS)
* Central Intelligence Agency (CIA)
* Department of the Treasury
* Federal Bureau of Investigation (FBI)
* Office of Foreign Assets Control (OFAC)

### :flag\_gb: United Kingdom

* Crown Prosecution Service
* HM Treasury
* Financial Conduct Authority (FCA)
* Office of Financial Sanctions Implementation (OFSI)
* The Gambling Commission

### :flag\_de: Germany

* BaFin Warnings and Enforcement Notices
* Federal Ministry of the Interior (BMI)

### :flag\_fr: France

* Autorité de Contrôle Prudentiel et de Résolution (ACPR)
* Autorité des Marchés Financiers (AMF)
* Banque de France

### :flag\_it: Italy

* Autorità Garante della Concorrenza e del Mercato (AGCM)
* Bank of Italy
* Commissione Nazionale per le Società e la Borsa (CONSOB)

### :flag\_ca: Canada

* Canadian Investment Regulatory Organization (CIRO)
* Canadian Securities Administrators (CSA)
* Global Affairs Canada

### :flag\_au: **Australia**

* Australian Securities and Investments Commission (ASIC)
* Australian Transaction Reports and Analysis Centre (AUSTRAC)
* Department of Foreign Affairs and Trade (DFAT)

### :flag\_nl: Netherlands

* Authority for the Financial Markets (AFM)
* De Nederlandsche Bank (DNB)

### :flag\_ch: Switzerland

* Federal Council
* Federal Department of Economic Affairs
* Financial Market Supervisory Authority (FINMA)
* Money Laundering Control Authority (MLCA)
* State Secretariat for Economic Affairs (SECO)

### :flag\_ae: United Arab Emirates

* Central Bank of the UAE (CBUAE)
* Dubai Financial Services Authority (DFSA)
* Financial Services Regulatory Authority (ADGM FSRA)
* Virtual Assets Regulatory Authority (VARA)

### :flag\_sa: Saudi Arabia

* Capital Markets Authority (CMA)
* Central Bank of Saudi Arabia (SAMA)
* Ministry of Interior (MOI)

### :flag\_in: India

* Ministry of Corporate Affairs
* Ministry of Home Affairs (MHA)
* National Stock Exchange (NSE)
* Securities and Exchange Board of India (SEBI)

### :flag\_sg: Singapore

* Accounting and Corporate Regulatory Authority (ACRA)
* Commercial Affairs Department
* Corrupt Practices Investigation Bureau (CPIB)
* Inland Revenue Authority of Singapore (IRAS)
* Monetary Authority of Singapore (MAS)
* Ministry of Home Affairs
* Ministry of Law

### :flag\_cn: China

* Ministry of Commerce (MOFCOM) - Unreliable Entity List
* Ministry of Public Security

### :flag\_jp: Japan

* Ministry of Defense (MOD)
* Ministry of Land, Infrastructure, Transport and Tourism (MLIT)

### :flag\_br: Brazil

* Banco Central
* Ministry of Economy
* Ministry of Labour
* The National Register of Ineligible and Suspended Companies (CEIS)
* The Registry of Banned Private Non-Profit Entities (CEPIM)
* The Securities and Exchange Commission of Brazil (CVM)

### :globe\_with\_meridians: Other Jurisdictions

* Austria - Financial Market Authority (FMA)
* Bahamas - Central Bank of the Bahamas
* Belize - International Financial Services Commission (IFCS)
* Belgium - Financial Services and Markets Authority (FSMA)
* Costa Rica - Superintendencia General de Valores
* Cyprus - Securities and Exchange Commission (CYSEC)
* Greece - Hellenic Capital Market Commission (HCMC)
* Hong Kong - Securities and Futures Commission (SFC)
* Ireland - Central Bank
* Latvia - Financial and Capital Market Commission (FCMC)
* Liechtenstein - Financial Market Authority (FMA)
* Lithuania - Financial and Capital Market Commission (FCMC)
* Malta - Financial Services Authority (FSA)
* Mexico - Superior Audit of Federation
* Pakistan - Federal Investigation Agency (FIA) and National Counter Terrorism Authority (NACTA)
* Poland - Financial Supervision Authority (FSA)
* Qatar - Financial Centre Authority (FCA)
* Russia - Federal Financial Monitoring Services
* South Africa - Financial Sector Conduct Authority (FSCA) / Financial Services Board (FSB)
* South Korea - Ministry of Strategy and Finance (MOSF), Financial Supervisory Service (FSS) and Financial Services Commission (FSC)
* Tunisia - Conseil du Marché Financier (CMF)
* Turkey - Ministry of Interior and Capital Markets Board (CMB)

> *The above is a non-exhaustive sample. ComplyCube screens against over 3,000 global, regional, and local sources.*


# Custom Lists

Create custom watchlists for AML screening in KYC and KYB using internal sanctions, PEP, adverse media, and other risk lists.

### Custom Lists Overview

Custom Lists let you create **custom screening lists** in ComplyCube. Use them to extend ComplyCube’s [AML Screening Checks](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) with your own internal or proprietary data.

Screen both **individuals** and **businesses** during **KYC** and **KYB**.

Typical lists include blocked customers, internal fraud lists, high-risk counterparties, and jurisdiction-specific risk lists.

{% hint style="info" %}
This service is only available through our **Enterprise Plan**. Get in touch with your Account Manager to enable it.
{% endhint %}

{% hint style="info" %}
[Learn about the Custom Lists API.](https://docs.complycube.com/api-reference/tools/custom-lists)
{% endhint %}

### Common use cases

Use Custom Lists to improve screening coverage in cases like:

* **Internal watchlists**: Screen against your blocked customers and internal fraud lists.
* **Regulatory and enforcement lists**: Screen against industry-specific regulatory actions, enforcement notices, or prohibited entities relevant to your sector.
* **Shared fraud databases**: Screen against consortium or third-party fraud lists to identify known bad actors before approval.
* **Higher-risk portfolios**: Add bespoke risk lists for specific products or jurisdictions.

### How custom lists works

Once a Custom List is created, you can upload entities using **CSV files**, **API requests**, or an **SFTP integration**.

These lists are then included in AML screening checks alongside ComplyCube’s global datasets.

<figure><img src="/files/o7gYB3L9vpQXfdcNzwHs" alt="ComplyCube Custom Lists view for custom watchlists and AML screening"><figcaption><p>Custom Lists view in the ComplyCube Portal</p></figcaption></figure>

### Upload options

You can upload and manage Custom List entities using the following methods:

<table><thead><tr><th width="131.53125">Method</th><th>Description</th></tr></thead><tbody><tr><td><strong>Web</strong> <strong>Portal</strong></td><td>Create and manage lists, then upload entity data via CSV through the <a href="https://portal.complycube.com/tools/customLists">Custom Screening Lists</a> page. See the <a href="/spaces/KyFKMqftsmT6qln9zo5y/pages/-MVvn2s46XsSTMJqh5ip#csv-template">CSV template</a>.</td></tr><tr><td><strong>API</strong></td><td><a href="https://docs.complycube.com/api-reference/tools/custom-lists">Add and update entities programmatically</a> in real time using the Custom Lists API.</td></tr><tr><td><strong>SFTP</strong></td><td>Schedule secure CSV or JSON uploads via SFTP for automated list refreshes. Contact your <strong>Account Manager</strong> for setup details.</td></tr></tbody></table>

### CSV template

To use our CSV template:

1. Download the **sample template** below.
2. Open it in **Excel**, **Numbers**, or any compatible spreadsheet editor.
3. Keep the first row unchanged, it contains the required column headers needed for correct parsing.
4. Enter your data into the relevant columns.
5. Save the file once complete.
6. Upload it through the Portal.

{% file src="/files/-MVx2NbvEXyKUrOmlmlZ" %}
Sample Template
{% endfile %}

### Frequently asked questions

<details>

<summary>What are Custom Lists used for?</summary>

AML custom watchlists help you screen against internal or proprietary risk data during **KYC** and **KYB**.

Use them for blocked customers, internal fraud records, high-risk counterparties, and sector-specific or jurisdiction-specific screening lists.

</details>

<details>

<summary>What can I add to a Custom List?</summary>

You can add both **individuals** and **businesses**.

Typical entries include blocked customers, internal fraud cases, high-risk counterparties, and sector-specific or jurisdiction-specific watchlists.

</details>

<details>

<summary>How do I upload or update Custom List data?</summary>

You can manage data through the **Portal**, the **Custom Lists API**, or **SFTP**.

Use the Portal for manual CSV uploads. Use the API or SFTP for automated or recurring updates.

</details>

<details>

<summary>Will Custom Lists be screened alongside ComplyCube datasets?</summary>

Yes.

Once configured, Custom Lists are included in AML screening checks alongside ComplyCube’s global screening data.

</details>

<details>

<summary>Can I use Custom Lists for both KYC and KYB screening?</summary>

Yes.

Custom Lists support screening for both **individuals** and **businesses**, so they fit both **KYC** and **KYB** use cases.

</details>

### Related checks

Combine Custom Lists-enabled screening with other KYC and fraud checks, such as:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for biometric liveness verification.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for identity and address verification.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) for device-level fraud signals (VPN, emulator, root/jailbreak).

### Related topics

Use these to configure screening coverage, run it at scale, and manage outcomes:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate screening inside onboarding journeys.
* [Bulk Processing](/documentation/product-guides/watchlist-pep-and-adverse-media/bulk-processing) to run screening checks at scale using CSV uploads.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent decision rules across workflow sessions.
* [Automation](/documentation/product-guides/due-diligence-tools/customisable-thresholds) to tune screening thresholds (*standalone checks only*).
* [AML Risk Scoring](/documentation/product-guides/due-diligence-tools/risk-profile) to add risk indicators and support CDD/EDD decisions.


# Bulk Processing

Bulk AML screening for KYC and KYB. Upload CSV files to screen sanctions, watchlists, PEP, and adverse media at scale.

### Bulk Processing Overview

Bulk Processing (batch processing) lets you **bulk upload customers** and run batch [AML Screening Checks](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) in the ComplyCube Portal.

It’s a **no-code** solution designed for businesses of all sizes. Use it to import large client datasets into ComplyCube via **CSV upload**, whether for **migration purposes** or to run periodic **batch AML screenings** with **continuous monitoring**.

{% hint style="info" %}
This service has a **soft limit** of **1000 customers** per batch. Get in touch with your **Account Manager** to increase it.
{% endhint %}

{% hint style="info" %}
ComplyCube is also capable of processing files in bulk through **Secure File Transfer Protocol (SFTP)**. Get in touch with your **Account Manager** to enable this method.
{% endhint %}

### Common use cases

Use Bulk Processing when you need to run compliance checks across a large dataset:

* **Customer migration**: Upload existing customers from another system during migration.
* **Audit & remediation runs**: Run a bulk [AML screening check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) to validate or remediate a large set of customers after data corrections, rule changes, or an internal audit.
* **Periodic batch screenings**: Upload customer files as part of scheduled internal processes, such as recurring screening reviews, control checks, or compliance refresh cycles.
* **Internal list matching**: Combine with [Custom Lists](/documentation/product-guides/watchlist-pep-and-adverse-media/custom-lists) to screen against proprietary watchlists.

### Interactive demo

{% @arcade/embed url="<https://app.arcade.software/share/uGwZpFKK1AVvP27Ac2ne>" flowId="uGwZpFKK1AVvP27Ac2ne" %}

### CSV template

Use the CSV template to ensure your **bulk upload** parses correctly:

1. Download the **bulk upload sample template** below.
2. Open it in **Excel**, **Numbers**, or any compatible spreadsheet editor.
3. Keep the first row unchanged, it contains the required column headers needed for correct parsing.
4. Enter your data into the relevant columns.
5. Save the file once complete.
6. Upload it through the Portal.

{% file src="/files/-MdWkumYq45AUdB2-x6U" %}
Sample Template
{% endfile %}

### CSV formatting requirements

Use these requirements to avoid parsing issues during upload:

* Keep the template structure unchanged and do not **rename** or **remove** required headers.
* Always include the **type**, **email**, and either **first name** plus **last name** for individuals or **name** for companies.
* Use [2-letter ISO country codes](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) for **nationality**, **address country**, and **incorporation country** values, for example **GB**, **US**, or **FR**.
* Use **YYYY-MM-DD** for **date of birth** values.
* If you include an **address**, always include the **line**, **city**, and **country** to avoid parsing errors.

{% hint style="info" %}
If the **address** portion of an entry cannot be processed, the issue is recorded in the **error file** (available on the [Portal](https://portal.complycube.com/batchProcessor)). However, **client creation** and any selected **screening checks** will still proceed.
{% endhint %}

### Best practices

Use these practices to help your uploads run smoothly:

* Include stronger identifiers like **date of birth**, **nationality**, or **registration number** where possible.
* Remove **duplicate records** before upload to reduce duplicate clients and repeated screening results.
* Review the **error file** after each batch run and correct any flagged records before the next run.
* Test with a **small batch first** to confirm your data maps correctly.
* Run bulk processing jobs **outside your peak usage windows.**

### Frequently asked questions

<details>

<summary>When should I use Bulk Processing instead of the API?</summary>

Use Bulk Processing when you already have customer data in a **CSV file** or need a manual or periodic screening run.

Use the API when you need **real-time**, **fully automated** screening inside your own systems.

</details>

<details>

<summary>What customer data improves match quality in a bulk screening file?</summary>

For individuals, add fields like **date of birth**, **nationality**, and **country** where possible.

Use **YYYY-MM-DD** for **date of birth** values.

Use **2-letter ISO country codes** for **nationality** and **address country** values, for example **GB**, **US**, or **FR**.

For businesses, include **registered name**, **registration number**, and **incorporation country**.

Use a **2-letter ISO country code** for **incorporation country** values, for example **GB**, **US**, or **FR**.

If you provide **client details**, include the **type**, **email**, and either **first name** plus **last name** for individuals or **name** for companies.

If you provide an **address**, include the **line**, **city**, and **country** to reduce parsing errors.

More identifying data helps reduce weak matches and improves screening quality.

</details>

<details>

<summary>Can the same batch include both individuals and businesses?</summary>

Yes.

Bulk Processing supports **KYC** and **KYB** screening use cases.

Make sure each record follows the sample template and contains the right fields for the entity type you are uploading.

</details>

<details>

<summary>Can I rerun screening after fixing customer data?</summary>

Yes.

Bulk Processing is well suited to **remediation** and **data correction** exercises.

After you fix the source data, upload a new batch to rerun screening across the affected customers.

</details>

<details>

<summary>Do I need extra setup for automated bulk file transfers?</summary>

Yes.

**SFTP** is available for automated bulk file delivery, but it must be enabled first.

Contact your **Account Manager** if you want to set up scheduled file transfers.

</details>

### Related topics

* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, watchlist, PEP, and adverse media screening.
* [Custom Lists](/documentation/product-guides/watchlist-pep-and-adverse-media/custom-lists) to extend AML screening with proprietary risk lists.


# Document Check

ID document verification for KYC. Authenticate passports and national IDs. Extract OCR, MRZ, barcode, and NFC chip data.

### Document Check Overview

A Document Check is an advanced **ID document verification** service designed for **KYC onboarding** and **digital identity** **verification**.

It allows businesses to verify passports, driving licences, and national identity cards while **detecting document fraud**, including **deepfake portrait swaps**, **Photoshop edits**, and **image manipulation**, and **extracting structured identity data** for compliance and downstream processing.

ComplyCube supports verification of over [13,000 document types](/documentation/product-guides/identity-verification/document-check/document-types-per-country) across **250+ countries and territories**, enabling global identity coverage. Supported documents include:

* Passports
* Driving licenses
* National identity cards
* Residence permits
* Tax identification documents
* Other region-specific IDs, including voter, refugee, and health cards

{% hint style="info" %}
While this check can be run entirely through our API, we **highly** **recommend** using the [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide). These SDKs guide your customers through the capture process, reducing friction, improving completion rates, and minimizing false positive outcomes.
{% endhint %}

{% hint style="info" %}
[Learn about the Document Checks API.](/documentation/api-reference/check-types/document-check)
{% endhint %}

### Common use cases

Document Checks enable businesses to verify identities securely, reduce onboarding fraud, and meet global AML and compliance requirements at scale. They're typically used for:

* **Digital KYC onboarding**: Authenticate passports and government-issued IDs during remote customer acquisition.
* **Cross-border identity verification**: Validate identity documents across multiple countries and jurisdictions with broad global coverage.
* **Age verification and access control**: Verify date of birth from government-issued IDs to confirm age eligibility for restricted services and regulated products.
* **Fraud prevention**: Detect fake, tampered, or manipulated ID documents during customer registration.
* **Regulated industry compliance**: Extract structured ID data and generate audit-ready verification records for regulated industries such as fintech, telcos, crypto, and marketplaces.

### How document check works

ComplyCube verifies the submitted document through a series of capture, authenticity, fraud, and data extraction checks:

* **Real-time capture quality checks**: When you use the [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide), ComplyCube checks image quality in real time during capture. This helps ensure the document is clear, complete, and suitable for validation before the check runs.
* **Document authenticity verification:** Performs forensic analysis of built-in security features such as holograms, print patterns, layout consistency, and embedded protections to confirm the document is genuine.
* **Fraud detection**: Detects tampering, Photoshop edits, image manipulation, deepfake swaps, camera injections, photocopies, and screen replays.
* **OCR and MRZ extraction**: Extracts identity data, signatures, and images from the document, and validates Machine Readable Zone (MRZ) data in ICAO-compliant format.
* **Barcode and NFC chip authentication**: Extracts data from barcodes and [verifies the integrity of embedded RFID chips using NFC](/documentation/product-guides/identity-verification/document-check/nfc-chip-verification) on compatible ePassports and identity cards to confirm authenticity.
* **Lost, stolen, and flagged document screening**: Screens documents against global blacklists and databases of lost, stolen, flagged, and otherwise compromised IDs.
* **Privacy-first redaction**: Automatically [redacts sensitive data](/documentation/product-guides/identity-verification/document-check/redaction) fields in images and extracted data to support data minimization and compliance requirements.

{% hint style="info" %}
[RFID chip](/documentation/product-guides/identity-verification/document-check/nfc-chip-verification) data extraction and analysis are available exclusively through our [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide), which use NFC to access the chip.
{% endhint %}

### Analysis performed

The Document Check runs multiple layers of analysis to validate the authenticity, integrity, and consistency of identity documents. Each analysis type focuses on a specific set of verifications.

The diagram below outlines the key analysis categories.

***

![Document Check Overview](/files/-M7O-M4eO4FD__4OS-r5)

***

**Detailed verification checks**

<table data-full-width="false"><thead><tr><th width="204.5703125">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Forensic Analysis</strong></td><td><ul><li><strong>Security elements check</strong>: Confirms embedded features (e.g., holograms, UV marks) are genuine.</li><li><strong>Tamper or manipulation detection</strong>: Identifies alterations, Photoshop edits, image manipulation, and other forgeries.</li><li><strong>Document liveness analysis</strong>: Ensures the document is physically present, not a static copy or AI-generated.</li><li><strong>Photo location analysis</strong>: Detects mismatched or swapped photos.</li><li><strong>MRZ classification and placement</strong>: Checks MRZ data is structured correctly and in the right place.</li></ul></td></tr><tr><td><strong>Format Analysis</strong></td><td><ul><li><strong>Country and document model validation</strong>: Confirms the ID matches official country formats.</li><li><strong>Photocopy detection</strong>: Flags photocopied or re-printed documents.</li></ul></td></tr><tr><td><strong>Content Analysis</strong></td><td><ul><li><strong>Expiry and issuance</strong>: Validates ID is current and correctly issued.</li><li><strong>Data integrity</strong>: Ensures consistency across fields.</li><li><strong>Specimen analysis</strong>: Compares against genuine sample IDs.</li><li><strong>Blacklist check</strong>: Detects IDs reported lost, stolen, or compromised.</li></ul></td></tr><tr><td><strong>MRZ Analysis</strong></td><td><ul><li><strong>Checksum validation</strong>: Confirms MRZ codes are valid.</li><li><strong>Format validation</strong>: Ensures compliance with ICAO standards.</li></ul></td></tr><tr><td><strong>RFID Analysis</strong></td><td><ul><li><strong>Basic and chip authentication</strong>: Confirms the RFID chip is original and untampered.</li><li><strong>Passive and active authentication</strong>: Validates chip data integrity.</li><li><strong>PACE (Password Authenticated Connection Establishment)</strong>: Ensures the RFID chip is genuine and has not been tampered with.</li><li><strong>Facial similarity check</strong>: Compares the chip-stored biometric photo with the document’s visible portrait.</li></ul></td></tr><tr><td><strong>Front &#x26; Back Analysis</strong></td><td><ul><li><strong>Format and consistency</strong>: Ensures details match across both sides of the document.</li></ul></td></tr><tr><td><strong>Consistency Analysis</strong></td><td><ul><li><strong>Cross-validation</strong>: Compares OCR data from VIZ, MRZ, barcodes, and RFID chip data for alignment.</li></ul></td></tr><tr><td><strong>Client Validation</strong></td><td><ul><li><strong>Age verification</strong>: Confirms whether the customer is older than the defined threshold.</li><li><strong>Client data consistency</strong>: Ensures submitted customer info matches extracted document data.</li></ul></td></tr></tbody></table>

### Sample result

The example below shows a representative Document Check result for document authenticity, data extraction, and validation outcomes.

Use it to see how extracted identity data, authenticity signals, and verification findings may appear in a Document Check report.

<figure><img src="/files/fpqCCrWZWZ4Ao4Me2un1" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

A Document Check takes an average of **8 seconds** to complete.

### Frequently asked questions

<details>

<summary>Which documents can I verify online with Document Check?</summary>

You can verify **passports**, **driving licences**, **national identity cards**, **residence permits**, and many other government-issued IDs.

See [Country and ID document coverage](/documentation/product-guides/identity-verification/document-check/document-types-per-country) for the full list.

</details>

<details>

<summary>Can Document Check detect fake, forged, or tampered IDs?</summary>

Yes.

Document Check is designed to detect **document fraud** such as tampering, Photoshop edits, image manipulation, photocopies, screen replays, and deepfake portrait swaps.

It also checks security features, document format consistency, MRZ validity, and blacklist exposure for lost, stolen, or compromised IDs.

</details>

<details>

<summary>Can Document Check extract OCR, MRZ, barcode, and NFC data?</summary>

Yes.

Document Check can extract structured identity data from **visual fields**, **MRZ**, and **barcodes**.

For compatible ePassports and identity cards, it can also verify and extract data from embedded RFID chips through [NFC chip verification](/documentation/product-guides/identity-verification/document-check/nfc-chip-verification) when you use the **Mobile SDKs**.

</details>

<details>

<summary>Do I need both sides of the ID document?</summary>

Not always.

The required sides depend on the **document type** and **issuing country**. Some documents only need the front. Others require both sides for full verification.

If you use the [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide), ComplyCube detects the expected sides from the provided document type and guides the user to capture one side or both sides as needed.

See [Expected sides per type](/documentation/product-guides/identity-verification/document-check/document-sides-per-type) for details.

</details>

<details>

<summary>Can I run ID document verification without a selfie?</summary>

Yes.

Document Check verifies the document itself. Add [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) when you also need **liveness detection** and **face match** against the document holder.

</details>

<details>

<summary>How do I improve online document verification pass rates?</summary>

Use clear images with **good lighting**, **minimal glare**, **sharp focus**, and **all document edges visible**.

Guided capture through the [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide) helps reduce submission errors and improve completion rates.

</details>

<details>

<summary>Can Document Check be used for age verification?</summary>

Yes.

Document Check can extract and validate **date of birth** from government-issued IDs, which makes it useful for **age verification** and access control flows.

For selfie-based age checks without document capture, see [Age Estimation Check](/documentation/product-guides/biometric-and-liveness-verification/age-estimation-check).

</details>

<details>

<summary>Which checks are commonly combined with Document Check in KYC?</summary>

Document Check is often paired with [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for liveness verification, [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check), and [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check).

This helps you move from document verification to a fuller identity and compliance decision in one [Workflow](/documentation/product-guides/compliance-studio/workflows).

</details>

### Related checks

You’ll typically run a Document Check alongside:

* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for liveness and selfie verification.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for identity and address verification via authoritative sources.
* [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check) to validate address documents when required.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media screening.

### Related topics

Use these when running or configuring Document Checks:

* [NFC chip verification](/documentation/product-guides/identity-verification/document-check/nfc-chip-verification) for chip-based document integrity checks (mobile).
* [Autofill](/documentation/product-guides/kyc-automation-services/autofill) for structured data extraction from identity documents.
* [Workflows](/documentation/product-guides/compliance-studio/workflows) to bundle Document Check into an end-to-end KYC journey.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply rule-based pass/fail logic and regulatory requirements.


# Country and ID document coverage

Explore KYC document verification coverage for Document Check, including supported countries, passports, driving licences, national IDs, and residence permits for identity verification.

ComplyCube [Document Check](/documentation/product-guides/identity-verification/document-check) supports **global ID document coverage** and **ID document verification** across **250+ countries and territories**, and **13,000+ identity document types**.

Use this coverage list to confirm which **countries** and **government-issued IDs** are supported for **KYC onboarding** and **digital identity verification**.

For passports, we support all variants, including **national**, **international**, **diplomatic**, **ePassports**, and **passport cards**.

In addition to the core document types listed in the table, Document Check also supports many other identity documents, including **visas**, **health cards**, **tax identification cards**, **voter cards**, **refugee cards**, and other **paper-based IDs**.

{% hint style="info" %}
Document Check can extract and parse identity data in **Latin**, **Arabic**, **Cyrillic**, **Chinese**, **Sanskrit**, **Sindhi**, **Tamil**, **Thai**, **Persian**, **Greek**, **Japanese**, **Urdu**, and **Hebrew** scripts.
{% endhint %}

<table data-header-hidden="false" data-header-sticky data-full-width="true"><thead><tr><th></th><th data-type="checkbox">Passport</th><th data-type="checkbox">Driving License</th><th data-type="checkbox">National ID</th><th data-type="checkbox">Residence Permit</th></tr></thead><tbody><tr><td>Abkhazia</td><td>true</td><td>true</td><td>false</td><td>false</td></tr><tr><td>Afghanistan</td><td>true</td><td>false</td><td>true</td><td>false</td></tr><tr><td>Albania</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Algeria</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Andorra</td><td>true</td><td>true</td><td>false</td><td>true</td></tr><tr><td>Angola</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Anguilla</td><td>true</td><td>true</td><td>false</td><td>false</td></tr><tr><td>Antigua and Barbuda</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Argentina</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Armenia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Aruba</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Australia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Austria</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Azerbaijan</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Bahamas</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Bahrain</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Bangladesh</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Barbados</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Belarus</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Belgium</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Belize</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Benin</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Bermuda</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Bhutan</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Bolivia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Bosnia And Herzegovina</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Botswana</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Brazil</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Brunei Darussalam</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Bulgaria</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Burkina Faso</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Burundi</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Cambodia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Cameroon</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Canada</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Cape Verde</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Cayman Islands</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Central African Republic</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Chad</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Chile</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>China</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Colombia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Comoros</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Congo</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Costa Rica</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Croatia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Cuba</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Curacao</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Cyprus</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Czech Republic</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Denmark</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Djibouti</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Dominica</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Dominican Republic</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Ecuador</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Egypt</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>El Salvador</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Equatorial Guinea</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Eritrea</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Estonia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Ethiopia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Fiji</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Finland</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>France</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Gabon</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Gambia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Georgia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Germany</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Ghana</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Gibraltar</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Great Britain</td><td>true</td><td>true</td><td>false</td><td>true</td></tr><tr><td>Greece</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Grenada</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Guatemala</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Guinea</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Guinea-Bissau</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Guyana</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Haiti</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Holy See</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Honduras</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Hungary</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Iceland</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>India</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Indonesia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Iran</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Iraq</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Ireland</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Israel</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Italy</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Ivory Coast</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Jamaica</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Japan</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Jordan</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Kazakhstan</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Kenya</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Kiribati</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Kosovo</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Kuwait</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Kyrgyzstan</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Lao</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Latvia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Lebanon</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Lesotho</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Liberia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Libya</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Liechtenstein</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Lithuania</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Luxembourg</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Macedonia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Madagascar</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Malawi</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Malaysia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Maldives</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Mali</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Malta</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Mauritania</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Mauritius</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Mexico</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Micronesia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Moldova</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Monaco</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Mongolia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Montenegro</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Montserrat</td><td>true</td><td>true</td><td>false</td><td>false</td></tr><tr><td>Morocco</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Mozambique</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Myanmar</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Namibia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Nepal</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Netherlands</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>New Zealand</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Nicaragua</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Niger</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Nigeria</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>North Korea</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Norway</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Oman</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Pakistan</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Palau</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Panama</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Papua New Guinea</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Paraguay</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Peru</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Philippines</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Poland</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Portugal</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Qatar</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Republic Of The Congo</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Romania</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Russian Federation</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Rwanda</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Saint Kitts And Nevis</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Saint Lucia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Saint Vincent And Grenadines</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Samoa</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>San Marino</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Sao Tome And Principe</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Saudi Arabia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Senegal</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Serbia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Seychelles</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Sierra Leone</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Singapore</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Sint Maarten</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Slovakia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Slovenia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Somalia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>South Africa</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>South Korea</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>South Sudan</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Spain</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Sri Lanka</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Sudan</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Suriname</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Swaziland</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Sweden</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Switzerland</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Syrian Arab Republic</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Taiwan</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Tajikistan</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Thailand</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Timor-Leste</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Togolese Republic</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Tonga</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Trinidad And Tobago</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Tunisia</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Turkey</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Turkmenistan</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Turks And Caicos Islands</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Uganda</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Ukraine</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>United Arab Emirates</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>United Kingdom</td><td>true</td><td>true</td><td>false</td><td>true</td></tr><tr><td>United Republic Of Tanzania</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>United States Of America</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Uruguay</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Uzbekistan</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Vanuatu</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Venezuela</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Viet Nam</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Yemen</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Zambia</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td>Zimbabwe</td><td>true</td><td>true</td><td>true</td><td>false</td></tr></tbody></table>


# NFC chip verification

Verify ePassport and eID NFC chips for KYC, identity verification, and document fraud detection via Mobile SDKs.

### Overview

NFC chip verification is a core component of ComplyCube’s [Document Check](/documentation/product-guides/identity-verification/document-check) service.

It uses **NFC (Near-Field Communication)** to read and verify the **RFID chip** embedded in modern identity documents. This includes **ePassports** and many **electronic national ID cards**. This is often referred to as **ePassport NFC chip verification** for **ICAO 9303 eMRTDs**.

Chip-based verification increases identity assurance. It also reduces document fraud in remote **KYC onboarding**.

### Benefits for KYC and fraud prevention

* **Higher identity assurance:** Validates the chip’s integrity using chip authentication and data integrity checks.
* **NFC data extraction from the chip:** Reads structured identity data perfectly and reduces OCR-only errors.
* **Stronger fraud detection:** Detects cloned or tampered chips and inconsistent chip vs. visual data.
* **Multi-layer verification:** Complements forensic checks, MRZ parsing, and security element validation.
* **Secure handling:** Uses encrypted NFC sessions and returns auditable verification results.

### How NFC passport scanning works

NFC chip verification runs as part of a Document Check when an RFID chip is present. The typical flow is:

1. The customer captures their ID as normal.
2. The Mobile SDK detects an NFC-readable RFID chip when supported.
3. The customer completes an NFC scan (tap-to-scan).
4. ComplyCube reads chip data and validates integrity and authenticity.
5. The result is returned as part of Document Check, for reporting and audit.

Depending on the document and chip, ComplyCube can perform:

* **Passive authentication:** Validates signed chip data against issuing authority certificates.
* **Chip and active authentication:** Confirms the chip is genuine and not cloned.
* **PACE:** Establishes a secure session with the chip before reading data.
* **Biometric consistency:** Compares the chip-stored portrait against the document image.

### Supported documents and availability

NFC scanning and analysis is supported only for documents that contain RFID chips. Examples include **ePassports** and modern **national ID cards**. Customers need an **NFC-capable smartphone** to complete the chip scan.

NFC chip verification is available exclusively through ComplyCube’s [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide). The SDKs prompt the customer to scan only when NFC is available and the document supports it.

### Frequently asked questions

<details>

<summary>What is NFC chip verification in identity verification?</summary>

NFC chip verification verifies the **embedded RFID chip** inside compatible identity documents, such as **ePassports** and some **electronic national ID cards**.

It helps confirm the chip is genuine, the data has not been altered, and the document is harder to clone or tamper with.

</details>

<details>

<summary>Is NFC verification the same thing as RFID authentication?</summary>

In practice, yes.

In identity verification, both terms usually refer to reading and validating the document’s embedded chip with a phone’s **NFC** capability.

The difference is technical. **NFC** is the short-range communication method used by the phone. **RFID authentication** is the verification process that checks the chip is genuine and its data is intact.

</details>

<details>

<summary>Which documents support NFC chip verification?</summary>

NFC chip verification only works on identity documents with an embedded **RFID chip**.

This usually includes **ePassports** and some **national ID cards**.

</details>

<details>

<summary>Does NFC chip verification require a phone with NFC?</summary>

Yes.

The customer needs an **NFC-capable smartphone** to read the chip and complete the scan.

If NFC is unavailable, the chip scan will be automatically skipped.

</details>

<details>

<summary>Is NFC chip verification available through web or API-only flows?</summary>

No.

NFC chip verification is available only through ComplyCube’s [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide), because reading the chip requires direct NFC access on the device.

</details>

<details>

<summary>Does NFC chip verification replace OCR and document forensic checks?</summary>

No.

NFC chip verification adds another verification layer. It complements **OCR**, **MRZ validation**, and **document forensic analysis** inside [Document Check](/documentation/product-guides/identity-verification/document-check).

</details>

### Related topics

* [Document Check](/documentation/product-guides/identity-verification/document-check) for end-to-end ID document verification.
* [Country & ID coverage](/documentation/product-guides/identity-verification/document-check/document-types-per-country) to confirm supported document types.


# Redaction (data masking)

Automatically redact and mask PII in KYC document verification to protect sensitive data, support GDPR compliance, and strengthen privacy controls.

### Overview

ComplyCube automatically applies **field-level redaction** (also known as **field masking** or **data masking**) on sensitive **personally identifiable information (PII)** fields to ensure compliance with global privacy regulations.

Examples of redacted fields include:

* **Dutch BSN** (Burgerservicenummer or Dutch Citizen Service Number)
* **Singapore NRIC** (National Registration Identity Card Number)
* **Korean RRN** (Resident Registration Number)

{% hint style="info" %}
To meet strict compliance requirements, sensitive fields are automatically redacted from **document images** stored in the customer record and the results of **Document Checks**. Where applicable, redaction is applied to both the **front and back** of the document.
{% endhint %}

{% hint style="info" %}
Users on our **Growth** or **Enterprise** **plans** can customize and add additional fields to their [redaction policies](https://portal.complycube.com/policies). Please contact your Account Manager to update your policy.
{% endhint %}

### Scope

Redaction is applied immediately on document capture, before the document image is stored. All instances of sensitive fields are masked, including those encoded within **QR codes**, the **Visual Inspection Zone (VIZ)**, the **Machine Readable Zone (MRZ)**, and **barcodes**.

ComplyCube does not **store** or **process** these sensitive fields, ensuring strong privacy protection and full regulatory compliance.

During **Document Check** processing, all redacted text fields return as fixed-length asterisk (\*) strings. This format is consistent across the **API**, **Web Portal**, and **reports**.

### Where redaction is applied

Redaction applies anywhere ComplyCube displays or returns document images or extracted fields, including:

* Stored document images in the customer record (Portal and exports).
* [Document Check](/documentation/product-guides/identity-verification/document-check) results returned via API and visible in the Portal.
* Generated reports that include document images or extracted fields.

### Configuring redaction policies

Redaction is enabled by default for supported sensitive fields.

If you need to modify or add masking rules, your redaction configuration can be updated by contacting your Account Manager.

### Sample illustrations of field redaction

<div><figure><img src="/files/KBf87YQwmnEtao0PJ0fB" alt="Example of personally identifiable information (PII) redaction (data masking) of a Dutch BSN on a passport"><figcaption><p>Redacted BSN on a Dutch passport</p></figcaption></figure> <figure><img src="/files/kMN2BVL4Tli3YOJUCZTP" alt="Example of personally identifiable information (PII) redaction (data masking) of a Korean RRN on a passport"><figcaption><p>Redacted RRN on a Korean passport</p></figcaption></figure></div>

### Frequently asked questions

<details>

<summary>What does redaction do in ComplyCube?</summary>

Redaction masks supported sensitive fields before document images are stored or returned.

This helps reduce privacy risk and supports compliance with data minimization requirements.

</details>

<details>

<summary>Why is redaction important for jurisdiction-specific compliance?</summary>

Some jurisdictions restrict the **processing** or **storage** of certain document fields, such as national ID numbers or other regulated identifiers.

Redaction helps meet these requirements by masking supported fields before they are stored or returned in results.

</details>

<details>

<summary>Where is redaction applied?</summary>

Redaction applies to stored **document images**, [Document Check](/documentation/product-guides/identity-verification/document-check) results, and generated reports.

It also covers sensitive data found in the **VIZ**, **MRZ**, **barcodes**, and supported **QR codes**.

</details>

<details>

<summary>Can I customize which fields are redacted?</summary>

Yes.

You can request changes to your redaction policy, including additional fields, if this is available under your plan.

</details>


# Expected sides per type

Depending the country and document type, ComplyCube may require one or both sides of the document.

Depending on the issuing country and document type, ComplyCube may require submission of either one or both sides of the document, for processing.

The table below specifies the number of sides expected for each document type.

{% hint style="info" %}
The ComplyCube **Web SDK**, **Mobile SDKs**, and **Hosted Solution** automatically capture the required document sides during the verification process.
{% endhint %}

<table><thead><tr><th width="227">Document Type</th><th width="87.48177083333331" align="center">Sides</th><th>Exceptions</th></tr></thead><tbody><tr><td>Passport</td><td align="center">1</td><td>-</td></tr><tr><td>Driving License</td><td align="center">2</td><td>-</td></tr><tr><td>Residence Permit</td><td align="center">2</td><td>-</td></tr><tr><td>National Identity Card</td><td align="center">2</td><td><p>Only one side for the following:<br></p><ul><li>🇦🇷 Argentina</li><li>🇨🇱 Chile</li><li><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1fe">🇨🇾</span> Cyprus </li><li>🇸🇻 El Salvador</li><li>🇨🇮 Ivory Coast</li><li>🇲🇾 Malaysia</li><li>🇵🇪 Peru</li><li>🇷🇴 Romania</li></ul></td></tr><tr><td>Visa</td><td align="center">1</td><td>-</td></tr></tbody></table>


# eID Check

Electronic identity verification (eID) for KYC using schemes like BankID, MitID, itsme, iDIN, Aadhaar, and UAE Pass.

### eID Check Overview

This service verifies a customer using a **national or bank-led electronic identification scheme**, such as **BankID** or **MitID**. By leveraging these schemes, we can securely validate a customer’s details against the records held by the issuing scheme.

This check provides a **high level of identity assurance**.

{% hint style="info" %}
[Learn about the eID Checks API.](/documentation/api-reference/check-types/eid-check)
{% endhint %}

### Common use cases

Use eID verification to increase identity assurance across key customer journeys:

* **Digital KYC onboarding**: Verify customer identity instantly using trusted national eID schemes, without requiring document upload.
* **High-assurance identity verification**: Rely on government-backed digital identity schemes to meet enhanced KYC and regulatory requirements.
* **Strong Customer Authentication (SCA)**: Re-authenticate users for sensitive actions such as payout or limit increases using scheme-based authentication.
* **Cross-border and local compliance**: Meet jurisdiction-specific identity verification requirements using nationally recognized eID schemes.

### How eID check works

An eID Check connects directly to the selected **eID scheme** or **identity provider**.

The customer is redirected, or handed off, to the scheme to complete authentication. This requires the customer to approve the request using the scheme’s own login flow, such as a **one-time password (OTP)**, banking app approval, or another supported authentication method.

Once the customer successfully authenticates, the scheme returns verified identity data to ComplyCube, which then validates it against the customer record to produce the eID Check result.

{% hint style="info" %}
Unlike [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check), which verifies identity by checking customer-provided details against trusted data sources, eID Check relies on live user authentication with the scheme before the check can complete.
{% endhint %}

### Supported eID schemes

It currently supports the following schemes:

| Country                             | eID Scheme                                                                                                     |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| :flag\_ao: **Angola**               | <ul><li>National ID</li></ul>                                                                                  |
| :flag\_be: **Belgium**              | <ul><li>itsme</li><li>eID</li></ul>                                                                            |
| 🇧🇷 **Brazil**                     | <ul><li>Cadastro de Pessoas Físicas (CPF)</li></ul>                                                            |
| 🇨🇿 **Czech Republic**             | <ul><li>BankID</li><li>mojeID</li></ul>                                                                        |
| :flag\_dk: **Denmark**              | <ul><li>MitID</li></ul>                                                                                        |
| :flag\_fi: **Finland**              | <ul><li>BankID</li></ul>                                                                                       |
| 🇫🇷 **France**                     | <ul><li>L’Identité Numérique</li></ul>                                                                         |
| :flag\_de: **Germany**              | <ul><li>Personalausweis</li><li>Verimi</li></ul>                                                               |
| 🇬🇭 **Ghana**                      | <ul><li>Ghana Card</li><li>Passport</li><li>Voter ID</li></ul>                                                 |
| 🇮🇹 **Italy**                      | <ul><li>Carta di Identità Elettronica (CIE)</li></ul>                                                          |
| :flag\_in: **India**                | <ul><li>Aadhaar</li></ul>                                                                                      |
| 🇨🇮 **Ivory Coast**                | <ul><li>National ID</li><li>Resident ID</li></ul>                                                              |
| 🇰🇪 **Kenya**                      | <ul><li>National ID</li><li>Passport</li><li>Alien Card</li></ul>                                              |
| :flag\_nl: **Netherlands**          | <ul><li>iDIN</li><li>Digidentity</li></ul>                                                                     |
| 🇳🇬 **Nigeria**                    | <ul><li>Bank Verification Number (BVN)</li><li>National Identification Number (NIN)</li><li>Voter ID</li></ul> |
| :flag\_no: **Norway**               | <ul><li>BankID</li><li>Buypass</li></ul>                                                                       |
| 🇸🇰 **Slovakia**                   | <ul><li>MobileID</li></ul>                                                                                     |
| **🇿🇦 South Africa**               | <ul><li>National ID</li><li>Refugee ID</li></ul>                                                               |
| :flag\_se: **Sweden**               | <ul><li>BankID</li><li>Freja eID</li></ul>                                                                     |
| 🇺🇬 **Uganda**                     | <ul><li>National ID</li></ul>                                                                                  |
| :flag\_ae: **United Arab Emirates** | <ul><li>UAE Pass</li></ul>                                                                                     |
| 🇿🇼 **Zimbabwe**                   | <ul><li>National ID</li></ul>                                                                                  |

### Analysis performed

ComplyCube’s eID checks validate all customer attributes supported by the scheme and securely **retrieve verified customer information** directly from the eID provider.

**Detailed verification checks**

<table><thead><tr><th width="204.9609375">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Identity Verification</strong></td><td><p>Depending on the eID provider, the verifiable attributes will include:</p><ol><li>Name</li><li>Date of birth (DOB)</li><li>Nationality</li><li>Gender</li><li>Address</li><li>Tax identification number (TIN)</li></ol></td></tr><tr><td><strong>Client Validation</strong></td><td>This ensures the submitted client info matches the information returned by the eID scheme.</td></tr></tbody></table>

### Sample result

The example below shows a representative eID Check result for verified identity attributes and validation outcomes.

Use it to see how returned identity data, provider responses, and verification findings may appear in an eID Check report.

<figure><img src="/files/qifBqlma84ydT1EJeWet" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by eID scheme, provider, workflow, configuration, and result.
{% endhint %}

### Check duration

An eID Check takes an average of **2 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is an eID Check?</summary>

An eID Check verifies a customer through a trusted **electronic identity scheme** such as **BankID**, **MitID**, **itsme**, or **UAE Pass**.

It uses the scheme’s own authentication flow to confirm the customer’s identity and return verified data.

</details>

<details>

<summary>Do customers need to upload an ID document for an eID Check?</summary>

No.

An eID Check relies on the customer authenticating with the selected eID scheme rather than uploading a physical identity document.

If you also need document authenticity checks or document image capture, add [Document Check](/documentation/product-guides/identity-verification/document-check).

</details>

<details>

<summary>Which identity data can an eID Check verify?</summary>

The verified data depends on the selected scheme.

It can include attributes such as **name**, **date of birth**, **nationality**, **gender**, **address**, and **tax identification number**.

</details>

<details>

<summary>How is eID Check different from Multi-Bureau Check?</summary>

An eID Check requires the customer to complete **live authentication** with the selected scheme.

[Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) verifies customer details against authoritative data sources without that live scheme login step.

</details>

<details>

<summary>Can I use eID Check inside a workflow?</summary>

Yes.

You can run eID Check inside [Workflows](/documentation/product-guides/compliance-studio/workflows) and combine it with checks such as [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), [Document Check](/documentation/product-guides/identity-verification/document-check), and [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check).

</details>

<details>

<summary>Can eID Check be used for Strong Customer Authentication?</summary>

Yes.

eID Check can support **Strong Customer Authentication (SCA)** and other high-assurance re-authentication flows for sensitive actions such as payouts or limit increases.

</details>

<details>

<summary>Which checks are commonly combined with eID Check in KYC?</summary>

eID Check is often combined with [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), and [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check).

This helps you move from scheme-based identity verification to a broader KYC and compliance decision in one [Workflow](/documentation/product-guides/compliance-studio/workflows).

</details>

### Related checks

Combine eID verification with other KYC and compliance checks:

* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media screening.
* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for biometric liveness verification.
* [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check) for document-based address verification.

### Related topics

Use these when configuring eID Checks in a broader onboarding journey:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate eID Checks alongside other checks.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent decision rules across workflow sessions.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to capture user details and eSignature before redirecting to an eID scheme.


# Multi-Bureau Check

Credit bureau and authoritative data checks for KYC identity verification and address verification.

### Multi-Bureau Check Overview

A Multi-Bureau Check is an **identity** and **address verification** service commonly used in KYC onboarding workflows.

ComplyCube matches customer details against multiple trusted and authoritative data sources to verify identity attributes and confirm address information.

Our extensive [service coverage](/documentation/product-guides/identity-verification/multi-bureau-check/service-coverage) enables businesses to verify customers across multiple supported countries and trusted data sources. These data sources include:

<table><thead><tr><th width="245.48046875">Data Source</th><th>Description</th></tr></thead><tbody><tr><td><strong>Credit Agencies</strong></td><td>Data provided by credit reference agencies.</td></tr><tr><td><strong>Government Authorities</strong></td><td>Official records from government authorities such as motor vehicle registries, electoral rolls, land and property registries, court filings, and other authoritative datasets.</td></tr><tr><td><strong>Utility Authorities</strong></td><td>Data from utility providers, including water, gas, electricity, and other service accounts.</td></tr><tr><td><strong>Postal Authorities</strong></td><td>Address and identity data provided by national and regional postal authorities.</td></tr><tr><td><strong>Telecom Agencies</strong></td><td>Data from mobile and landline telecom providers.</td></tr><tr><td><strong>Proprietary Databases</strong></td><td>Exclusive datasets curated and provided by trusted 3rd partners.</td></tr><tr><td><strong>Commercial Databases</strong></td><td>Private or commercial datasets where individuals have opted in and consented to share their details for verification purposes.</td></tr><tr><td><strong>Consumer Databases</strong></td><td>Opt-in consumer data, marketing databases, and other similar data sets.</td></tr><tr><td><strong>Other Sources</strong></td><td>Data collected from 3rd party providers that combine information from multiple sources into a single record.</td></tr></tbody></table>

{% hint style="info" %}
[Learn about the Multi-Bureau Checks API.](/documentation/api-reference/check-types/multi-bureau-check)
{% endhint %}

### Common use cases

Multi-Bureau Checks are typically used for:

* **No-document identity verification**: Validate customer identity without requiring an ID document upload.
* **Cross-source identity validation**: Match customer details against multiple trusted data providers to confirm consistency and accuracy.
* **Credit bureau identity checks**: Perform identity and address verification using credit bureau data where applicable.
* **Fraud risk reduction**: Identify discrepancies across authoritative sources that may indicate synthetic or stolen identities.

### How the check works

ComplyCube searches for a bureau record matching the submitted customer details.

It then verifies identity and address attributes across one or more sources.

You can use the results to support customer due diligence (CDD) decisions.

{% hint style="info" %}
This service includes a **2+2 check** variant that verifies at least two identity attributes with **two or more separate bureaus**. Get in touch with your Account Manager or [contact us](https://www.complycube.com/sales) to enable it.
{% endhint %}

### Analysis performed

ComplyCube verifies key customer details against multiple [trusted sources](#multi-bureau-check-overview). This improves confidence in the accuracy of identity and address data.

**Verifiable attributes** include:

1. Name
2. Date of birth (DOB)
3. Address
4. ID number (e.g. SSN, Social Insurance Number, National Identity Number, or Tax Number)

By default, customer details are considered verified when at least the **name** and **one additional attribute** match in a bureau record. This verification can occur in one of the following ways:

1. Name + DOB match
2. Name + Address match
3. Name + ID number match

{% hint style="info" %}
ComplyCube will attempt to match all attributes if possible: **name**, **address**, **DOB**, and **ID number**.
{% endhint %}

{% hint style="info" %}
Names are matched intelligently against source records using **spelling variations**, **initials**, and other **common name variants** to the fullest extent supported by the available data source.
{% endhint %}

### Sample result

The example below shows a representative Multi-Bureau Check result for identity and address verification outcomes.

Use it to see how matched attributes, source coverage, and verification findings may appear in a Multi-Bureau Check report.

<figure><img src="/files/-MlGPPAU3THsp8gqKHS7" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by country, data source, workflow, configuration, and result.
{% endhint %}

### Check duration

A Multi-Bureau Check takes **under 4 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is a Multi-Bureau Check?</summary>

A Multi-Bureau Check verifies a customer’s identity and address against multiple trusted data sources.

These sources can include credit agencies, government records, utility data, postal records, telecom data, and other authoritative datasets.

</details>

<details>

<summary>Can I verify identity without asking the customer to upload a document?</summary>

Yes.

Multi-Bureau Check supports **no-document identity verification** by matching customer details against trusted data sources.

If you also need document authenticity checks, add [Document Check](/documentation/product-guides/identity-verification/document-check).

</details>

<details>

<summary>How is Multi-Bureau Check different from eID Check?</summary>

Multi-Bureau Check verifies customer details against authoritative records and trusted data providers.

[eID Check](/documentation/product-guides/identity-verification/eid-check) requires the customer to complete live authentication with a supported eID scheme or identity provider.

</details>

<details>

<summary>What is a 2+2 check?</summary>

A **2+2 check** verifies at least **two identity attributes** against **two or more separate bureaus**.

This can provide stronger assurance for certain onboarding and compliance flows.

</details>

<details>

<summary>Can I use Multi-Bureau Check inside a workflow?</summary>

Yes.

You can run Multi-Bureau Check inside [Workflows](/documentation/product-guides/compliance-studio/workflows) and combine it with checks such as [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), and [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check).

</details>

<details>

<summary>Which checks are commonly combined with Multi-Bureau Check in KYC?</summary>

Multi-Bureau Check is often combined with [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check), [Compliance Policies](/documentation/product-guides/compliance-studio/policies), and [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check).

This helps you move from data-source verification to a broader KYC and compliance decision in one [Workflow](/documentation/product-guides/compliance-studio/workflows).

</details>

### Related checks

You’ll typically run Multi-Bureau Check alongside:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for liveness and selfie verification.
* [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check) for document-based address verification.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media.
* [SSN Check](/documentation/product-guides/identity-verification/ssn-check) for US-specific SSN validation.

### Related topics

Use these when configuring Multi-Bureau Checks in a broader onboarding journey:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate Multi-Bureau Check alongside other checks.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent decision rules across workflow sessions.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to capture customer information and declarations for compliance.


# Service coverage

Below is the [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) country coverage. For each country, you'll find a list of verifiable customer and address attributes.&#x20;

{% hint style="info" %}
Attributes marked with an asterisk (\*) are **required** for the check to run. All other attributes are ***optional***.
{% endhint %}

<table data-header-hidden="false" data-header-sticky data-full-width="false"><thead><tr><th width="221.984375">Country</th><th width="338.09765625">Client Attributes</th><th>Address Attributes</th></tr></thead><tbody><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e6-1f1f7">🇦🇷</span> Argentina</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e6-1f1fa">🇦🇺</span> Australia<br></td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong> </p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e6-1f1f9">🇦🇹</span> Austria</td><td><p><strong>Name*</strong></p><p><em>DOB</em></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e7-1f1ea">🇧🇪</span> Belgium</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e7-1f1f4">🇧🇴</span> Bolivia</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br><br>The So Identity Number corresponds to the <mark style="color:blue;">Cedula de Identidad (CI)</mark> number. This is expected in the following format: </p><p><em>56784321</em><br><em>(7 or 8 characters)</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e7-1f1f7">🇧🇷</span> Brazil</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong></p><p></p><p>The National Identity Number corresponds to either:</p><ul><li><mark style="color:blue;">Cadastro de Pessoas Físicas (CPF).</mark> This is expected in the following format: <em>000.000.000-00</em></li><li><mark style="color:blue;">Cadastro Nacional de Pessoas Jurídicas (CNPJ)</mark>. This is expected in the following format: <em>00.000.000/0001-00</em></li></ul></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e7-1f1ec">🇧🇬</span> Bulgaria</td><td><strong>Name*</strong></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1e6">🇨🇦</span> Canada</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><em>Social Insurance Number</em></p><p><em>Telephone</em> or <em>Mobile</em></p><p><br>The Social Insurance Number should be 9 digits (without dashes), as follows: <em>123456789</em></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1f1">🇨🇱</span> Chile</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><em>National Identity Number</em></p><p></p><p>The National Identity Number can correspond to the <mark style="color:blue;">Rol Único Tributario (RUT)</mark> or <mark style="color:blue;">Rol Único Nacional (RUN)</mark> numbers. This is expected in the following format:<br><em>XXXXXXXX-Z</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1f3">🇨🇳</span> China</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong></p><p></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Resident Identity Card</mark> number. This is expected in the following format: <em>RRRRRRYYYYMMDDSSSC</em> <br><em>(15 or 18 characters)</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1f4">🇨🇴</span> Colombia</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong></p><p></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Colombian Personal Identification Number</mark>. This is expected in the following formats:<br><em>2131234321</em> or <em>213.123.432-1</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1ff">🇨🇿</span> Czech Republic </td><td><strong>Name*</strong></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e9-1f1f0">🇩🇰</span> Denmark</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><em>National Identity Number</em></p><p></p><p>The National Identity Number corresponds to the <mark style="color:blue;">CPR</mark> number, which is expected in the following format:<br><em>DDMMYY-0000</em></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e9-1f1f4">🇩🇴</span> Dominican Republic</td><td><p><strong>Name*</strong></p><p><strong>National Identity Number*</strong></p><p></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Cédula de Identidad y Electoral (CIE)</mark> number, which is expected in the following format: <br><em>01234567891</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ea-1f1e8">🇪🇨</span> Ecuador</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Cédula de Identidad</mark> number. This is expected in the following format: <em>0123456789</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f8-1f1fb">🇸🇻</span> El Salvador</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Documento Unico de Identidad (DUI)</mark> number. This is expected in the following format: </p><p><em>12345679</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1eb-1f1ee">🇫🇮</span> Finland</td><td><strong>Name*</strong></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1eb-1f1f7">🇫🇷</span> France</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e9-1f1ea">🇩🇪</span> Germany</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ec-1f1ed">🇬🇭</span> Ghana</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Social Security and National Insurance Trust (SSNIT)</mark> number. This is expected in the following format: <em>C000000000000</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ec-1f1ee">🇬🇮</span> Gibraltar</td><td><strong>Name*</strong></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ec-1f1f7">🇬🇷</span> Greece</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ec-1f1f9">🇬🇹</span> Guatemala</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Codigo Unico de Identification (CUI)</mark> number. This is expected in the following format:<br><em>0000000000000</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ed-1f1f3">🇭🇳</span> Honduras</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Número de Identidad Nacional (NIN)</mark> number. This is expected in the following format:<br><em>0801198512345</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ed-1f1f0">🇭🇰</span> Hong Kong</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong></p><p></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Hong Kong ID (HKID)</mark> number. This is expected in the following format: <em>X123456(A)</em> <br><em>(10 or 11 characters)</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ed-1f1fa">🇭🇺</span> Hungary</td><td><strong>Name*</strong></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ee-1f1f9">🇮🇹</span> Italy</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><em>Social Insurance Number</em><br><br>The Social Insurance Number corresponds to <mark style="color:blue;">Codice Fiscale</mark>, which is expected in the following format:<br><em>SSSNNNYYMDDZZZZX</em></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ee-1f1e9">🇮🇩</span> Indonesia</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Nomor Induk Kependudukan (NIK)</mark>. This is expected in the following format:<br><em>XXXXXXDDMMYYXXXX</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ee-1f1f3">🇮🇳</span> India</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><em>Tax Identification Number</em><br><br>The Tax Identification Number corresponds to <mark style="color:blue;">Permanent Account Number (PAN)</mark>, which is expected in the following format:<br><em>AAAAA1234A</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ee-1f1ea">🇮🇪</span> Ireland</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ef-1f1f5">🇯🇵</span> Japan</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f0-1f1ea">🇰🇪</span> Kenya</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">National ID</mark> number. This is expected in the following format:<br><em>012345678</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f1-1f1f9">🇱🇹</span> Lithuania</td><td><strong>Name*</strong></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f1-1f1fa">🇱🇺</span> Luxembourg</td><td><strong>Name*</strong></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f2-1f1fe">🇲🇾</span> Malaysia</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">National Registration Identity Card (NRIC)</mark> number. This is expected in the following format:<br><em>YYMMDD-SS-123G</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f2-1f1fd">🇲🇽</span> Mexico</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br></p><p>The National Identity Number corresponds to either:</p><ul><li><mark style="color:blue;">Clave Única de Registro de Población (CURP)</mark>. This is expected in the following format:<br><em>HEGG560427MVZRRL05</em></li><li><mark style="color:blue;">Registro Federal de Contribuyentes (RFC)</mark>. This is expected in the following format:<br><em>XXXXXXXXXXXXX</em></li></ul></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f3-1f1f1">🇳🇱</span> Netherlands</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f3-1f1ff">🇳🇿</span> New Zealand</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f3-1f1ec">🇳🇬</span> Nigeria</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to either:</p><ul><li><mark style="color:blue;">National Identification Number (NIN)</mark>. This is expected in the following format:<br><em>XXXXXXXXXXX</em></li><li><mark style="color:blue;">Virtual National Identification Number (vNIN)</mark>. This is expected in the following format:<br><em>AAXXXXXXXXXXXXXX</em></li><li><mark style="color:blue;">Bank Verification Number (BVN)</mark>. This is expected in the following format (the 'BVN' prefix must be present):<br>BVN<em>XXXXXXXXXXX</em></li><li><mark style="color:blue;">Taxpayer Identification Number(BVN)</mark>. This is expected in the following format:<br><em>XXXXXXXX-XXXX</em></li></ul></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f3-1f1f4">🇳🇴</span> Norway</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f5-1f1e6">🇵🇦</span> Panama</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Cédula de Identidad Personal (CIP)</mark> number. This is expected in the following format:<br><em>8-123-4567</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f5-1f1fe">🇵🇾</span> Paraguay</td><td><strong>Name*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Cédula de Identidad Civil (CIC)</mark> number. This is expected in the following format:<br><em>4567891</em></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f5-1f1ea">🇵🇪</span> Peru</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Documento Nacional de Identidad (DNI)</mark> number. This is expected in the following format:<br><em>01234567</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f5-1f1ed">🇵🇭</span> Philippines</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><em>National Identity Number</em><br><br>The National Identity Number corresponds to the <mark style="color:blue;">PhilId Card Number (PCN)</mark> number. This is expected in the following format: <br><em>0123456789123456</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f5-1f1f1">🇵🇱</span> Poland</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><em>National Identity Number</em><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Polish Powszechny Elektroniczny System Ewidencji Ludnoc</mark> (<mark style="color:blue;">PESEL)</mark> number. This is expected in the following format:<br><em>YYMMDDZZZXQ</em></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f5-1f1f9">🇵🇹</span> Portugal</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f7-1f1f4">🇷🇴</span> Romania</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br>National Identity Number<br><br>The National Identity Number corresponds to the <mark style="color:blue;">Personal Numerical Code (CNP)</mark>. This is expected in the following format:<br><em>GYYMMDDZZSSSC</em></p></td><td><p>Property Number</p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p>Postal Code</p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f8-1f1ec">🇸🇬</span> Singapore</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p><p><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">National Registration Identity Card (NRIC)</mark>  number. This is expected in the following format: <br><em>LXXXXXXXX</em><br><br>Depending on the status of the holder, <em>L</em> can be "S", "T", "F", "G", or "M".</p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f8-1f1f0">🇸🇰</span> Slovakia</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ff-1f1e6">🇿🇦</span> South Africa</td><td><p><strong>Name*</strong></p><p><em>DOB</em></p><p><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">National ID</mark> number. This is expected in the following format: <br><em>YYMMDDSSSSCAZ</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ea-1f1f8">🇪🇸</span> Spain</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><em>National Identity Number</em><br></p><p>The National Identity Number corresponds to either:</p><ul><li><mark style="color:blue;">Documento Nacional de Identidad (DNI)</mark>. This is expected in the following format: <br><em>00000000-A</em></li><li><mark style="color:blue;">Número de Identidad de Extranjero (NIE)</mark>. This is expected in the following format: <br><em>X-0000000-A</em></li></ul></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f8-1f1ea">🇸🇪</span> Sweden</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Personal Identification Number (PIN)</mark> number. This is expected in the following format: <br><em>YYMMDD-NNGC</em></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e8-1f1ed">🇨🇭</span> Switzerland</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f9-1f1fc">🇹🇼</span> Taiwan</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f9-1f1ed">🇹🇭</span> Thailand</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Thai Identification Number</mark>. This is expected in the following format: <br><em>0-0000-0000-00-0</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p>State</p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1f9-1f1f7">🇹🇷</span> Türkiye</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Turkish Identification Number</mark>. This is expected in the following format: <br><em>11111111111</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1e6-1f1ea">🇦🇪</span> United Arab Emirates</td><td><strong>Name*</strong><br><strong>Nationality*</strong><br><strong>DOB*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Emirates ID</mark> number. This is expected in the following format: <br><em>784195625715172</em></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ec-1f1e7">🇬🇧</span> United Kingdom</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><strong>Property Number*</strong></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1fa-1f1f8">🇺🇸</span> United States</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br>SSN<br><br>The <mark style="color:blue;">Social Security Number (SSN)</mark> is expected in the following format: <br><em>123-45-6789</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><strong>State*</strong></p><p><strong>Postal Code*</strong></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1fa-1f1fe">🇺🇾</span> Uruguay</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong><br><strong>National Identity Number*</strong><br></p><p>The National Identity Number corresponds to the <mark style="color:blue;">Cédula de Identidad (CI)</mark> number. This is expected in the following format: <br><em>4123456-7</em></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1fb-1f1ea">🇻🇪</span> Venezuela</td><td><strong>Name*</strong><br><strong>National Identity Number*</strong><br><br>The National Identity Number corresponds to the <mark style="color:blue;">Cédula de Identidad (CI)</mark> number. This is expected in the following format:<br><em>V-12345678</em><br><br>Depending on the status of the holder, the first letter can be "V", "E", "J", "P", or "G".</td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1fb-1f1f3">🇻🇳</span> Vietnam</td><td><p><strong>Name*</strong></p><p><strong>DOB*</strong></p></td><td><p><em>Property Number</em></p><p><strong>Line*</strong></p><p><strong>City*</strong></p><p><em>State</em></p><p><em>Postal Code</em></p></td></tr></tbody></table>


# Driving License Check

Verify a driving license against issuing authorities (DMV, DVLA) and retrieve entitlement, status, and restriction data.

### Driving License Check Overview

Driving License Check is a **driving license / driver’s license verification** service.

It leverages ComplyCube’s integrations with **official issuing authorities** to validate a license number and retrieve **entitlements**, **restrictions**, and **infractions**.

This helps you prove a customer’s **right to drive** in KYC and onboarding flows.

{% hint style="info" %}
We recommend running this type of check through our [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or native [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide). These SDKs guide your customers through the capture process, aiding them with completing the flow successfully with minimal friction.
{% endhint %}

{% hint style="info" %}
[Learn about the Driving License Checks API.](/documentation/api-reference/check-types/driving-license-check)
{% endhint %}

### Common use cases

Typical use cases include:

* **Driver onboarding**: Verify driving licenses for ride-hailing and delivery platform applicants before activation.
* **Fleet and transport** **compliance**: Validate driver credentials to meet logistics, transport, and regulatory requirements.
* **Insurance underwriting and servicing**: Confirm license validity and driving entitlements during policy issuance and ongoing servicing.
* **Age and entitlement checks**: Verify driving eligibility and age requirements for services such as vehicle hire.

### Supported countries

Currently, this service supports licenses from the following issuing authorities:

<table><thead><tr><th width="204.515625">Country</th><th>Verification method</th></tr></thead><tbody><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1fa-1f1f8">🇺🇸</span> <strong>United States</strong></td><td>Verified against the official state <strong>Department of Motor Vehicles (DMV)</strong> records.</td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f1ec-1f1e7">🇬🇧</span> <strong>United Kingdom</strong></td><td>Verified against the <strong>Driver and Vehicle Licensing Agency (DVLA)</strong>.</td></tr></tbody></table>

### Analysis performed

The Driving License Check validates the authenticity of a driver’s license and ensures the details provided by the customer match those recorded with the issuing authority.

It also retrieves **driver information**, **entitlements**, and **restrictions**.

The diagram below outlines the key analysis categories.

***

<figure><img src="/files/jqIOm3RDY2u4k4BgWQzY" alt="Driving License Check analysis overview diagram"><figcaption><p><br>Driving License Check Overview</p></figcaption></figure>

***

**Detailed verification checks**

<table><thead><tr><th width="242.31640625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>License Verification</strong></td><td>Confirms the license exists and is valid with the issuing authority. Flags status issues, plus any available infractions or penalties.</td></tr><tr><td><strong>Consistency Analysis</strong></td><td>Compares the official driver records with the information provided by your customer to identify any mismatches or inconsistencies.</td></tr><tr><td><strong>Entitlements &#x26; Restrictions</strong></td><td>Retrieves driving entitlements (e.g. categories/classes) and highlights endorsements, restrictions, or disqualifications when available.</td></tr></tbody></table>

### Sample result

The example below shows a representative Driving License Check result for license validity, entitlement data, and verification outcomes.

Use it to see how driver details, licence status, and restriction findings may appear in a Driving License Check report.

<figure><img src="/files/ahw243Wn7KDRjErIoE5i" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by country, issuing authority, workflow, configuration, and result.
{% endhint %}

### Check duration

A Driving License Check takes an average of **2 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is the difference between a Driving License Check and a Document Check?</summary>

Driving License Check verifies a driving licence against **official issuing authority records**.

Use [Document Check](/documentation/product-guides/identity-verification/document-check) to verify the **physical licence card**, inspect it for fraud, and extract document data.

Many onboarding flows use both:

* **Driving License Check** for authority-backed licence status and entitlement data.
* **Document Check** for document authenticity and data extraction.

</details>

<details>

<summary>Can Driving License Check detect suspended, revoked, or restricted licences?</summary>

Yes, where supported by the issuing authority data.

Driving License Check confirms whether the licence is valid, flags status issues, and returns available restrictions, endorsements, disqualifications, infractions, or penalties.

</details>

<details>

<summary>Is Driving License Check enough for identity verification or KYC?</summary>

No.

Driving License Check helps prove a customer's **right to drive**. It is **not** an identity verification check.

For **identity verification** or **KYC**, combine it with:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for selfie liveness and face verification.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for identity and address corroboration.

</details>

<details>

<summary>Who uses Driving License Check?</summary>

Driving License Check is commonly used by businesses that must confirm driving eligibility before access, activation, or service delivery.

Typical users include:

* Ride-hailing, delivery, and logistics platforms.
* Fleet operators and transport businesses.
* Insurers and vehicle hire providers.

</details>

<details>

<summary>Can I use Driving License Check in a real-time onboarding flow?</summary>

Yes.

Driving License Check takes an average of **2 seconds**, which makes it suitable for real-time onboarding, driver activation, and eligibility decisions.

</details>

### Related checks

You’ll typically run Driving License Check alongside:

* [Document Check](/documentation/product-guides/identity-verification/document-check) to verify the physical driving licence card and extract ID data.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for selfie liveness and face verification.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for identity and address verification.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media screening.

### Related topics

Use these to run Driving License Check inside a broader onboarding flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate checks into a single customer journey.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent decision rules across journeys.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to collect customer details and declarations in the same flow.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to manage exceptions, tasks, and reviewer outcomes.


# Identity Fraud Check

UK identity fraud check for KYC. Verify name, date of birth, and address against authoritative sources and screen against fraud risk databases.

### Identity Fraud Check Overview

An Identity Fraud Check is a **UK identity verification** and **identity fraud detection** service.

It verifies a customer’s **name**, **date of birth (DOB)**, and **address** against UK authoritative sources. It then screens the same details against **fraud risk databases** to help identify suspicious patterns.

:flag\_gb: Currently, this service is available only for **UK data sources**.

{% hint style="info" %}
[Learn about the Identity Fraud Checks API.](/documentation/api-reference/check-types/identity-fraud-check)
{% endhint %}

### Common use cases

It is particularly relevant for:

* **Account opening and registration (UK KYC)**: Verify identity details before activating an account.
* **Lending and credit applications**: Reduce application fraud before credit decisioning.
* **Change of personal details**: Verify new name, DOB, or address (UK address verification) during profile updates.
* **Account recovery and re-verification**: Re-confirm identity before restoring access or reactivating accounts.

### Analysis performed

The Identity Fraud Check applies a two-layer verification process. It validates both the **authenticity of customer details** and the customer’s **fraud risk profile**.

**Detailed verification checks**

<table><thead><tr><th width="237.5234375">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Identity Verification</strong></td><td><p>Verifies the following customer details against UK authoritative sources:</p><ol><li>Name</li><li>Date of birth (DOB)</li><li>Address</li></ol></td></tr><tr><td><strong>Fraud Database Analysis</strong></td><td>Screens customer details against high-risk data sources such as fraud, police, mortality, and known fake profile databases.</td></tr></tbody></table>

### Sample result

The example below shows a representative Identity Fraud Check result for identity verification and fraud screening outcomes.

Use it to see how matched customer details, fraud indicators, and verification findings may appear in an Identity Fraud Check report.

<figure><img src="/files/w7PZ7CfTKqHK97PbNPJN" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by data source, workflow, configuration, and result.
{% endhint %}

### Check duration

An Identity Fraud Check takes an average of **2 seconds** to complete.

### Frequently asked questions

<details>

<summary>Is Identity Fraud Check available outside the UK?</summary>

No.

Identity Fraud Check currently supports **UK data sources only**.

</details>

<details>

<summary>Which customer details does Identity Fraud Check verify?</summary>

Identity Fraud Check verifies:

* Name
* Date of birth
* Address

It then screens the same details against fraud, police, mortality, and known fake profile databases.

</details>

<details>

<summary>How is Identity Fraud Check different from Multi-Bureau Check?</summary>

Identity Fraud Check is focused on **UK identity verification** plus **fraud database screening**.

[Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) focuses on identity and address verification across broader data sources and multiple supported countries.

</details>

<details>

<summary>Can I use Identity Fraud Check for account opening and account recovery?</summary>

Yes.

It is well suited for **account opening**, **lending applications**, **profile detail changes**, and **account recovery or re-verification** flows.

</details>

<details>

<summary>Can I use Identity Fraud Check inside a workflow?</summary>

Yes.

You can run Identity Fraud Check inside [Workflows](/documentation/product-guides/compliance-studio/workflows) and combine it with checks such as [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check), and [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check).

</details>

### Related checks

You’ll typically run Identity Fraud Check alongside:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for biometric liveness verification.
* [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check) to verify address evidence.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media screening.

### Related topics

Use these to run Identity Fraud Check inside a broader UK onboarding flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate checks into a single customer journey.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent decision rules across journeys.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to collect customer details and attestations in the same flow.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to manage exceptions, tasks, and reviewer outcomes.


# SSN Check

US Social Security Number (SSN) verification for KYC and CIP. Validate SSNs against authoritative records, confirm customer identity details, and reduce fraud risk.

### SSN Verification Overview

An SSN Check is a **US identity verification** service for **Social Security Number (SSN) verification**.

It validates the SSN against authoritative records and confirms it matches the customer’s submitted details.

Use it to reduce onboarding risk and strengthen **KYC**, **Customer Identification Program (CIP)**, and identity fraud controls for US customers.

:flag\_us: This service supports **US Social Security Number verification** only.

{% hint style="info" %}
[Learn about the SSN Check API (Social Security Number verification).](/documentation/api-reference/check-types/ssn-check)
{% endhint %}

### Common use cases <a href="#common-use-cases" id="common-use-cases"></a>

This service is commonly used in the following scenarios:

* **US customer onboarding**: Verify US customers during account opening and registration.
* **Fraud prevention**: Detect identity discrepancies and potential synthetic identities.
* **US KYC and CIP compliance**: Support Customer Identification Program requirements for regulated businesses.

### Analysis performed

The SSN Check confirms the **validity of the SSN** and the **authenticity of the customer details** provided.

**Detailed verification checks**

<table><thead><tr><th width="204.53515625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Data Verification</strong></td><td><p>Verifies the following customer details against authoritative US records:<br></p><ol><li>First name</li><li>Last name</li><li>SSN</li></ol></td></tr><tr><td><strong>Database Analysis</strong></td><td>Confirms that the SSN has been legitimately issued, is currently active, and is not associated with a deceased individual based on mortality data checks.</td></tr></tbody></table>

### Sample result

The example below shows a representative SSN Check result for SSN verification and customer data validation outcomes.

Use it to see how verified identity details, SSN status, and verification findings may appear in an SSN Check report.

<figure><img src="/files/5CT8ScHtAs8qmm5wMSOl" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by data source, workflow, configuration, and result.
{% endhint %}

### Check duration

An SSN Check takes an average of **1 second** to complete.

### Frequently asked questions

<details>

<summary>When should I use SSN Check?</summary>

Use SSN Check when you need to verify a US customer's Social Security Number against authoritative records.

It fits account opening, US KYC onboarding, CIP checks, and fraud reduction workflows.

</details>

<details>

<summary>What customer data does SSN Check verify?</summary>

SSN Check verifies:

* First name
* Last name
* Social Security Number (SSN)

It also checks whether the SSN has been legitimately issued, is active, and is not linked to a deceased individual.

</details>

<details>

<summary>Is SSN Check enough for KYC or CIP?</summary>

SSN Check supports US identity data validation.

For stronger identity verification, SSN Check is usually complemented by checks such as [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check), and [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), depending on your risk model and regulatory requirements.

</details>

<details>

<summary>Does SSN Check replace document verification?</summary>

No.

Use [Document Check](/documentation/product-guides/identity-verification/document-check) when you need government-issued ID verification and document fraud analysis.

</details>

<details>

<summary>Does SSN Check verify date of birth or address?</summary>

No.

SSN Check verifies the customer's first name, last name, and Social Security Number.

If you also need date of birth or address verification, use [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) or [eID Check](/documentation/product-guides/identity-verification/eid-check), depending on your workflow.

</details>

<details>

<summary>What is the difference between SSN Check and Multi-Bureau Check?</summary>

Use **SSN Check** when you need **US-specific Social Security Number verification**.

Use [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) when you need broader identity or address verification across multiple countries and data sources.

Many US onboarding flows use both:

* **SSN Check** for direct SSN validation.
* **Multi-Bureau Check** for broader identity and address corroboration.

</details>

### Related checks

You’ll typically run SSN Check alongside other identity verification methods, such as:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for biometric liveness verification.
* [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check) to extract and verify address evidence from documents.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) to screen customers against sanctions, PEP, and adverse media.

### Related topics

Use these to run SSN Check inside a broader KYC flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate checks into a single customer journey.
* [Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent decision rules across journeys.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to manage exceptions, tasks, and reviewer outcomes.


# Identity Check

Passive selfie liveness detection, deepfake detection, and face match for KYC identity verification. ISO-certified PAD Level 2 biometrics to prevent spoofing.

### Identity Check Overview

An Identity Check is a **biometric identity verification** service for **KYC onboarding**.

It combines **ISO-certified (PAD Level 2) passive liveness detection** with **facial similarity (face match)** to verify that a customer is the genuine person behind an identity.

It compares a live selfie against the photo on an official ID document and returns both a liveness outcome and facial similarity confidence score.

To protect your identity verification flow from spoofing, ComplyCube uses **Presentation Attack Detection (PAD)**. This helps detect common **liveness fraud** vectors, including:

* **Printed mask attacks**: Where masks with cut-outs are used to mimic real faces.
* **Printed photo attacks:** Where fraudsters use printed photos.
* **Image replay attacks:** Where injected images attempt to simulate liveness.
* **Deepfake attacks:** Where AI-generated or manipulated facial media attempts to impersonate a real person.
* **3D mask attacks**: Where silicone or plastic masks are used to impersonate individuals.

By combining face match with real-time liveness detection, Identity Check helps reduce onboarding fraud. It’s commonly used for **KYC identity verification**, **customer onboarding**, **transaction approvals**, and more

If you need higher assurance with video challenges, use [Enhanced Identity Check](/documentation/product-guides/biometric-and-liveness-verification/enhanced-identity-check).

{% hint style="info" %}
On a successful Identity Check, your customer’s facial biometrics will be **automatically enrolled** (if enabled on your plan). This helps prevent fraud related to multiple registrations under different identities and enables [face-based authentication](/documentation/product-guides/biometric-and-liveness-verification/face-authentication-check) for future interactions.
{% endhint %}

{% hint style="info" %}
Even though it is possible to run this check entirely through our API, we **highly recommend** that you run it through our [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or native [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide). These SDKs guide your clients through the capture process, aiding them with completing the flow successfully with minimal friction and false-positive outcomes.
{% endhint %}

{% hint style="info" %}
[Learn about the Identity Checks API.](/documentation/api-reference/check-types/identity-check)
{% endhint %}

### Analysis performed

An Identity Check runs layered **biometric analysis** to validate **passive liveness**, confirm **facial similarity**, and flag **spoofing**, **deepfake**, or **tampering** signals.

The diagram below outlines the key analysis categories.

***

![Identity Check Overview](/files/-MV1OAM6OklgKz5HbAmz)

***

**Detailed verification checks**

<table><thead><tr><th width="205.12890625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Face Analysis</strong></td><td><ul><li><strong>Facial similarity</strong>: Compares the submitted selfie with the ID photo to confirm both belong to the same person. Returns a confidence score between 0–100%, where 100% indicates a perfect match and 0% indicates no match at all.</li><li><strong>Banned faces analysis</strong>: Flags matches against prohibited or blacklisted face databases.</li><li><strong>Previously enrolled face</strong>: Detects if the same face has already been registered using different customer details.</li></ul></td></tr><tr><td><strong>Authenticity Analysis</strong></td><td><ul><li><strong>Spoofed image analysis</strong>: Indicates whether the images are manipulated, copied from the internet, or are known blacklisted images.</li><li><p><strong>Liveness check</strong>: Confirms the customer is physically present and not a spoof attempt. This involves advanced biometric and anti-spoofing techniques, such as:</p><ul><li>3D facial mapping</li><li>Skin texture and micro-expression analysis</li><li>Pixel-level tampering detection</li><li>Virtual camera detection</li><li>Mask and disguise recognition</li><li>Proprietary anti-spoofing techniques</li></ul><p>Returns a confidence score between 0–100%, where 100% indicates a highly reliable live presence and 0% indicates a likely spoof attempt.</p></li></ul></td></tr><tr><td><strong>Integrity Analysis</strong></td><td><ul><li><strong>Face detection</strong>: Ensures the expected number of faces are present in the image and that the image quality is sufficient for reliable analysis.</li></ul></td></tr></tbody></table>

### Sample result

The example below shows a representative Identity Check result for liveness detection and facial similarity outcomes.

Use it to see how selfie analysis, face match signals, and verification findings may appear in an Identity Check report.

<figure><img src="/files/DEXyBgLnhPYQSrs6KyC3" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

An Identity Check takes an average of **3 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is an Identity Check in KYC?</summary>

An Identity Check is a **biometric identity verification** step used in **KYC onboarding**.

It compares a **live selfie** to the photo on an official ID document and confirms both **liveness** and **face match**.

</details>

<details>

<summary>What is selfie identity verification?</summary>

Selfie identity verification is the process of checking whether a customer’s **live selfie** matches the photo on their identity document.

It helps confirm that the person completing onboarding is the real document holder.

</details>

<details>

<summary>What is passive liveness detection?</summary>

**Passive liveness detection** confirms that the customer is physically present during selfie capture without requiring video prompts or action challenges.

It analyzes the submitted selfie for spoofing, replay, mask, deepfake, and tampering signals in the background.

</details>

<details>

<summary>Can Identity Check detect deepfakes, spoofing, and selfie fraud?</summary>

Yes.

Identity Check is designed to detect **deepfakes**, **printed photo attacks**, **image replay attacks**, **3D mask attacks**, and other common **selfie fraud** vectors.

It uses **ISO-certified PAD Level 2** biometric anti-spoofing controls to reduce fraud risk.

</details>

<details>

<summary>Do I need an ID document and a selfie for Identity Check?</summary>

Yes.

Identity Check compares the customer’s live selfie against the photo from an official identity document.

If you only need document verification, use [Document Check](/documentation/product-guides/identity-verification/document-check).

</details>

<details>

<summary>What is the difference between Identity Check and Enhanced Identity Check?</summary>

Identity Check uses a **passive selfie** for fast biometric verification.

[Enhanced Identity Check](/documentation/product-guides/biometric-and-liveness-verification/enhanced-identity-check) uses a **video selfie** with guided motion and voice challenges for higher-assurance identity verification.

</details>

<details>

<summary>What is the difference between Identity Check and Face Authentication Check?</summary>

Identity Check compares a live selfie to an **ID document photo** during onboarding.

[Face Authentication Check](/documentation/product-guides/biometric-and-liveness-verification/face-authentication-check) compares a live selfie to a **previously enrolled face** for repeat login, step-up authentication, or account recovery.

</details>

<details>

<summary>Can Identity Check help prevent account takeover and duplicate accounts?</summary>

Yes.

Identity Check helps detect spoofing and can also identify **previously enrolled faces** when enabled, which helps reduce duplicate registrations and related fraud.

</details>

<details>

<summary>Which checks are commonly combined with Identity Check in KYC?</summary>

Identity Check is often combined with [Document Check](/documentation/product-guides/identity-verification/document-check), [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check), and [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check).

This helps you move from selfie and face match verification to a broader KYC and compliance decision in one [Workflow](/documentation/product-guides/compliance-studio/workflows).

</details>

<details>

<summary>Is ComplyCube certified to the same anti-spoofing standards as iBeta-tested solutions?</summary>

Yes, ComplyCube is certified to **ISO/IEC 30107-3 PAD Level 2** and achieved certified results that **significantly exceeded** the standard’s required performance thresholds.

PAD Level 2 is the internationally recognized standard for biometric liveness and anti-spoofing performance. The certification validates resistance to sophisticated presentation attacks and requires solutions to meet strict performance thresholds, including a **False Acceptance Rate (FAR) of 0.2% or lower** and a **False Rejection Rate (FRR) of 5% or lower**.

For customers evaluating liveness providers, the certification level achieved is the most meaningful measure of anti-spoofing performance and assurance, providing independently verified protection against sophisticated spoofing attacks.

</details>

### Related checks

You’ll typically run an Identity Check alongside:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for document authenticity and ID data extraction.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media screening.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for identity and address verification via authoritative sources.
* [Face Authentication Check](/documentation/product-guides/biometric-and-liveness-verification/face-authentication-check) for step-up and repeat authentication after enrollment.

### Related topics

Use these when building end-to-end KYC journeys that include Identity Check:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to bundle Identity Check into a single customer journey.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply rule-based decisions and evidence requirements.
* [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), and [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide) for guided selfie capture.


# Enhanced Identity Check

Active video selfie liveness detection with motion and voice challenges, plus face match, for high-assurance KYC identity verification (ISO-certified PAD Level 2).

### Enhanced Identity Check Overview

An Enhanced Identity Check is a high-assurance **biometric identity verification** service. Use it for **KYC onboarding** and **video-based identity verification (video KYC)**.

It combines **ISO-certified (PAD Level 2) active liveness detection** with **facial similarity (face match)**. It analyzes a **video selfie** with guided motion and voice challenges. It then compares the video face to the photo on an official ID document.

This service uses **Presentation Attack Detection (PAD)** to reduce **liveness fraud**. This helps detect advanced spoofing vectors, including:

* **Printed mask attacks**: Where masks with cut-outs are used to mimic real faces.
* **Printed photo attacks:** Where fraudsters use printed photos.
* **Video replay attacks:** Where pre-recorded or virtual videos attempt to simulate liveness.
* **Deepfake attacks:** Where AI-generated or manipulated facial media attempts to impersonate a real person.
* **3D mask attacks**: Where silicone or plastic masks are used to impersonate individuals.

In some jurisdictions, **video-based identity verification** is a regulatory requirement. This check supports those requirements with guided challenges.

If you don’t need video challenges, use [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check).

{% hint style="info" %}
On a successful Enhanced Identity Check, your customer’s facial biometrics will be **automatically enrolled** (if enabled on your plan). This helps prevent fraud related to multiple registrations under different identities and enables [face-based authentication](/documentation/product-guides/biometric-and-liveness-verification/face-authentication-check) for future interactions.
{% endhint %}

{% hint style="info" %}
This check can only be performed through our [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide).
{% endhint %}

{% hint style="info" %}
[Learn about the Enhanced Identity Checks API.](/documentation/api-reference/check-types/enhanced-identity-check)
{% endhint %}

### Analysis performed

The Enhanced Identity Check performs multiple layers of **biometric analysis** to validate **active liveness** and **facial similarity.** It also flags **spoofing**, **deepfake**, and **tampering** signals.

The diagram below outlines the key analysis categories.

***

![Enhanced Identity Check Overview](/files/-MV1OtGlT129jtltlosD)

***

**Detailed verification checks**

<table><thead><tr><th width="205.12890625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Face Analysis</strong></td><td><ul><li><strong>Facial similarity</strong>: Compares the submitted video with the ID photo to confirm both belong to the same person. Returns a confidence score between 0–100%, where 100% indicates a perfect match and 0% indicates no match at all.</li><li><strong>Previously enrolled face</strong>: Detects if the same face has already been registered using different customer details.</li></ul></td></tr><tr><td><strong>Authenticity Analysis</strong></td><td><ul><li><strong>Spoofed image analysis</strong>: Indicates whether the images are manipulated, copied from the internet, or are known blacklisted images.</li><li><p><strong>Liveness check</strong>: Confirms the customer is physically present and not a spoof attempt. This involves advanced biometric and anti-spoofing techniques, such as:</p><ul><li>3D facial mapping</li><li>Skin texture and micro-expression analysis</li><li>Pixel-level tampering detection</li><li>Virtual camera detection</li><li>Mask and disguise recognition</li><li>Proprietary anti-spoofing techniques</li></ul><p>Returns a confidence score between 0–100%, where 100% indicates a highly reliable live presence and 0% indicates a likely spoof attempt.</p></li><li><strong>Voice challenge analysis</strong>: Indicates if the customer has successfully completed the voice challenge.</li><li><strong>Action challenge analysis</strong>: Indicates if the customer has successfully completed the action challenge.</li></ul></td></tr><tr><td><strong>Integrity Analysis</strong></td><td><ul><li><strong>Face detection</strong>: Ensures the expected number of faces are present in the video and that the image quality is sufficient for reliable analysis.</li></ul></td></tr></tbody></table>

### Check duration

An Enhanced Identity Check takes an average of **20 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is an Enhanced Identity Check in KYC?</summary>

An Enhanced Identity Check is a **high-assurance biometric identity verification** step used in **KYC onboarding**.

It compares a **video selfie** to the photo on an official ID document and confirms both **active liveness** and **face match**.

</details>

<details>

<summary>What is video KYC?</summary>

**Video KYC** is a form of identity verification that uses a **video selfie** to confirm a customer is physically present and matches their identity document.

It is commonly used when regulators or risk models require stronger identity assurance than a static selfie.

</details>

<details>

<summary>What is active liveness detection?</summary>

**Active liveness detection** confirms that the customer is physically present by asking them to complete guided challenges during capture.

These can include **motion** and **voice** prompts, which help detect spoofing, replay attacks, and other advanced fraud attempts.

ComplyCube is certified to **ISO PAD Level 2**, the highest certification level for this type of liveness check.

</details>

<details>

<summary>Can Enhanced Identity Check detect deepfakes, spoofing, and video replay attacks?</summary>

Yes.

Enhanced Identity Check is designed to detect **deepfakes**, **video replay attacks**, **printed photo attacks**, **3D mask attacks**, and other advanced **liveness fraud** vectors.

It uses **ISO-certified PAD Level 2** biometric anti-spoofing controls to reduce fraud risk.

</details>

<details>

<summary>When should I use Enhanced Identity Check instead of Identity Check?</summary>

Use Enhanced Identity Check when you need **higher-assurance identity verification**, **video-based onboarding**, or guided liveness challenges.

Use [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) when a faster **passive selfie** check is enough for your risk and compliance requirements.

</details>

<details>

<summary>Do I need an ID document and a video selfie for Enhanced Identity Check?</summary>

Yes.

Enhanced Identity Check compares the customer’s **video selfie** against the photo from an official identity document.

If you only need document verification, use [Document Check](/documentation/product-guides/identity-verification/document-check).

</details>

<details>

<summary>Can Enhanced Identity Check help meet regulated video verification requirements?</summary>

Yes.

Enhanced Identity Check is well suited to jurisdictions and use cases that require **video-based identity verification** or stronger proof of live customer presence.

</details>

<details>

<summary>Can Enhanced Identity Check help prevent account takeover and duplicate accounts?</summary>

Yes.

Enhanced Identity Check helps detect spoofing and can also identify **previously enrolled faces** when enabled, which helps reduce duplicate registrations and related fraud.

</details>

<details>

<summary>Which checks are commonly combined with Enhanced Identity Check in KYC?</summary>

Enhanced Identity Check is often combined with [Document Check](/documentation/product-guides/identity-verification/document-check), [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check), [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check), and [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check).

This helps you move from video liveness and face match verification to a broader KYC and compliance decision in one [Workflow](/documentation/product-guides/compliance-studio/workflows).

</details>

<details>

<summary>Is ComplyCube PAD Level 2 certified?</summary>

Yes.&#x20;

ComplyCube is certified to **ISO/IEC 30107-3 PAD Level 2**, the internationally recognized standard for biometric liveness and anti-spoofing performance, and achieved results that **exceeded the standard’s stringent requirements by a significant margin**.

PAD Level 2 certification validates a solution’s ability to detect sophisticated presentation attacks, including spoofing attempts using photos, videos, masks, and other attack instruments. It also requires rigorous testing across security and usability metrics to ensure effective fraud prevention without compromising the user experience.

For organizations evaluating liveness providers, PAD Level 2 certification provides independent, standards-based assurance that a solution has been rigorously tested and proven effective against real-world biometric spoofing attacks.

</details>

### Related checks

You’ll typically run Enhanced Identity Check alongside:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document authenticity and data extraction.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media screening.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for authoritative identity and address verification.
* [Face Authentication Check](/documentation/product-guides/biometric-and-liveness-verification/face-authentication-check) for step-up and repeat authentication after enrollment.

### Related topics

Use these when building end-to-end KYC journeys that include video-based identity verification:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to bundle checks into a single customer journey.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply rule-based decisions and evidence requirements.
* [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), and [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide) for guided video selfie capture.


# Age Estimation Check

Selfie-based biometric age estimation and liveness detection for age-gating, using our ACCS 2:2021-certified age estimation technology.

### Age Estimation Check Overview

The Age Estimation Check uses **liveness detection** and **facial analysis** to estimate a customer’s age from a selfie.

It uses **our ACCS 2:2021-certified age estimation technology** for high-confidence **biometric age estimation**.

It’s built for **age assurance**, **age verification**, and **age-gating** flows. It requires only a selfie, with no document capture.

{% hint style="info" %}
We recommend running this type of check through our [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or native [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide). These SDKs guide your customers through the capture process, aiding them with completing the flow successfully with minimal friction.
{% endhint %}

{% hint style="info" %}
[Learn about the Age Estimation Checks API.](/documentation/api-reference/check-types/age-estimation-check)
{% endhint %}

### Common use cases

Use Age Estimation when you need a fast, low-friction **age check**:

* **Youth safety enforcement**: Apply age threshold validation to protect minors and support platform safety controls.
* **Access control for age-restricted services**: Confirm age before granting access to restricted content, platforms, or communities.
* **Age-gating for restricted products**: Verify age eligibility for regulated goods.
* **Gaming onboarding**: Validate age requirements during registration for gaming and related services.

### Analysis performed

The Age Estimation Check applies biometric analysis to confirm **live presence** (anti-spoofing) and generate a **selfie-based age estimation**.

The diagram below outlines the key analysis categories.

***

<figure><img src="/files/o4IUdw9D2gF0NI1tH5mi" alt="Age estimation and liveness detection overview for selfie-based age verification"><figcaption><p>Age Estimation Check Overview</p></figcaption></figure>

***

**Detailed verification checks**

<table><thead><tr><th width="205.34375">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Authenticity Analysis</strong></td><td>Performs a liveness check (Presentation Attack Detection / anti-spoofing) to confirm the customer is physically present and not spoofed via photo, video, or deepfake.</td></tr><tr><td><strong>Age Estimation</strong></td><td>Provides an estimated age (e.g., 25 years) and range prediction (e.g., 20–28 years).</td></tr><tr><td><strong>Age Validation</strong></td><td>Confirms whether the customer’s estimated age meets the required age threshold.</td></tr><tr><td><strong>Liveness Scoring</strong></td><td>Returns a confidence score between 0–100%, where 100% indicates a highly reliable live presence and 0% indicates a likely spoof attempt.</td></tr></tbody></table>

### Sample result

The example below shows a representative Age Estimation Check result for age estimation, threshold validation, and liveness outcomes.

Use it to see how estimated age, age-band signals, and verification findings may appear in an Age Estimation Check report.

<figure><img src="/files/kFQ0PW2441KUR807FyoK" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

An Age Estimation Check takes an average of **4 seconds** to complete.

### Frequently asked questions

<details>

<summary>Can I estimate a customer’s age with a selfie only?</summary>

Yes.

Age Estimation Check works with a **selfie only**, so customers do not need to upload an identity document.

It uses **our ACCS 2:2021-certified age estimation technology** to estimate whether the customer is above or below an age threshold. It does not verify an exact age or **date of birth**.

</details>

<details>

<summary>What is the difference between age estimation and document-based age verification?</summary>

Age estimation uses **facial analysis** to estimate whether a customer is above or below an age threshold.

Document-based age verification uses an official ID document to confirm the customer’s exact **date of birth**.

</details>

<details>

<summary>Can Age Estimation Check detect spoofing or fake selfie attempts?</summary>

Yes.

Age Estimation Check includes **liveness detection** to help detect spoofing attempts such as photos, video replays, and other fake selfie submissions.

</details>

<details>

<summary>What happens if the estimated age is close to the threshold?</summary>

You can use Age Estimation Check as a first-pass age gate, then step up to [Document Check](/documentation/product-guides/identity-verification/document-check) when the result is borderline or more assurance is required.

This helps balance **conversion**, **safety**, and **compliance**.

</details>

<details>

<summary>Which industries use selfie-based age estimation?</summary>

Age Estimation Check is commonly used for **gaming**, **online communities**, **age-restricted goods**, and other digital services that need a fast age gate.

</details>

### Related checks

You’ll typically run Age Estimation Check alongside:

* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for a data-based authoritative identity and address verification.
* [SMS Verification](/documentation/product-guides/kyc-automation-services/sms-verification) for OTP-based mobile number verification.
* [Face Authentication Check](/documentation/product-guides/biometric-and-liveness-verification/face-authentication-check) for passwordless authentication using enrolled biometrics.
* [Document Check](/documentation/product-guides/identity-verification/document-check) when age estimation falls below a defined threshold and documentary proof (e.g. date of birth on an ID) is required.

### Related topics

Use these docs when you’re designing the end-to-end journey:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate age-gating with follow-up checks and decisions.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to capture declarations (for example, DOB and consent) alongside the selfie.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check), [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check), and [Mobile Intelligence](/documentation/product-guides/digital-fraud-intelligence/mobile-intelligence-check) to add digital fraud signals to your age-gating flow.


# Face Authentication Check

Facial biometric authentication for passwordless login and account recovery.

### Face Authentication Check Overview

The Face Authentication Check is a **facial biometric authentication** service.

It uses our **face match** and **liveness** engine to authenticate your customer's facial attributes against their **enrolled face**.

{% hint style="info" %}
This type of check requires a customer's face to be **enrolled** first.
{% endhint %}

{% hint style="info" %}
We recommend running this type of check through our [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or native [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide).
{% endhint %}

{% hint style="info" %}
[Learn about the Face Authentication Checks API.](/documentation/api-reference/check-types/face-authentication-check)
{% endhint %}

### Common use cases

Use Face Authentication when you need fast **biometric customer authentication**:

* **Passwordless login**: Replace passwords with selfie-based face authentication.
* **Account recovery**: Re-authenticate users for **account reactivation** and **unlock** flows.
* **Step-up authentication**: Add a biometric challenge for high-risk actions.
* **Periodic KYC re-verification**: Confirm the same user returns over time.

### Analysis performed

The Face Authentication Check confirms whether a customer’s **live face** matches their previously **enrolled face**.

The diagram below outlines the key analysis categories.

***

![Face Authentication Overview: Selfie-based Biometric Matching and Liveness Scoring](/files/rLDsJeCn9s9UUPn3mFFw)

***

**Detailed verification checks**

<table><thead><tr><th width="208.7734375">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Face authentication</strong></td><td>Determines whether the live selfie matches the enrolled face.</td></tr><tr><td><strong>Liveness scoring</strong></td><td>Returns a confidence score between 0–100%. 100% indicates a highly reliable live presence. 0% indicates a likely spoof attempt.</td></tr></tbody></table>

### Check duration

A Face Authentication Check takes an average of **2 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is the difference between Face Authentication Check and Identity Check?</summary>

Face Authentication Check compares a live selfie to a **previously enrolled face**.

[Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) compares a live selfie to an **ID document photo** during onboarding.

</details>

<details>

<summary>Do I need to enroll the customer’s face first?</summary>

Yes.

Face Authentication Check requires the customer’s face to be **enrolled** before authentication can take place.

</details>

<details>

<summary>Can Face Authentication Check detect spoofing or fake selfie attempts?</summary>

Yes.

Face Authentication Check includes **liveness scoring** to help detect spoofing attempts and confirm the customer is physically present during capture.

</details>

<details>

<summary>Can Face Authentication Check help prevent account takeover?</summary>

Yes.

It helps reduce **account takeover** risk by confirming that the person attempting access matches the enrolled biometric identity.

</details>

### Related checks

You’ll typically run Face Authentication Check alongside:

* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) runs selfie liveness and face match against an ID photo. It can also enroll the face.
* [Enhanced Identity Check](/documentation/product-guides/biometric-and-liveness-verification/enhanced-identity-check) when you need video challenges for higher assurance.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) to add device-level fraud signals to authentication flows.

### Related topics

Use these docs when designing end-to-end onboarding and authentication journeys:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate step-up authentication and follow-up decisions.
* [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), and [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide) for guided selfie capture.


# Device Intelligence

Detect fraud risk using device fingerprinting, tamper signals, and network indicators (VPN, emulator, root/jailbreak).

### Device Intelligence Overview

The Device Intelligence check uses **device fingerprinting** and **device risk signals** to detect fraud. It inspects the device and network connection to identify tampering, automation, and suspicious behavior.

This service helps ensure that only **trusted and genuine devices** are used during customer onboarding.

It supports a range of device types, including:

* Mobile phones
* Tablets
* Laptops and desktop PCs
* Kiosks and POS terminals

{% hint style="info" %}
[Learn about the Device Intelligence Checks API.](/documentation/api-reference/check-types/device-intelligence-check)
{% endhint %}

### Common use cases

Use Device Intelligence to reduce fraud across key customer journeys:

* **KYC onboarding and account opening**: Spot high-risk devices early in your [Workflows](/documentation/product-guides/compliance-studio/workflows).
* **Account takeover (ATO)**: Detect unusual device fingerprints and network changes.
* **Bot protection**: Identify automated sessions and scripted sign-ups.
* **Promo and referral abuse**: Flag device reuse across multiple accounts.

### Analysis performed

The check performs device, network, and bot risk assessments. It also tracks signals over time to identify repeat fraud patterns.

**Detailed verification checks**

<table><thead><tr><th width="204.53515625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Device Analysis</strong></td><td><ul><li><strong>Previously enrolled device</strong>: Flags devices reused across multiple customer accounts.</li><li><strong>Emulator detection</strong>: Flags attempts to use virtualized or emulated devices.</li><li><strong>Rooted/Jailbroken device</strong>: Detects compromised operating systems with escalated privileges.</li><li><strong>Cloned app</strong>: Identifies duplicate or cloned versions of applications.</li><li><strong>Browser tampering</strong>: Detects altered or suspicious browser setups.</li><li><strong>Virtual machine</strong>: Flags devices running inside virtual environments.</li><li><strong>Location spoofing</strong>: Detects falsified or masked geolocation signals.</li><li><strong>Frida detection</strong>: Detects mobile debugging and manipulation frameworks.</li></ul></td></tr><tr><td><strong>Network Analysis</strong></td><td><ul><li><strong>VPN detection</strong>: Identifies usage of Virtual Private Networks.</li><li><strong>Relay detection</strong>: Detects relay service providers.</li></ul></td></tr><tr><td><strong>Bot Analysis</strong></td><td><ul><li><strong>Bot detection</strong>: Detects whether sessions are automated or bot-driven.</li></ul></td></tr><tr><td><strong>Timeline Analysis</strong></td><td><ul><li><strong>Device timeline analysis</strong>: Monitors device behavior patterns across sessions.</li><li><strong>Network timeline analysis</strong>: Tracks network usage over time to spot anomalies.</li></ul></td></tr></tbody></table>

### Sample result

The example below shows a representative Device Intelligence result for device, network, and bot risk outcomes.

Use it to see how device signals, fraud indicators, and verification findings may appear in a Device Intelligence report.

<figure><img src="/files/Qkc8M73J3zgdUuTanudC" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

A Device Intelligence Check takes an average of **2 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is Device Intelligence in fraud prevention?</summary>

Device Intelligence uses **device fingerprinting** and **risk signals** to detect suspicious devices, networks, and sessions.

It helps identify fraud before or during onboarding.

</details>

<details>

<summary>What does device fingerprinting detect?</summary>

Device fingerprinting helps identify whether a device has been seen before and whether it shows signs of tampering or abuse.

It can surface patterns linked to repeated fraud, multi-accounting, and suspicious session behavior.

</details>

<details>

<summary>What fraud signals can Device Intelligence detect, such as VPNs, emulators, and rooted devices?</summary>

Yes.

Device Intelligence can detect signals such as **VPN usage**, **emulators**, **virtual machines**, **rooted or jailbroken devices**, **browser tampering**, and **location spoofing**.

</details>

<details>

<summary>Can Device Intelligence help prevent multi-account abuse?</summary>

Yes.

It helps flag **device reuse**, suspicious device changes, bot activity, and other signals linked to **account takeover**, **promo abuse**, and **duplicate accounts**.

</details>

<details>

<summary>Should I combine Device Intelligence with Email Intelligence and Mobile Intelligence checks?</summary>

Yes.

Device Intelligence works well with [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check) and [Mobile Intelligence](/documentation/product-guides/digital-fraud-intelligence/mobile-intelligence-check) when you want to assess **device**, **email**, and **phone number** risk together.

You can also combine them with checks such as [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), and [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for broader fraud and compliance coverage.

</details>

### Related checks

Combine Device Intelligence with other fraud intelligence signals:

* [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check) for email reputation and threat signals, including disposable email detection and breach exposure.
* [Mobile Intelligence](/documentation/product-guides/digital-fraud-intelligence/mobile-intelligence-check) for phone number risk scoring and reputation signals.

### Related topics <a href="#related-topics" id="related-topics"></a>

Use these to run Device Intelligence Check inside a broader KYC orchestration and decisioning:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate verification checks into a unified customer journey.
* [Policies](/documentation/product-guides/compliance-studio/policies) to enforce consistent decision logic across different journeys.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to handle exceptions, assign tasks, and manage reviewer decisions.


# Email Intelligence

Email fraud detection and risk scoring. Verify email reputation, detect disposable emails, and check breach exposure for KYC onboarding.

### Email Intelligence Overview

Email Intelligence is an **email fraud detection** check. It scores the fraud risk of a customer’s email address using reputation and threat signals.

Use it to reduce sign-up abuse and improve **KYC onboarding** quality. It also helps stop customers using disposable or breached email addresses.

{% hint style="info" %}
[Learn about the Email Intelligence Checks API.](/documentation/api-reference/check-types/email-intelligence-check)
{% endhint %}

### Common use cases

Use Email Intelligence anywhere an email address is a key identifier:

* **KYC onboarding and account opening**: Flag high-risk emails before running identity checks.
* **Email OTP and inbox ownership flows**: Treat high-risk emails as a step-up signal alongside [Email Verification](/documentation/product-guides/kyc-automation-services/email-verification).
* **New account and sign-up fraud**: Stop disposable emails and mass-created accounts.
* **Account takeover (ATO)**: Treat sudden email changes or risky emails as a step-up signal.
* **Promo and referral abuse**: Detect disposable email reuse across promotions.

### Analysis performed

The check runs an **email verification** and **email reputation** assessment. It combines multiple indicators to produce an overall fraud risk score.

**Detailed verification checks**

<table><thead><tr><th width="204.53515625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Risk Analysis</strong></td><td><ul><li><strong>Risk level analysis</strong>: Assigns a fraud risk score based on patterns linked to suspicious or malicious activity.</li><li><strong>Data leak analysis</strong>: Checks whether the email has appeared in known data breaches or leak databases.</li><li><strong>Disposable email</strong>: Detects if the email is temporary or from a disposable email provider.</li><li><strong>Format analysis</strong>: Confirms the email address is syntactically valid and follows correct formatting standards.</li><li><strong>Domain validity</strong>: Verifies that the domain exists and is active.</li></ul></td></tr></tbody></table>

### Sample result

The example below shows a representative Email Intelligence result for email risk, breach exposure, and domain validation outcomes.

Use it to see how fraud signals, reputation findings, and verification results may appear in an Email Intelligence report.

<figure><img src="/files/pLSFC1AdwifWQZ1GNVqC" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

An Email Intelligence Check takes an average of **2 seconds** to complete.

### Frequently asked questions

<details>

<summary>Can Email Intelligence detect disposable email addresses?</summary>

Yes.

Email Intelligence can detect whether an email address belongs to a **disposable email provider**, which helps reduce fake sign-ups and abuse.

</details>

<details>

<summary>Can Email Intelligence check if an email appears in a data breach?</summary>

Yes.

It checks whether the email address has appeared in known **data breaches** or **leak databases**.

</details>

<details>

<summary>Does Email Intelligence verify email ownership?</summary>

No.

Email Intelligence assesses **risk** and **reputation**. It does not prove that the customer controls the inbox.

Use [Email Verification](/documentation/product-guides/kyc-automation-services/email-verification) when you need to confirm inbox ownership with an OTP.

</details>

<details>

<summary>Can Email Intelligence help reduce sign-up fraud?</summary>

Yes.

It helps detect risky email patterns linked to **sign-up fraud**, **mass account creation**, and potential **account takeover** scenarios.

</details>

<details>

<summary>Should I combine Email Intelligence with other fraud checks?</summary>

Yes.

Email Intelligence works well with [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check), [Mobile Intelligence](/documentation/product-guides/digital-fraud-intelligence/mobile-intelligence-check), and identity verification checks when you need stronger onboarding controls.

</details>

### Related checks

Combine Email Intelligence with other fraud intelligence signals:

* [Email Verification](/documentation/product-guides/kyc-automation-services/email-verification) for OTP-based email ownership verification.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) for session-level device and network risk signals, including VPN/proxy usage, emulators, rooted/jailbroken devices, and automation.
* [Mobile Intelligence](/documentation/product-guides/digital-fraud-intelligence/mobile-intelligence-check) for phone number risk scoring and reputation signals.

### Related topics <a href="#related-topics" id="related-topics"></a>

Use these to integrate Email Intelligence within a broader KYC and fraud decision flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate Email Intelligence as a step in onboarding.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent rules using the returned risk signals.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to review edge cases and keep audit-ready decisions.


# Mobile Intelligence

Phone number fraud detection and risk scoring. Verify mobile number reputation, activity, and abuse signals to reduce KYC onboarding fraud.

### Mobile Intelligence Overview

Mobile Intelligence is a **phone number fraud detection** check. It analyzes a customer’s **mobile number** to assess risk using mobile network and reputation signals.

Use it to identify high-risk phone numbers early, reduce onboarding fraud, and strengthen KYC flows with **mobile number verification**.

{% hint style="info" %}
[Learn about the Mobile Intelligence Checks API.](/documentation/api-reference/check-types/mobile-intelligence-check)
{% endhint %}

### Common use cases

Use Mobile Intelligence anywhere the phone number is a core identifier:

* **KYC onboarding and account opening**: Flag risky phone numbers when running identity checks.
* **SMS OTP and phone ownership flows**: Treat high-risk numbers as a step-up signal alongside [SMS Verification](/documentation/product-guides/kyc-automation-services/sms-verification).
* **Account takeover (ATO)**: Detect suspicious phone number changes and low-trust numbers.
* **Promo and referral abuse**: Spot reused or abusive numbers across sign-ups.

### Analysis performed

The check combines **phone number verification** and reputation signals to produce an overall **mobile number fraud risk score**.

**Detailed verification checks**

<table><thead><tr><th width="204.53515625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Risk Analysis</strong></td><td><ul><li><strong>Valid format</strong>: Confirms that the mobile number follows correct international and regional formatting rules.</li><li><strong>Recent abuse</strong>: Flags whether the number has been associated with recent fraudulent or abusive activity.</li><li><strong>Activity</strong>: Assesses the number’s usage history to check if it is active or dormant.</li><li><strong>Digital number analysis</strong>: Examines deeper digital risk signals such as carrier type and number reputation.</li><li><strong>Risk level analysis</strong>: Generates a fraud risk score (0–100) indicating the overall likelihood of the number being compromised or fraudulent.</li></ul></td></tr></tbody></table>

### Sample result

The example below shows a representative Mobile Intelligence result for phone number risk, activity, and abuse outcomes.

Use it to see how reputation signals, fraud indicators, and verification findings may appear in a Mobile Intelligence report.

<figure><img src="/files/9pXRoRMG3yt7evKsa4MI" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

A Mobile Intelligence Check takes an average of **2 seconds** to complete.

### Frequently asked questions

<details>

<summary>What is Mobile Intelligence in fraud prevention?</summary>

Mobile Intelligence is a **phone number fraud detection** check.

It analyzes a customer’s mobile number for **reputation**, **activity**, and **abuse signals** to help identify fraud risk early.

</details>

<details>

<summary>How is Mobile Intelligence different from SMS Verification?</summary>

Mobile Intelligence scores the **risk** and **reputation** of a phone number.

[SMS Verification](/documentation/product-guides/kyc-automation-services/sms-verification) confirms that the customer can receive and submit a one-time password sent to that number.

</details>

<details>

<summary>Can Mobile Intelligence detect abusive or low-trust phone numbers?</summary>

Yes.

It can flag mobile numbers linked to **recent abuse**, suspicious activity patterns, or other signals associated with fraud risk.

</details>

<details>

<summary>Does Mobile Intelligence verify phone ownership?</summary>

No.

Mobile Intelligence assesses **phone number risk**. It does not prove that the customer controls the number.

Use [SMS Verification](/documentation/product-guides/kyc-automation-services/sms-verification) when you need to confirm phone ownership with an OTP.

</details>

<details>

<summary>Can Mobile Intelligence help prevent account takeover and promo abuse?</summary>

Yes.

It helps identify risky numbers used in **ATO**, **sign-up fraud**, and **referral or promotion abuse** flows.

</details>

<details>

<summary>Should I combine Mobile Intelligence with Device Intelligence and Email Intelligence?</summary>

Yes.

Mobile Intelligence works well with [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) and [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check) when you want to assess **phone**, **device**, and **email** risk together.

</details>

### Related checks

Combine Mobile Intelligence with other fraud intelligence signals:

* [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check) for email reputation, disposable email detection, and breach exposure.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) for device fingerprinting, VPN/emulator signals, and bot detection.

### Related topics <a href="#related-topics" id="related-topics"></a>

Use these to run Mobile Intelligence inside a broader KYC workflow and decision flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate Mobile Intelligence as a step in onboarding.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent rules using the returned risk signals.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to review exceptions and keep audit-ready decisions.


# Proof of Address Check

KYC proof of address verification. Extract address data from PoA documents (e.g. utility bills, bank statements) and match it to customer details using OCR and geolocation signals.

### Proof of Address Check Overview

Proof of Address (PoA) Check is a **document-based address verification** service for **KYC** and customer onboarding.

It uses ComplyCube’s OCR and decision engine to extract address details from PoA documents. It then verifies the extracted data against customer-provided information and geolocation signals.

#### Supported proof of address documents

This service supports the following PoA document types:

* Bank statements
* Utility bills
* Driving licenses
* Tax documents

{% hint style="info" %}
We recommend running this type of check through our [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide), [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide), or native [Mobile SDKs](/documentation/quick-guides/mobile-sdk-guide). This enables ComplyCube to perform additional analysis on the submitted proof of address document.
{% endhint %}

{% hint style="info" %}
[Learn about the Proof of Address Checks API.](/documentation/api-reference/check-types/proof-of-address-check)
{% endhint %}

### Common use cases

Proof of Address Checks are typically used for:

* **Document-based address verification**: Verify a customer’s residential address using proof of address documents (for example, a utility bill or bank statement).
* **KYC onboarding and CDD**: Collect and validate address evidence to support customer due diligence (CDD) requirements.
* **Fraud risk reduction**: Detect mismatches between submitted and extracted address data, suspicious document recency, or anomalous geolocation signals.
* **Audit-ready proof of address evidence**: Capture extracted address details and document metadata to support compliance reviews.

### How the check works

1. The customer uploads a proof of address document (for example, a utility bill).
2. ComplyCube extracts address and document metadata using OCR.
3. The check validates the extracted address against customer-provided details.
4. The check evaluates geolocation signals (for example, IP proximity) to support the decision.

### Analysis performed

The PoA Check extracts and validates a customer’s address details from PoA documents.

The diagram below outlines the key analysis categories.

***

![Proof of Address Check Overview](/files/-MkloaHcLlvwcB9ilZB3)

***

**Detailed verification checks**

<table><thead><tr><th width="204.53515625">Analysis</th><th>Verifications Performed</th></tr></thead><tbody><tr><td><strong>Content Analysis</strong></td><td>Checks the issue date of the PoA document to confirm it is recent and valid.</td></tr><tr><td><strong>Geolocation Analysis</strong></td><td>Validates IP address details and proximity against the extracted address.</td></tr><tr><td><strong>Client Validation</strong></td><td>Ensures the customer’s submitted details align with the information extracted from the PoA document.</td></tr></tbody></table>

### Sample result

The example below shows a representative Proof of Address Check result for address extraction, validation, and geolocation outcomes.

Use it to see how extracted address details, supporting signals, and verification findings may appear in a Proof of Address Check report.

<figure><img src="/files/Mq4N0NNa6xI8h6iXAI7e" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
This example is illustrative. Exact fields, values, and layout may vary by workflow, configuration, and result.
{% endhint %}

### Check duration

A PoA Check takes an average of **10 seconds** to complete.

### Frequently asked questions

<details>

<summary>Why is proof of address required for KYC?</summary>

Proof of address helps confirm that a customer lives at the address they provided.

It supports **KYC**, **CDD**, and fraud controls by adding address evidence to the verification process.

</details>

<details>

<summary>Can I verify an address using a utility bill or bank statement?</summary>

Yes.

Proof of Address Check is designed to verify customer addresses from common **PoA documents** such as utility bills and bank statements.

</details>

<details>

<summary>Does the proof of address document need to be recent?</summary>

Yes.

The check reviews the document’s **issue date** to confirm that it is recent enough for address verification.

The document age threshold is **configurable**, so you can define how old a proof of address document can be before it is flagged.

</details>

<details>

<summary>What is the difference between Proof of Address Check and Multi-Bureau Check?</summary>

Proof of Address Check verifies address evidence from a **document** uploaded by the customer.

[Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) verifies identity and address details against **authoritative data sources**.

</details>

<details>

<summary>Which checks are commonly combined with Proof of Address Check in KYC?</summary>

Proof of Address Check is often combined with [Document Check](/documentation/product-guides/identity-verification/document-check), [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check), [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check), and [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check).

</details>

### Related checks

You’ll typically run Proof of Address Check alongside:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for ID document verification.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for liveness and selfie verification.
* [Multi-Bureau Check](/documentation/product-guides/identity-verification/multi-bureau-check) for database-based identity and address verification.
* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, PEP, and adverse media.

### Related topics

Use these pages to design an end-to-end address verification journey:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to run PoA checks as part of a full onboarding journey.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to collect customer information and supporting data.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply rule-based decisions and evidence requirements.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to review exceptions and handle manual follow-ups.


# Company Search & Insights

KYB company search and business verification. Retrieve company, director, and beneficial ownership (UBO) data for 150M+ businesses in 50+ jurisdictions.

### Company Search & Insights Overview

Company Search enables you to automate **KYB (Know Your Business)** onboarding and **business verification** by retrieving verified business data for **150M+ companies** across **50+ jurisdictions**.

Use it to retrieve **company profile data**, **directors**, and **ownership / beneficial ownership (UBO)** insights sourced from **official business registers**.

This is a **company registry lookup** for KYB, corporate due diligence, and compliance automation.

{% hint style="info" %}
[Learn about the Company Search API.](/documentation/api-reference/tools/company-search)
{% endhint %}

### Common use cases

Company Search is commonly used for:

* **KYB onboarding**: Verify businesses during merchant, partner, or vendor onboarding.
* **Beneficial ownership (UBO) discovery**: Support ownership understanding and control checks.
* **Company status checks**: Confirm the entity is active (and not dissolved/struck off), where available.
* **Corporate due diligence**: Enrich internal records with authoritative registry data.

### Data & insights returned

The results depend on the jurisdiction and available register data. Responses typically include:

* **Company details** such as legal name, registration number, status, and registered address.
* **Officers / directors** and related appointment information where available.
* **Ownership and control data**, including shareholder or beneficial ownership (UBO) where available.

### How it works

1. You submit a company search request using a company name.
2. ComplyCube queries official business registers for the matching entity.
3. You receive structured business data and insights you can use in KYB workflows and reviews.

### Country coverage

Company Search currently supports the following countries and territories.

{% columns %}
{% column %}

#### Europe

* 🇦🇱 Albania
* 🇧🇾 Belarus
* 🇧🇪 Belgium
* 🇧🇬 Bulgaria
* 🇭🇷 Croatia
* 🇨🇾 Cyprus
* 🇨🇿 Czech Republic
* 🇩🇰 Denmark
* 🇫🇮 Finland
* 🇫🇷 France
* 🇩🇪 Germany
* 🇬🇮 Gibraltar
* 🇬🇷 Greece
* 🇬🇱 Greenland
* 🇬🇬 Guernsey
* 🇮🇸 Iceland
* 🇮🇪 Ireland
* 🇮🇲 Isle of Man
* 🇯🇪 Jersey
* 🇱🇻 Latvia
* 🇱🇮 Liechtenstein
* 🇱🇺 Luxembourg
* 🇲🇹 Malta
* 🇲🇩 Moldova
* 🇲🇪 Montenegro
* 🇳🇱 Netherlands
* 🇳🇴 Norway
* 🇵🇱 Poland
* 🇷🇴 Romania
* 🇸🇰 Slovakia
* 🇸🇮 Slovenia
* 🇪🇸 Spain
* 🇸🇪 Sweden
* 🇨🇭 Switzerland
* 🇺🇦 Ukraine
* 🇬🇧 United Kingdom
  {% endcolumn %}

{% column %}

#### Asia-Pacific

* 🇦🇺 Australia
* 🇧🇩 Bangladesh
* 🇰🇭 Cambodia
* 🇭🇰 Hong Kong
* 🇮🇳 India
* 🇯🇵 Japan
* 🇲🇾 Malaysia
* 🇲🇲 Myanmar
* 🇳🇿 New Zealand
* 🇵🇰 Pakistan
* 🇸🇬 Singapore
* 🇹🇭 Thailand
* 🇻🇳 Vietnam
  {% endcolumn %}
  {% endcolumns %}

{% columns %}
{% column %}

#### North America and Caribbean

* 🇧🇸 Bahamas
* 🇧🇧 Barbados
* 🇧🇿 Belize
* 🇧🇲 Bermuda
* 🇨🇦 Canada
* 🇩🇴 Dominican Republic
* 🇯🇲 Jamaica
* 🇵🇷 Puerto Rico
* 🇺🇸 United States
  {% endcolumn %}

{% column %}

#### **Africa**

* 🇲🇺 Mauritius
* 🇷🇼 Rwanda
* 🇿🇦 South Africa
* 🇹🇿 Tanzania
* 🇹🇳 Tunisia
* 🇺🇬 Uganda
  {% endcolumn %}
  {% endcolumns %}

{% columns %}
{% column %}

#### Latin America

* 🇧🇴 Bolivia
* 🇧🇷 Brazil
* 🇲🇽 Mexico
* 🇵🇦 Panama
  {% endcolumn %}

{% column %}

#### **Middle East**

* 🇧🇭 Bahrain
* 🇮🇷 Iran
* 🇮🇱 Israel
* 🇦🇪 United Arab Emirates
  {% endcolumn %}
  {% endcolumns %}

{% columns %}
{% column %}

#### Other / Territories

* 🇦🇼 Aruba
* 🇲🇶 Martinique
* 🇹🇴 Tonga
* 🇻🇺 Vanuatu
  {% endcolumn %}

{% column %}

{% endcolumn %}
{% endcolumns %}

### Frequently asked questions

<details>

<summary>What is Company Search for KYB?</summary>

Company Search is a **KYB company search** and **business verification** service.

It retrieves structured business data from official registers to support merchant, partner, and vendor onboarding.

</details>

<details>

<summary>What company data does Company Search return?</summary>

Company Search can return **legal name**, **registration number**, **status**, **registered address**, **directors**, and **ownership or beneficial ownership data** where available.

</details>

<details>

<summary>Does Company Search include directors and beneficial owners?</summary>

Yes, where the jurisdiction and source register provide that data.

This can include **officers**, **directors**, shareholders, and **UBO-related** information.

</details>

<details>

<summary>Are Company Search results sourced from official business registers?</summary>

Yes.

Company Search retrieves data from **official business registers** and returns it in a structured format for KYB workflows and reviews.

</details>

<details>

<summary>How many companies and countries does Company Search cover?</summary>

Company Search covers **150M+ businesses** across **50+ jurisdictions**.

See the country coverage section above for the current supported jurisdictions.

</details>

<details>

<summary>Can I use Company Search in a KYB onboarding workflow?</summary>

Yes.

Company Search is well suited to **KYB onboarding**, **corporate due diligence**, and business verification flows where you need authoritative registry data.

</details>


# Address Search

Instantly check, verify and correct your customers' addresses.

### Address Search Overview

Address Search enables you to quickly search, validate, and retrieve **global addresses** in a structured format.

This service helps ensure that customer-provided address details are standardized, accurate, and easy to process across different systems and jurisdictions.

{% hint style="info" %}
When enabled, this service **integrates into workflows** with **address capture screens** and guides customers as they enter their address, helping ensure details are complete, properly structured, and correctly formatted.
{% endhint %}

{% hint style="info" %}
[Learn about the Address Search API.](/documentation/api-reference/tools/address-search)
{% endhint %}


# Autofill

KYC identity document OCR and data extraction. Parse MRZ, VIZ, and barcode data to prefill onboarding forms.

### Autofill Overview

Autofill is an **identity document OCR** and **data extraction** service.

It extracts structured customer data from [13,000+ document types](/documentation/product-guides/identity-verification/document-check/document-types-per-country) across **250+ countries and territories**.

Autofill supports a wide range of identity documents, including:

* Passports
* Driving licenses
* National identity cards
* Residence permits
* Tax identification documents
* Other region-specific IDs, including voter, refugee, and health cards

{% hint style="info" %}
[Learn about the Autofill API.](/documentation/api-reference/other-resources/autofill)
{% endhint %}

#### Data extracted

The extracted data is returned in a structured and standardized format.

It includes fields from the **Visual Inspection Zone (VIZ)**, **Machine Readable Zone (MRZ)**, and **barcodes**.

The service will also extract images from the document, including **cropped faces**, **signatures**, **security elements**, and more.

#### Common use cases

Autofill is commonly used in scenarios such as:

* **Onboarding form autofill**: Prefill registration and onboarding forms directly from ID document scans to reduce manual entry and customer drop-off.
* **Data quality improvement**: Extract names, dates of birth, document numbers, and other key attributes directly from identity documents to minimize input errors.
* **Faster customer verification**: Reduce onboarding friction by automatically populating required identity fields during verification flows.

### Frequently asked questions

<details>

<summary>What is Autofill in identity verification?</summary>

Autofill is an **identity document OCR** and **data extraction** service.

It extracts structured fields from identity documents so forms can be prefilled automatically during onboarding.

</details>

<details>

<summary>Which identity documents does Autofill support?</summary>

Autofill supports **passports**, **driving licenses**, **national identity cards**, **residence permits**, **tax identification documents**, and many other government-issued IDs.

</details>

<details>

<summary>What data can Autofill extract from an ID document?</summary>

Autofill can extract fields from the **VIZ**, **MRZ**, and **barcodes**.

It can also extract images such as **cropped faces**, **signatures**, and other document assets.

</details>

<details>

<summary>Does Autofill replace Document Check?</summary>

No.

Autofill extracts data from the document. It does not perform the full authenticity and fraud analysis provided by [Document Check](/documentation/product-guides/identity-verification/document-check).

</details>

<details>

<summary>Can Autofill reduce onboarding friction?</summary>

Yes.

Autofill reduces manual typing, improves data quality, and helps speed up onboarding by pre-populating customer fields from the document.

</details>

### Related checks

You’ll typically use Autofill alongside:

* [Document Check](/documentation/product-guides/identity-verification/document-check) for a full ID verification, including authenticity and fraud analysis.
* [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) for selfie liveness and face match.
* [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check) to confirm a customer’s address using supporting documents.

### Related topics

Use these to design an end-to-end onboarding journey:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate checks and steps.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to collect extra customer data and declarations.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply rule-based decisions.


# SMS Verification

SMS OTP for mobile number verification confirms phone ownership by sending a one-time password (OTP) via SMS during onboarding.

### SMS Verification Overview

SMS verification helps you confirm **phone ownership** during onboarding. ComplyCube generates **time-bound one-time passwords (OTP)**, delivers them through global carrier routes, and validates submissions with anti-abuse controls.

### Common use cases <a href="#common-use-cases" id="common-use-cases"></a>

Use SMS OTP verification anywhere the phone number is a key identifier:

* **KYC onboarding**: Confirm the customer controls the number before deeper checks.
* **Sign-up and login verification**: Reduce fake sign-ups with a friction-light OTP challenge.
* **Transaction and settings changes**: Re-verify phone ownership before sensitive actions.

### How it works

1. A flow initiates SMS Verification for the customer’s mobile number.
2. ComplyCube sends an OTP to the customer via SMS.
3. The customer enters the OTP in the verification step.
4. ComplyCube validates the code before the verification flow continues.

### Country coverage

ComplyCube supports SMS delivery and OTP validation in **over 230 countries and territories**.

Coverage is grouped into **eight service tiers**. Tiers reflect regional carrier characteristics and delivery rules. They help set routing and deliverability expectations.

<table><thead><tr><th width="83.296875">Tier</th><th>Countries</th></tr></thead><tbody><tr><td><strong>T1</strong></td><td>Australia, Bahrain, Brazil, Brunei, Canada, Chile, China, Christmas Island, Cocos (Keeling) Islands, Colombia, Costa Rica, Czech Republic, Denmark, Faroe Islands, France, Greece, Greenland, Guam, Guernsey, Hong Kong, Iceland, Ireland, Isle of Man, Jersey, Korea (Republic of), Latvia, Liechtenstein, Lithuania, Macao, Malta, Micronesia, Namibia, Norfolk Island, Northern Mariana Islands, Norway, Poland, Portugal, Puerto Rico, Romania, Singapore, Svalbard and Jan Mayen, Sweden, Switzerland, Thailand, Turkey, United Kingdom, United States</td></tr><tr><td><strong>T2</strong></td><td>Åland Islands, Albania, Andorra, Antarctica, Argentina, Austria, Bahamas, Belgium, Botswana, Croatia, Cyprus, Dominican Republic, Eritrea, Estonia, Falkland Islands, Finland, Germany, Gibraltar, Hungary, India, Italy, Japan, Luxembourg, Moldova, Netherlands, New Zealand, Nicaragua, Paraguay, San Marino, São Tomé and Príncipe, Slovakia, Solomon Islands, South Africa, Spain, Taiwan, United Arab Emirates, Uruguay, Wallis and Futuna</td></tr><tr><td><strong>T3</strong></td><td>American Samoa, Anguilla, Antigua and Barbuda, Aruba, Bermuda, Bolivia, Bulgaria, Burkina Faso, Cape Verde, Cook Islands, Djibouti, Dominica, DR Congo, East Timor, Fiji, French Guiana, French Polynesia, French Southern Territories, Gambia, Georgia, Guadeloupe, Kenya, Kiribati, Macedonia, Martinique, Mauritius, Marshall Islands, Mayotte, Mexico, Monaco, Montenegro, Morocco, New Caledonia, Niue, Oman, Palau, Panama, Philippines, Réunion, Saudi Arabia, Slovenia, Saint Kitts and Nevis, Saint Lucia, Saint Pierre and Miquelon, Swaziland (Eswatini), Tonga, Turks and Caicos Islands, Tuvalu, Ukraine, Vanuatu, Venezuela, Vietnam, U.S. Virgin Islands, Western Sahara</td></tr><tr><td><strong>T4</strong></td><td>Algeria, Angola, Armenia, Barbados, Belarus, Belize, Benin, Cameroon, Cayman Islands, Chad, Congo, El Salvador, Equatorial Guinea, Grenada, Guatemala, Guinea, Haiti, Honduras, Israel, Jamaica, Kosovo, Laos, Liberia, Malaysia, Mauritania, Mongolia, Montserrat, Nepal, Peru, Qatar, Rwanda, Samoa, Seychelles, Somalia, South Sudan, Saint Vincent and the Grenadines, Trinidad and Tobago, British Virgin Islands, Yemen, Zimbabwe</td></tr><tr><td><strong>T5</strong></td><td>Afghanistan, Azerbaijan, Bangladesh, Bosnia and Herzegovina, Ecuador, Egypt, Ethiopia, Gabon, Ghana, Guyana, Jordan, Kazakhstan, Kuwait, Kyrgyzstan, Lebanon, Libya, Malawi, Maldives, Mali, Myanmar, Niger, Nigeria, Palestine, Sierra Leone, Sri Lanka, Suriname, Turkmenistan, Uganda, Zambia</td></tr><tr><td><strong>T6</strong></td><td>Bhutan, Burundi, Cambodia, Central African Republic, Comoros, Guinea-Bissau, Indonesia, Iraq, Ivory Coast, Lesotho, Mozambique, Pakistan, Senegal, Serbia, Sudan, Tajikistan, Tanzania, Togo, Tunisia, Uzbekistan</td></tr><tr><td><strong>T7</strong></td><td>Madagascar</td></tr><tr><td><strong>T8</strong></td><td>Papua New Guinea, Russia</td></tr></tbody></table>

### Related checks

Combine SMS Verification with other fraud and identity signals:

* [Mobile Intelligence](/documentation/product-guides/digital-fraud-intelligence/mobile-intelligence-check) for risk scoring and reputation signals on the same phone number.
* [Email Verification](/documentation/product-guides/kyc-automation-services/email-verification) for OTP-based inbox ownership verification in the same onboarding journey.
* [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check) for email reputation and disposable/breached email detection.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) for device fingerprinting, tamper signals, and network indicators (VPN/proxy, emulator, root/jailbreak).

### Related topics

Use these to integrate SMS OTP verification into a broader KYC flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate SMS Verification and follow-up checks.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to capture customizable customer details in the same journey.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to review exceptions and keep audit-ready evidence.


# Email Verification

Email OTP for email address verification confirms inbox ownership by sending a one-time password (OTP) during onboarding.

### Email Verification Overview

Email Verification helps you confirm **email ownership** during onboarding. ComplyCube generates **time-bound one-time passwords (OTP)**, delivers them to the customer’s inbox, and validates submissions before the verification flow continues.

Email Verification confirms that the customer can access the inbox. It does **not** assess whether the email address is **temporary**, **disposable**, **breached**, or otherwise high risk.

{% hint style="info" %}
Use [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check) when you need disposable email detection, breach exposure checks, and broader email risk analysis.
{% endhint %}

### Common use cases

Use Email OTP verification anywhere the email address is a key identifier:

* **KYC onboarding**: Confirm the customer controls the email address before deeper checks.
* **Sign-up and login verification**: Reduce fake sign-ups with a friction-light OTP challenge.
* **Transaction and settings changes**: Re-verify email ownership before sensitive actions.

### How it works

1. A flow initiates Email Verification for the customer’s email address.
2. ComplyCube sends an OTP to the customer via email.
3. The customer enters the OTP in the verification step.
4. ComplyCube validates the code before the verification flow continues.

### Related checks

Combine Email Verification with other fraud and identity signals:

* [Email Intelligence](/documentation/product-guides/digital-fraud-intelligence/email-intelligence-check) for risk scoring and disposable or breached email detection on the same email address.
* [Device Intelligence](/documentation/product-guides/digital-fraud-intelligence/device-intelligence-check) for device fingerprinting, tamper signals, and network indicators such as VPN or proxy use.
* [SMS Verification](/documentation/product-guides/kyc-automation-services/sms-verification) for OTP-based phone ownership verification in the same journey.

### Related topics

Use these to integrate Email OTP verification into a broader KYC flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate Email Verification and follow-up checks.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to capture customer details in the same journey.
* [Advanced Case Management](/documentation/product-guides/due-diligence-tools/advanced-case-management) to review exceptions and keep audit-ready evidence.


# AML Risk Scoring

AML risk scoring solution for customer risk assessment in KYC and KYB. Customize risk models to assign AML risk ratings and trigger CDD or EDD workflows.

### AML Risk Scoring Overview

AML Risk Scoring generates a **customer AML risk rating** for **KYC and KYB compliance**.

It supports a consistent **AML customer risk assessment** across onboarding and ongoing monitoring. Use it to trigger **Customer Due Diligence (CDD)** or **Enhanced Due Diligence (EDD)** based on risk.

AML Risk Scoring supports both **ComplyCube’s native risk scores** and **custom risk models** tailored to your AML risk framework.

It’s designed for both **individuals** and **businesses**.

{% columns %}
{% column %}

<figure><img src="/files/gefgv8fQb6C4KPyTTUnZ" alt="" width="563"><figcaption><p>Sample Individual Risk Profile</p></figcaption></figure>
{% endcolumn %}

{% column %}

<figure><img src="/files/mmT1sSYjZtzst0zNXBl3" alt="" width="563"><figcaption><p>Sample Business Risk Profile</p></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

{% hint style="info" %}
**Country risk** scores are fully customizable in the Portal. Align them to your internal AML risk framework and policies.
{% endhint %}

{% hint style="info" %}
To configure a fully flexible and comprehensive AML risk model that aligns with your AML and risk framework, contact your **Account Manager**.
{% endhint %}

### Common use cases

Use AML Risk Scoring in any flow where you need a defensible **customer risk rating**:

* **KYC onboarding**: Create a baseline AML risk profile at account opening.
* **KYB risk assessment**: Score businesses using incorporation, ownership, and granular risk dimensions.
* **Workflow decisioning**: Use AML risk to route customers through different workflows.
* **Dynamic questionnaires**: Use [Smart Form](/documentation/product-guides/compliance-studio/smart-forms) responses to refine risk scores.
* **Ongoing monitoring**: Re-score customers after changes to key identity attributes.

### Interactive demo

{% @arcade/embed url="<https://app.arcade.software/share/jkUkvzHPUA3J1MeMhKps>" flowId="jkUkvzHPUA3J1MeMhKps" %}

### How AML risk scoring works

AML Risk Scoring generates an overall AML risk profile using two types of risk elements: [System risks](#system-risks) and [Custom risk](#custom-risk).

#### System risks

System risks are ComplyCube’s native AML risk indicators. These represent common compliance and fraud-related risk factors, including: [Political exposure (PEP)](#aml-risk-factors-and-scoring-elements), [Watchlist exposure](#aml-risk-factors-and-scoring-elements)**,** [Occupation risk](#aml-risk-factors-and-scoring-elements)**,** and [Country risk](#aml-risk-factors-and-scoring-elements)**.**

These risk scores are automatically calculated using customer details, verification results, and trusted external datasets.

#### Custom risk

Custom risk allows you to define your own risk elements and scoring logic, while ComplyCube performs the calculation and evaluation for you.

Custom risk can use:

* Customer profile data.
* [Smart Form](/documentation/product-guides/compliance-studio/smart-forms) (i.e. dynamic questionnaire) responses.
* Verification check results.
* Other captured customer attributes.

This enables businesses to implement organization-specific risk frameworks and decisioning logic.

### Risk levels and overall scoring

Each risk element returns one of the following levels: **Very High**, **High**, **Medium**, **Low**, or **No Risk Set**.

The overall AML risk profile can then be calculated using one of two models:

* **Highest risk**: Uses the highest detected risk level as the overall result (default).
* **Weighted score**: Combines multiple risk elements into a single weighted result.

### Score explainability

AML Risk Scoring is designed to support **explainable risk assessments** and **traceable AML decision-making**.

Each AML risk score includes a **detailed breakdown** showing the contributing risk elements, scoring methodology, and supporting inputs used in the calculation.

The AML Risk view helps teams understand:

* Why a customer received a particular risk level.
* The factors driving the overall AML risk score.
* Whether highest-risk or weighted scoring was used.
* Which inputs (data, checks, or questionnaire responses) influenced the outcome.

In the Portal, this information is presented through **visual score breakdowns** and factor-level drill-downs, making results easier to review and investigate.

<figure><img src="/files/uqI6D6fTlZ8ndBzIFLMW" alt=""><figcaption><p>Visual AML risk score breakdown with factor-level traceability and supporting evidence.</p></figcaption></figure>

This level of transparency supports **faster investigations**, more **consistent reviews**, stronger **audit trails**, and easier justification of **CDD and EDD decisions** throughout the customer lifecycle.

### Automatic recalculation

The AML Risk Profile is automatically refreshed throughout the client lifecycle, including:

1. **After check completion**: Once a verification is successfully completed and validated.
2. **After workflow completion**: When a workflow session finishes.
3. **When customer details change**: Updates to customer information trigger a recalculation.
4. **When questionnaires or attestations are completed**: New submissions can trigger a recalculation of the score.

### AML risk scoring elements

<table><thead><tr><th width="216.40234375">Element</th><th>Description</th></tr></thead><tbody><tr><td><strong>Overall Risk</strong></td><td>The final AML risk indicator for the customer. This can be calculated using either a <strong>weighted score</strong> model or a <strong>highest risk</strong> model. It defaults to the <strong>highest risk.</strong></td></tr><tr><td><strong>Political Exposure Risk</strong></td><td>When a customer is confirmed as a <a href="/pages/-M7JAF0I0xV8IXZOscPw#pep-levels-explained">Politically Exposed Person (PEP)</a>, this represents the calculated political exposure risk level.</td></tr><tr><td><strong>Occupation Risk</strong></td><td>Represents the calculated occupation risk level.<br><br>Certain occupations are considered higher risk due to their potential influence and exposure to corruption.</td></tr><tr><td><strong>Watchlist Risk</strong></td><td>When a customer is confirmed to be on a <a href="/pages/-M7JAF0I0xV8IXZOscPw">sanctions list or watchlist</a>, this represents the calculated watchlist risk level.</td></tr><tr><td><strong>Country Risk</strong></td><td><p>Evaluates the customer’s address, nationality, birth country, and incorporation country for businesses.</p><p>ComplyCube calculates the score using data from industry-recognized bodies, including:<br></p><ul><li>Corruption Perceptions Index</li><li>Federal Bureau of Investigation (FBI)</li><li>Financial Action Task Force (FATF)</li><li>FinCEN</li><li>Freedom House</li><li>Index of Economic Freedom</li><li>International IDEA Political Finance Database</li><li>Organization for Economic Co-operation and Development</li><li>Transparency International</li><li>US Department of State</li><li>World Bank Group</li><li>World Economic Forum</li></ul><p>This can also be <strong>customized</strong> to align with your own assessment criteria.</p></td></tr><tr><td><strong>Custom Risk</strong></td><td>Define your <strong>own risk elements and scoring logic</strong>, then let ComplyCube calculate the result on an ongoing basis, using customer data captured across ComplyCube.</td></tr></tbody></table>

### Frequently asked questions

<details>

<summary>What is AML risk scoring?</summary>

AML Risk Scoring generates an overall **customer AML risk rating** for **KYC** and **KYB**.

It also generates **granular risk scores** across individual risk factors, which helps you classify customers into risk bands and support downstream due diligence decisions.

</details>

<details>

<summary>What is customer AML risk assessment in KYC and KYB?</summary>

Customer AML risk assessment is the process of evaluating how much **money laundering**, **sanctions**, or **financial crime** risk a customer or business presents.

AML Risk Scoring helps standardize that assessment across both **individuals** and **businesses**.

</details>

<details>

<summary>What factors are used in AML risk scoring?</summary>

AML Risk Scoring can use factors such as **PEP exposure**, **watchlist exposure**, **occupation risk**, **country risk**, and **custom risk elements**.

It can also use customer profile data, verification results, and [Smart Form](/documentation/product-guides/compliance-studio/smart-forms) responses.

</details>

<details>

<summary>Can AML risk scoring trigger CDD or EDD?</summary>

Yes.

AML Risk Scoring helps you route customers into **Customer Due Diligence (CDD)** or **Enhanced Due Diligence (EDD)** based on their overall risk profile.

</details>

<details>

<summary>Can I see why a customer received a specific AML risk score?</summary>

Yes.

AML Risk Scoring provides **score explainability** through a visual **risk score breakdown** and factor-level traceability.

This helps teams understand which inputs, checks, and risk elements contributed to the final score and supports **audit-ready** decisioning.

</details>

<details>

<summary>How is AML Risk Scoring different from AML Screening?</summary>

[AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) identifies sanctions, PEP, watchlist, and adverse media exposure.

AML Risk Scoring turns risk factors, screening results, and customer data into an overall **risk profile**.

</details>

<details>

<summary>Can AML Risk Scoring support both KYC and KYB?</summary>

Yes.

AML Risk Scoring supports **individuals** and **businesses**, so it can be used in both **KYC** and **KYB** programs.

</details>

<details>

<summary>Can I build a custom AML risk model?</summary>

Yes.

You can use **custom risk** elements alongside ComplyCube’s native risk indicators to align scoring with your internal AML framework.

</details>

<details>

<summary>When does the AML risk profile recalculate?</summary>

The AML risk profile can refresh after **check completion**, **workflow completion**, **customer data changes**, and new **questionnaire or attestation submissions**.

</details>

### Related checks

AML Risk Scoring is typically used alongside:

* [AML Screening Check](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check) for sanctions, watchlist, PEP, and adverse media screening.
* [Custom Lists](/documentation/product-guides/watchlist-pep-and-adverse-media/custom-lists) to screen customers against your internal watchlists and risk lists.

### Related topics

Use these to operationalize AML risk scoring inside an onboarding and decision flow:

* [Workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate screening and other checks in a single customer journey.
* [Smart Forms](/documentation/product-guides/compliance-studio/smart-forms) to capture questionnaire data and other customer inputs used in custom risk.
* [Compliance Policies](/documentation/product-guides/compliance-studio/policies) to apply consistent CDD/EDD rules and feed policy outcomes into custom risk.


# Advanced Case Management

Incorporate granular controls, tasks, and lifecycle stages into your cases.

### Advanced Case Management Overview

Our fully integrated Advanced Case Management service enables you to streamline and scale KYC operations through a centralized platform.

It allows you to:

* Create and assign custom tasks tailored to your compliance workflows.
* Configure automatic case triggers to speed up decision-making.
* Set up user groups to manage case state transitions securely.
* Maintain transparency with a comprehensive audit trail that records every action.

{% hint style="info" %}
This service is available through our **Enterprise Plan**. To learn more, please get in touch with your **Account Manager**.
{% endhint %}

<figure><img src="/files/AWgfViq34hzM6jof9DJk" alt=""><figcaption><p>Advanced Case Management</p></figcaption></figure>

### User groups

To complement our [user roles and permissions](broken://pages/-MBhSC2Tj3SxkS2oo0cs), Advanced Case Management introduces **User Groups** to help manage cases in a structured and controlled way. User Groups mirror your internal team structures and can be configured to restrict how tasks transition between states within a case, ensuring proper oversight and compliance.

![User Groups](/files/05aMEV3LATsvviVjdYcN)

### Frequently asked questions

<details>

<summary>What is Advanced Case Management?</summary>

Advanced Case Management is a centralized operations layer for managing compliance reviews, tasks, and case workflows.

It helps teams coordinate investigations, decisions, and follow-up actions in one place.

</details>

<details>

<summary>What can teams do with Advanced Case Management?</summary>

Teams can create and assign **tasks**, configure **case triggers**, control **state transitions**, and track every action with an **audit trail**.

</details>

<details>

<summary>How do User Groups help manage cases?</summary>

User Groups mirror your internal team structure and help control who can move a case or task between states.

This supports stronger oversight, separation of duties, and controlled case handling.

</details>

<details>

<summary>Does Advanced Case Management provide an audit trail?</summary>

Yes.

Advanced Case Management maintains a detailed **audit trail** so teams can review case activity, decisions, and ownership changes over time.

</details>

<details>

<summary>Who is Advanced Case Management designed for?</summary>

It is designed for **compliance**, **risk**, and **operations** teams that need structured review workflows, case ownership, and audit-ready oversight at scale.

</details>


# Automation

Customize and automate our checks to meet your compliance needs.

{% hint style="warning" %}

### Automation scope and limitations

The Automation feature outlined below applies only to **standalone checks**.

For checks executed within a **Workflow Session**, any automation, business rules, or capture preference should be configured at the check level within the associated **Workflow Template**.
{% endhint %}

## Automation Overview

ComplyCube provides the ability to customize check thresholds and settings. This allows you to automate your checks in line with your **risk-based approach**.

You can amend these automation rules through the [automation settings page](https://portal.complycube.com/automations).

## Screening Check

<figure><img src="/files/JPBICwrv4lRYLSKrJUVo" alt=""><figcaption><p>Screening Checks Automation View</p></figcaption></figure>

### Thresholds

ComplyCube's [AML Screening ](/documentation/product-guides/watchlist-pep-and-adverse-media/aml-screening-check)matching engine is purpose-built to find and match comparable identity data from any **language or script**. It incorporates sophisticated fuzzy matching algorithms, heuristics, linguistic variance, and phonetic analysis to find matches without producing costly and time-wasting lists of false positives.

To simplify usage, ComplyCube represents the outcome of the analysis in the form of a **match score**. A match score can range from 0 to 100, with 100 being the best match.

By default, an AML Screening Check will only return matches with a match score over **85** and automatically reject matches with a score ranging between **85** and **90**. Ultimately, only matches with scores higher than 90 will require manual checks.

You can adjust these automation thresholds according to your risk-based framework and internal process.

### Exclusion rules

By default, ComplyCube will not exclude any matches. We will return matches without a DOB, gender, nationality, or incorporation country details. Furthermore, ComplyCube will also return inactive, deceased, and low-quality alias matches.

### Search mode

Depending on your risk tolerance and preference, you can select from two distinct name-matching techniques:

1. **Fuzzy** (default): applies various linguistic, phonetic, and near-match techniques on names to find matches.
2. **Precise:** only matches names that are exact

{% hint style="info" %}
The search mode **only** applies to the name-matching aspect of the Screening Check. ComplyCube utilizes other proprietary algorithms to find matches using other attributes.
{% endhint %}

## Document Check

<figure><img src="/files/W3uJwiprSRznikYlXlEV" alt=""><figcaption><p>Document Checks Automation View</p></figcaption></figure>

### Minimum age

ComplyCube's [Document Check](/documentation/product-guides/identity-verification/document-check) uses OCR technology and advanced analytics to authenticate and extract data from your clients' ID documents.

This setting empowers **age verification** compliance by allowing you to set a minimum acceptable age before your client ID is flagged.

By default, a Document Check will flag anyone younger than **18 years of age**.

### **Security element matching threshold**

ComplyCube returns a **security element match score** for each analyzed security element present on a document. A match score can range from 0 to 100; the closer the score is to 100, the greater the confidence that the security element is authentic.

By default, a Document check will deem a security element real when the match score is over **65**.

### **Inflight check attempts via SDK**

ComplyCube performs **inflight quality checks** on document images uploaded via the Web and Mobile SDKs. This setting configures the maximum number of times our quality checks are performed before sending a document for full processing, regardless of its quality.

By default, a document's quality will be checked up to **5 times** on upload before it's sent for complete processing.

### Additional checks

ComplyCube extends further optional checks, including:

* **Client data validation**: this check compares the client record data (e.g., first and last names) with data extracted from an ID document.
* **Document model validation**: this check considers the visual consistency, at a pixel level, of a single or two-sided document.

By default, ComplyCube will only perform **document model validation**.

## Identity Check

<figure><img src="/files/EQuI7P4aS8lsvbvZtvXj" alt=""><figcaption><p>Identity Checks Automation View</p></figcaption></figure>

ComplyCube's [Identity Check](/documentation/product-guides/biometric-and-liveness-verification/identity-check) utilizes computer vision, liveness, spoof-detection technologies, and facial comparison algorithms to determine whether two faces belong to the same client.

### Facial similarity threshold

ComplyCube represents the outcome of a facial analysis in the form of a **facial similarity score**. A facial similarity score can range from 0 to 100, with 100 being an exact match.

By default, an Identity check will deem two faces a match when the facial similarity score is over **80**.

### Liveness threshold

ComplyCube returns a **liveness score**, representing the outcome of a liveness analysis. A liveness score can range from 0 - 100; the closer the score is to 100, the greater the confidence that your client is a real person.

By default, an Identity check will deem a client real when the liveness score is over **50**.

### Enrolled faces limit

ComplyCube returns a **previously** **enrolled** **face** indicator, asserting whether a face was registered as a different client.

By default, an Identity check will deem a face previously enrolled when registered more than **once**.

## Proof of Address Check

### Document age threshold

ComplyCube's [Proof of Address Check](/documentation/product-guides/kyc-automation-services/proof-of-address-check) aims to establish the issuing date of an eligible document using OCR. If a document is older than a specified threshold (e.g., 3 months), the **document age analysis** will be flagged for the check.

By default, a Proof of Address check will automatically flag documents older than **3 months**. You can adjust the threshold to be between 1 to 12 months.

## Age Estimation Check

### Minimum age

ComplyCube's [Age Estimation Check](/documentation/product-guides/biometric-and-liveness-verification/age-estimation-check) uses facial recognition and liveness detection technology to estimate the age of your clients.

This setting empowers **age estimation** compliance by allowing you to set a minimum acceptable age before your client is flagged.

By default, an Age Estimation check will flag anyone younger than **18 years of age**.


# Overview

Compare ComplyCube KYC and identity verification integration options across web, mobile, and third-party solutions.

ComplyCube’s identity verification (IDV) and KYC SDKs provide pre-built screens and functionality that let you easily embed complete and customizable verification flows into your mobile and web applications.

All SDKs can be orchestrated through [workflows](/documentation/product-guides/compliance-studio/workflows), ensuring consistent experiences across platforms.

To speed up development, you can also use our [integration assistant](https://portal.complycube.com/developers) to generate copy-and-paste code tailored to your setup.

{% hint style="info" %}

#### Integration Modes

The ComplyCube SDKs can be integrated in two different ways, depending on your needs:

1. **Workflow Integration (Recommended)**: Use the workflow designer to build your customer KYC journey and simply load it through the SDK. This is the preferred option for most use cases.
2. **Check-Driven Integration**: A lower-level approach where you directly control individual SDK screens and checks. It's best suited for **partners** or **advanced use cases**.
   {% endhint %}

### <img src="/files/-M7HpVwrtnuvcJW8mjXD" alt="" data-size="line"> Web Integrations

Drop in our web widgets to seamlessly embed identity verification flows into your web applications.

<table data-header-hidden><thead><tr><th width="204.5078125"></th><th></th></tr></thead><tbody><tr><td><img src="/files/-MeVnbgUFqVfLY-QX1SC" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/-MeVkD1FqGOlJlf3hwOI"><strong>Hosted Solution</strong></a></td><td><p>Redirect customers to our secure, branded, hosted KYC page.</p><p><mark style="color:$primary;"><strong>Our recommended option for web integrations.</strong></mark></p></td></tr><tr><td><img src="/files/iLAwRx2uTap1PYl1NO61" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/-M_0DOc7XDWVDpIcnV6L"><strong>Web SDK</strong></a></td><td>Embed UX-optimized IDV and KYC flows directly in your web app.</td></tr></tbody></table>

### <img src="/files/-M7HfCT69A9g_Ngct05Z" alt="" data-size="line"> Mobile Integrations

ComplyCube provides native SDKs to help you quickly embed verification flows into your mobile apps.

<table data-header-hidden><thead><tr><th width="204.73828125"></th><th></th></tr></thead><tbody><tr><td><img src="/files/IDViJk7Z7FVBpfIqos9v" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/smuFLHXxPjC1DXhoMroM"><strong>iOS SDK</strong></a></td><td>Add IDV flows to your iOS apps with a native experience.</td></tr><tr><td><img src="/files/QAQ1zKvz6LrznHqMkd16" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/U3Txnp5lpawf9IReQHej"><strong>Android SDK</strong></a></td><td>Integrate eKYC into Android apps with full platform support.</td></tr><tr><td><img src="/files/9ImG8tsJvAr3U3gVBMsC" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/miZB76QzZXoEXk6GtIL7"><strong>React Native SDK</strong></a></td><td>Bring verification flows to cross-platform React Native apps.</td></tr><tr><td><img src="/files/dQrqKzqspuwJmaU91w79" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/eAVqjz94Rhh0iBmL3ULC"><strong>Flutter SDK</strong></a></td><td>Embed IDV in Flutter apps with minimal setup.</td></tr></tbody></table>

{% hint style="info" %}
You can test the Mobile SDK immediately using the [ComplyCube Mobile app](/documentation/integration-resources/complycube-mobile-app), without needing to integrate anything.
{% endhint %}

### <img src="/files/VCakDCuxldCoavkG9rT8" alt="" data-size="line"> Third-Party Integrations

ComplyCube provides ready-made integrations, allowing you to connect verification data directly into your existing workflows without additional coding.

<table data-header-hidden><thead><tr><th width="205.12890625"></th><th></th></tr></thead><tbody><tr><td><img src="/files/6jNiQ3iFe1uK2aW3QLJa" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/IqqP3ZSIX22QvTO3VSKB"><mark style="color:blue;"><strong>Zapier</strong></mark></a></td><td>Connect ComplyCube to thousands of apps through Zapier with no code. Automate workflows to send alerts, update records, or trigger actions when verification results are received.</td></tr><tr><td><img src="/files/qfHDhPhKn76yZIUxsXqa" alt="" data-size="line"> <a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/7ZuFrqwQcIEzin8zXGJR"><mark style="color:blue;"><strong>Salesforce</strong></mark></a></td><td>Connect ComplyCube with Salesforce to sync verification results into your CRM. Automate onboarding and compliance workflows out of the box.<br><br><mark style="color:$info;"><strong>Invitation Only</strong></mark></td></tr></tbody></table>


# Branding

Customize KYC and identity verification branding across web, hosted, and mobile SDK flows with live preview and granular controls.

## Branding Overview

ComplyCube Branding helps you align identity verification, KYC, and AML onboarding experiences with your product across the **Web SDK**, **Hosted Solution**, and **mobile SDKs**.

From a single workspace, you can customize colors, logos, text, and other visual elements to deliver a consistent brand experience throughout the customer verification journey. This helps you deliver a consistent branded experience across every customer touchpoint.

The Branding Canvas includes a **live preview**, allowing you to review and validate branding updates before publishing them to production.

<figure><img src="/files/17XW2mM5KV4qYcAPV1zE" alt=""><figcaption><p>Manage colors, text, logos, and preview changes from one place.</p></figcaption></figure>

{% hint style="info" %}
Branding settings are available in the [ComplyCube Portal](https://portal.complycube.com/settings/branding), if supported by your plan.
{% endhint %}

{% hint style="info" %}
Branding settings are global by default. Supported SDKs can override selected settings during SDK initialization when you need a different experience for a specific integration.
{% endhint %}

## Customizations

Branding controls are configurable, allowing you to customize both visual styling and branded content.

### Color

Customize color tokens across the verification experience, such as **surface**, **primary**, **secondary**, **tertiary**, **error**, **info**, and **success**.

Each token can include values for the main background color and the color used on top of that background.

<figure><img src="/files/ES11pCPzSbwzaj55dqX3" alt=""><figcaption></figcaption></figure>

This lets you control the look and readability of interface elements such as:

* Screen and panel surfaces.
* Primary and secondary actions.
* Form elements, status messages, and feedback states.

### Logo

Upload supported logo assets to keep each flow aligned with your brand across different surfaces and display modes.

This can include:

* A main logo shown at the start of the verification flow.
* Footer logos for light mode and dark mode.
* A text logo fallback when image assets are not provided or cannot be loaded.

<figure><img src="/files/eFiAJQ2j7qJKhaO5i9Hc" alt=""><figcaption></figcaption></figure>

### Shape

Adjust layout spacing and corner styling to better match your product design system.

This can include controls such as:

* Padding values across size categories, such as small, medium, large, and extra large.
* Corner rounding for interface elements.
* Advanced shape settings for more granular control where supported.

<figure><img src="/files/MAUQXZVWY1lWJfmW1kxu" alt=""><figcaption></figcaption></figure>

### Text

Adjust typography styles used across the verification flow to better match your product voice and design system.

This can include text styles such as:

* Title and subtitle styles.
* Larger body text used for prominent content and input labels.
* Additional text categories exposed by the Branding workspace.

Supported text settings can include properties such as font weight, size, and line height.

<figure><img src="/files/7bj3ZSGTetTXbJuly2v8" alt=""><figcaption></figcaption></figure>

### Other

Some branding settings extend beyond visual styling and allow you to customize platform behavior and theme configuration.

Certain settings only apply to supported mobile SDKs or other mobile surfaces.

These can include:

* Behavior controls, such as haptics and animations on supported mobile platforms.
* Theme settings, including light and dark presentation modes.
* Business information, such as support email details.

<figure><img src="/files/ptcIQkL281GLnJ0YPqvn" alt=""><figcaption></figcaption></figure>

## Preview changes

The branding canvas gives you a live preview as you edit. You can validate changes before they reach production.

You can also test existing workflows and verifications in sandbox to review the applied theme in a more complete flow.

## Publishing changes

Changes made in the Branding canvas are not applied until saved.

Once saved, updated branding is automatically applied across supported ComplyCube platforms, including hosted experiences and SDKs.

## Supported platforms

Branding is supported across ComplyCube’s primary verification channels, including:

* [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide)
* [Web SDK](/documentation/sdks/web-integrations/web-sdk-quick-guide)
* [iOS SDK](/documentation/sdks/mobile-integrations/ios-sdk)
* [Android SDK](/documentation/sdks/mobile-integrations/android-sdk)
* [React Native SDK](/documentation/sdks/mobile-integrations/react-native-sdk)
* [Flutter SDK](/documentation/sdks/mobile-integrations/flutter-sdk)
* [Zapier](/documentation/sdks/third-party-integrations/zapier)
* [Salesforce](/documentation/sdks/third-party-integrations/salesforce)

## White-label support

ComplyCube supports a fully white-labeled solution for businesses that require a more deeply branded experience.

This can include the removal of ComplyCube branding. Availability depends on your plan.

## Best practices

* Keep button and text contrast high.
* Preview every change before saving.
* Use high-resolution logos that remain clear on both light and dark backgrounds.
* Keep branding consistent with the rest of your product to reduce user confusion.
* Avoid overly aggressive color combinations that may distract from key verification actions.
* Review branding updates across multiple devices and screen sizes before deployment.

## Frequently asked questions

<details>

<summary>Are branding settings global by default?</summary>

Yes.

Branding settings apply globally across supported ComplyCube integrations by default.

Supported SDKs can override selected settings during SDK initialization when needed.

</details>

<details>

<summary>Which ComplyCube integrations support branding?</summary>

Branding supports the Hosted Solution, Web SDK, and supported mobile SDKs.

Available controls can vary by platform.

</details>

<details>

<summary>Can I preview branding changes before publishing?</summary>

Yes.

The branding canvas provides a live preview while you edit.

You can also test workflows and verifications in sandbox to review the applied theme in context.

</details>

<details>

<summary>When do branding changes go live?</summary>

Branding changes do not go live until you save them.

After saving, updates apply across supported platforms.

</details>

<details>

<summary>Is white-label branding available?</summary>

Yes.

ComplyCube supports fully white-labeled KYC and identity verification experiences on supported plans.

</details>


# Hosted Solution

Build hosted KYC, AML, and identity verification flows with ComplyCube's branded verification pages.

## Overview

**ComplyCube Flow** is our secure, fully hosted KYC and identity verification solution. It provides a customizable, branded page that allows you to verify customers quickly with minimal code.

When you initiate a Flow session, a unique ComplyCube URL is generated. Redirect your customers to this URL to collect consent and guide them through the verification process. Once the session is completed, the customer is redirected back to your specified return URL.

![ComplyCube Hosted Solution](/files/K1X0pr6QaoVr9iLnXF9R)

## Benefits

Flow makes it simple to deliver a first-class KYC experience:

* **Fast to integrate**: Go live quickly with minimal engineering effort.
* **UX-optimized**: Guided, conversion-focused flows with built-in error handling.
* **Mobile ready**: Fully responsive design that works seamlessly across devices.
* **International**: Multi-language support for global coverage.
* **Customizable**: Configure verifications, stages, colors, and branding (logo and text).
* **Data-compliant**: Simplified compliance, as sensitive PII never resides on your infrastructure.

## Interactive demo

{% @arcade/embed url="<https://app.arcade.software/share/DQYWw1OnvTXJpuguEsVp>" flowId="DQYWw1OnvTXJpuguEsVp" fullWidth="false" %}

## Integration modes

The Hosted Solution can be integrated in two different ways, depending on your needs:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Workflow Integration</strong></mark></td><td>Use the Workflow Designer to build your customer KYC journey and simply load it. This is the preferred option for most use cases.</td><td><strong>Recommended</strong></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/0JwpWiOLTuOZyqV06G2s">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/0JwpWiOLTuOZyqV06G2s</a></td></tr><tr><td><mark style="color:blue;"><strong>Check-Driven Integration</strong></mark></td><td>A lower-level approach where you directly control individual journey screens and checks. It's best suited for advanced use cases.</td><td></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/wTI13zdy75hqfeD8uZzy">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/wTI13zdy75hqfeD8uZzy</a></td></tr></tbody></table>


# Workflow Integration

Integrate ComplyCube hosted KYC workflows using Flow Sessions and workflow templates.

## Overview

This guide walks you through integrating the Hosted Solution with ComplyCube [workflows](/documentation/product-guides/compliance-studio/workflows).

{% hint style="info" %}
For a quick copy-paste example, use our [integration assistant](https://portal.complycube.com/developers).
{% endhint %}

## Integration guide

<figure><img src="/files/JISLKW5TVlPqDLW7Bq3q" alt=""><figcaption><p>Flow Integration (Hosted Solution) via Workflows Guide</p></figcaption></figure>

ComplyCube's Hosted Solution requires a **Hosted Solution session** to be initiated by your backend. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Every Hosted Solution session starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

#### Example request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe",
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate a Hosted Solution session

A **Hosted Solution session** creates a unique ComplyCube URL that you can use to redirect your customers to complete their identity verification.

As part of the request, you are required to specify a [workflow template ID](https://portal.complycube.com/workflowTemplates). The Hosted Solution will automatically run the **active** version of the selected workflow.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/flow/sessions \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"CLIENT_ID",
          "workflowTemplateId": "WORKFLOW_TEMPLATE_ID",
          "successUrl": "https://www.yoursite.com/success",
          "cancelUrl": "https://www.yoursite.com/cancel"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const session = await complycube.flow.createSession("CLIENT_ID", {
    workflowTemplateId: "WORKFLOW_TEMPLATE_ID",
    successUrl: "https://www.yoursite.com/success",
    cancelUrl: "https://www.yoursite.com/cancel"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

flow_session = {
    'clientId': client.id,
    'workflowTemplateId': 'WORKFLOW_TEMPLATE_ID',
    'successUrl':'https://www.yoursite.com/success',
    'cancelUrl':'https://www.yoursite.com/cancel'
}

session = cc_api.flow.create(**flow_session)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');
$session = $ccapi->flow()->createSession([
    'clientId' => $clientId,
    'workflowTemplateId' => 'WORKFLOW_TEMPLATE_ID',
    'successUrl' => 'https://www.yoursite.com/success',
    'cancelUrl' => 'https://www.yoursite.com/cancel'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.FlowSessions;

var fSession = new FlowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var flowSession = new FlowSessionRequest {
  clientId = aClient.id,
  workflowTemplateId = "WORKFLOW_TEMPLATE_ID",
  successUrl = "http://complycube.com",
  cancelUrl = "http://complycube.com"
};

var result = fSession.CreateAsync(flowSession).Result;
```

{% endtab %}
{% endtabs %}

**Example response**

{% code overflow="wrap" %}

```json
{
    "redirectUrl": "https://id.complycube.com/test_ODdkNjhiOTU0MzY4YmE5NjRmMDMyY2E5MWYwZjgxNjMzZTcyMWJmNzU2YjZmNDQ4NmFjMTU0ZGZhYTU5MmNhY2NiNjI3ZDE4YWJkYmU2M2M3ZWYzZTlmM2M3MzgxMmM3NzZhMjVlYmQyNDI0ODdkOWQ3M2JiMjkxZTYxNzdhYmExMGEzOGRhYmM2OTIwMjgyYmEzZGY3ZDY0NWZhMjcwN2RlMTFkOTcxZWNhOWI2Zjg0NjllZGNkODVjYzMzMDA5YjdlMWY5OGIwMmZjY2UzNGI2YTMxOGQxNGZmNGFhYjczNzU0YmYwMjFkMzU1M2FjMjQ4ZDQ2ZjJjZTY4YWY0MzIxNjVlMDRjOTIyYTExMTlmMWU3YTYwMDY1NGJmYWM0NTA2MDE5NTg5NTkxYzA4MzYyYTUyM2I0NDM4OGExNWIyMTIzYTBhNDc0NDA4NWM2ZTQwMmNjMGVjMTk2YW"
}
```

{% endcode %}

{% hint style="info" %}
See [Flow Sessions API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Redirect the customer to the URL

Redirect your customer to the `redirectUrl` generated in the previous step.

Once your customer starts the flow, a [workflow session](/documentation/product-guides/compliance-studio/workflows#workflow-session) is automatically created. This session contains all captured data (documents, images, and videos) as well as progress tracking. You can view all of them through the [workflow sessions page](https://portal.complycube.com/workflowSessions) on the portal or through the API.

When the customer completes the flow:

1. ComplyCube will automatically run all verification checks configured within that workflow.
2. The customer will be redirected to the `successUrl` you provided.

You can access the results and a detailed breakdown of each check via the API or Web Portal. If you’ve **configured webhooks**, ComplyCube will send a notification upon completion of each check.
{% endstep %}
{% endstepper %}

## Branding

You can customize colors, logos, and other branding elements through the [brand settings page](https://portal.complycube.com/settings/branding), if available on your plan.


# Check-Driven Integration

Build hosted KYC verification journeys with direct control over checks handling.

## Overview

This guide walks you through integrating the Hosted Solution with ComplyCube using the check-driven approach, giving you direct control over individual verification steps.

{% hint style="info" %}
For a quick copy-paste example, use our [integration assistant](https://portal.complycube.com/developers).
{% endhint %}

{% hint style="warning" %}
You’re viewing the **check-driven** SDK guide - an approach that provides detailed control but is best suited for **partners** or **advanced use cases.**  We recommend using **workflow integration** for most implementations.
{% endhint %}

## Integration guide

<figure><img src="/files/boZ0p7m5t5RQK8c4Ddoa" alt=""><figcaption><p>Flow Integration Guide (Hosted Solution)</p></figcaption></figure>

ComplyCube's Hosted Solution requires a **Hosted Solution session** to be initiated by your backend. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Every Hosted Solution session starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe",
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate a Hosted Solution session

A **Hosted Solution session** creates a unique ComplyCube URL that you can use to redirect your customers to complete their identity verification. Once complete, your clients will be redirected to your chosen URL.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/flow/sessions \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"CLIENT_ID",
          "checkTypes": ["extensive_screening_check", "identity_check", "document_check"],
          "successUrl": "https://www.yoursite.com/success",
          "cancelUrl": "https://www.yoursite.com/cancel"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const session = await complycube.flow.createSession("CLIENT_ID", {
    checkTypes: [
      "extensive_screening_check",
      "identity_check",
      "document_check"
    ],
    successUrl: "https://www.yoursite.com/success",
    cancelUrl: "https://www.yoursite.com/cancel",
    theme: "light"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

flow_session = {
    'clientId': client.id,
    'checkTypes':[
        'extensive_screening_check',
        'identity_check',
        'document_check'
    ],
    'successUrl':'https://www.yoursite.com/success',
    'cancelUrl':'https://www.yoursite.com/cancel',
    'theme': 'light'
}

session = cc_api.flow.create(**flow_session)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');
$session = $ccapi->flow()->createSession([
    'clientId' => $clientId,
    'checkTypes' => [
        'extensive_screening_check',
        'identity_check',
        'document_check'
    ],
    'successUrl' => 'https://www.yoursite.com/success',
    'cancelUrl' => 'https://www.yoursite.com/cancel',
    'theme' => 'light'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.FlowSessions;

var fSession = new FlowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var flowSession = new FlowSessionRequest {
  clientId = aClient.id,
  checkTypes = new string[] {
    "extensive_screening_check",
    "identity_check",
    "document_check"
  },
  successUrl = "http://complycube.com",
  cancelUrl = "http://complycube.com"
};

var result = fSession.CreateAsync(flowSession).Result;
```

{% endtab %}
{% endtabs %}

**Example response**

{% code overflow="wrap" %}

```json
{
    "redirectUrl": "https://flow.complycube.com/test_ODdkNjhiOTU0MzY4YmE5NjRmMDMyY2E5MWYwZjgxNjMzZTcyMWJmNzU2YjZmNDQ4NmFjMTU0ZGZhYTU5MmNhY2NiNjI3ZDE4YWJkYmU2M2M3ZWYzZTlmM2M3MzgxMmM3NzZhMjVlYmQyNDI0ODdkOWQ3M2JiMjkxZTYxNzdhYmExMGEzOGRhYmM2OTIwMjgyYmEzZGY3ZDY0NWZhMjcwN2RlMTFkOTcxZWNhOWI2Zjg0NjllZGNkODVjYzMzMDA5YjdlMWY5OGIwMmZjY2UzNGI2YTMxOGQxNGZmNGFhYjczNzU0YmYwMjFkMzU1M2FjMjQ4ZDQ2ZjJjZTY4YWY0MzIxNjVlMDRjOTIyYTExMTlmMWU3YTYwMDY1NGJmYWM0NTA2MDE5NTg5NTkxYzA4MzYyYTUyM2I0NDM4OGExNWIyMTIzYTBhNDc0NDA4NWM2ZTQwMmNjMGVjMTk2YW"
}
```

{% endcode %}

{% hint style="info" %}
See [Flow Sessions API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Redirect the client to the URL

Redirect your client to the `redirectUrl` generated in the previous step. Once the customer completes the flow on the hosted solution:

1. ComplyCube will automatically run the checks you selected when creating the session (as specified in `checkTypes`).
2. The customer will be redirected to the `successUrl` you provided.

You can access the results and a detailed breakdown of each check via the API or Web Portal. If you’ve **configured webhooks**, ComplyCube will send a notification upon completion of each check.
{% endstep %}
{% endstepper %}

## Branding

You can customize colors, logos, and other branding elements through the [brand settings page](https://portal.complycube.com/settings/branding), if available on your plan.


# Web SDK

Embed KYC and identity verification flows in your web app with the ComplyCube Web SDK.

## Overview

The **ComplyCube Web SDK** is a lightweight JavaScript library that lets you embed identity verification (IDV) flows directly into your web applications. It provides a ready-made, user-friendly widget for capturing documents, selfies, and proof of address, while handling quality detection and fraud signals under the hood.

Use the Web SDK if you want to run verification flows inside your web app, instead of redirecting users to the [Hosted Solution](/documentation/sdks/web-integrations/hosted-solution-quick-guide).

## Benefits

The SDK offers several benefits:

* **Flexible integration**: Orchestrate full journeys with [workflows](/documentation/product-guides/compliance-studio/workflows) or configure individual stages (selfie, document).
* **Biometric checks**: Liveness via photo and video, with spoof detection.
* **Smart quality checks**: Real-time quality checks to reduce errors and ensure optimal input.
* **Custom branding**: Adapt colors, text, and logos to match your app.
* **Global-ready**: Multi-language support with localized UI labels.

## Interactive demo

{% @arcade/embed url="<https://app.arcade.software/share/kjtci521jMvvMXDZIr7o>" flowId="kjtci521jMvvMXDZIr7o" fullWidth="false" %}

## Integration modes

The Web SDK can be integrated in two different ways, depending on your needs:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Workflow Integration</strong></mark></td><td>Use the Workflow Designer to build your customer KYC journey and simply load it through the SDK. This is the preferred option for most use cases.</td><td><strong>Recommended</strong></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/5pxzOsDPK5mo6paNvcWq">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/5pxzOsDPK5mo6paNvcWq</a></td></tr><tr><td><mark style="color:blue;"><strong>Check-Driven Integration</strong></mark></td><td>A lower-level approach where you directly control individual SDK screens and checks. It's best suited for advanced use cases.</td><td></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/4zJ0OweD3fA2VjrazaSB">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/4zJ0OweD3fA2VjrazaSB</a></td></tr></tbody></table>


# Workflow Integration

Integrate KYC workflows in your web app using the ComplyCube Web SDK.

## Overview

This guide walks you through integrating the Web SDK with ComplyCube [workflows](/documentation/product-guides/compliance-studio/workflows).

{% hint style="info" %}
For a quick copy-paste example, use our [integration assistant](https://portal.complycube.com/developers).
{% endhint %}

## Integration flow

The Web SDK runs as part of your frontend but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### **Import and mount the SDK**

Add the JS and CSS files, then mount the SDK in your web app.
{% endstep %}

{% step %}

#### Capture documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform verification checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/ZKVUgYKu9G0ym2abunPD" alt=""><figcaption><p>Web SDK Integration via Workflows Guide</p></figcaption></figure>

## Integration guide

{% stepper %}
{% step %}

#### Create a client

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token links the SDK session to the client. Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"CLIENT_ID",
          "referrer": "https://www.example.com/*"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const token = await complycube.token.generate("CLIENT_ID", {
    referrer: "https://www.example.com/*"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

token = cc_api.tokens.create('CLIENT_ID','https://www.example.com/*')
```

{% endtab %}

{% tab title="PHP" %}

```php
 use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$report = $ccapi->tokens()->generate('CLIENT_ID', 'https://www.example.com/*');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  referrer = "https://www.example.com/*"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Import the SDK

To import our Web SDK, you need to include it in your target page HTML:

```html
<!DOCTYPE html>
<html>
  <head>
    ...
    <!-- Importing the Javascript library -->
    <script src="complycube.min.js"></script>

    <!-- Importing the default CSS -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
     <!-- This is where the Web SDK will be mounted -->
    <div id="complycube-mount"></div>
  </body>
</html>
```

<details>

<summary><strong>Loading the SDK with Integrity</strong> <em>(Optional)</em></summary>

For additional security, you can optionally load the ComplyCube Web SDK using **Subresource Integrity (SRI)**. This allows the browser to verify that the JavaScript and CSS files have not been modified by validating them against cryptographic checksums.

#### **Retrieve the latest SDK integrity values**

To ensure you always use the latest supported SDK version and integrity hashes, retrieve the asset metadata from the Web SDK info endpoint.

**Example request**

```bash
curl -X POST https://api.complycube.com/v1/webSdk/latest \
     -H 'Authorization: <YOUR_API_KEY>'
```

**Example response**

The response includes the URLs and corresponding integrity values for both the JavaScript and CSS assets.

{% code overflow="wrap" %}

```json
{
  "js": {
    "url": "<JAVASCRIPT_ASSET_URL>/complycube.min.js",
    "integrity": "sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
  },
  "css": {
    "url": "<CSS_ASSET_URL>/style.css",
    "integrity": "sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
  }
}
```

{% endcode %}

#### **Import the SDK using integrity attributes**

Use the returned values to load the SDK in your HTML with `integrity` and `crossorigin` attributes:

```html
<!DOCTYPE html>
<html>
  ...
  <head>
    <!-- Importing the Javascript library -->
    <script
      src="<JAVASCRIPT_ASSET_URL>/sdk.min.js"
      integrity="sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
      crossorigin="anonymous">
    </script>

    <!-- Importing the default CSS -->
    <link
      rel="stylesheet"
      href="<CSS_ASSET_URL>/style.css"
      integrity="sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
      crossorigin="anonymous">
  </link>
  </head>
  
  <!-- This is where the Web SDK will be mounted -->
  <body>
    <div id="complycube-mount"></div>
  </body>
</html>
```

{% hint style="info" %}

#### Notes

* Using SRI is ***optional***, but recommended for environments with stricter security requirements.
* The crossorigin="anonymous" attribute is required when using SRI with assets served from a different origin.
* Integrity values may change when the SDK is updated. Always retrieve the latest values from the endpoint.
  {% endhint %}

</details>

{% hint style="info" %}
The links to `complycube.min.js` and `style.css` can be found in your [developers portal](https://portal.complycube.com/developers/webSdk).
{% endhint %}
{% endstep %}

{% step %}

#### Mount the SDK

As part of mounting the Web SDK, you are required to specify a [workflow template ID](https://portal.complycube.com/workflowTemplates). The SDK will automatically run the **active** version of the selected workflow.

Once the verification flow is complete, customers are redirected back to the return URL you specify.

With the generated token, the Web SDK can be initialized in your frontend using the following JavaScript code:

```javascript
ComplyCube.mount({
  token: '<YOUR_WEB_SDK_TOKEN>',
  containerId: 'complycube-mount',
  workflowTemplateId: "WORKFLOW_TEMPLATE_ID",
  onComplete: function(data) {    
    // Have your backend notify ComplyCube once the workflow is complete
    // to trigger the verification checks
    console.info('Capture complete');
  },
  onModalClose: function() {
    // Handle the modal closure attempt
  },
  onError: function ({ type, message }) {
    if (type === 'token_expired') {
      // Request a new SDK token
    } else {
      // Handle other errors
      console.error(message);
    }
  }
});
```

{% hint style="info" %}
The SDK mount parameters are described in the [SDK Settings](#settings) section below.
{% endhint %}

{% hint style="info" %}

#### Referrer policy

To enable successful communication between the SDK and our servers, your web page's **Referrer Policy** header should be set to `strict-origin-when-cross-origin`. This ensures that the referrer information is securely transmitted during HTTP requests.

You can either do it programmatically or add it directly to the web page as follows:\
`<meta name="referrer" content="strict-origin-when-cross-origin">`
{% endhint %}
{% endstep %}

{% step %}

#### Perform verification checks

Once your customer starts the flow, a [workflow session](/documentation/product-guides/compliance-studio/workflows#workflow-session) is automatically created. This session contains all captured data (documents, images, and videos) as well as progress tracking. You can view all of them through the [workflow sessions page](https://portal.complycube.com/workflowSessions) on the portal or through the API.

When the flow finishes, the SDK triggers the `onComplete` callback. The callback provides a `data` object that includes the `workflowSessionId`. Your backend should use this ID to notify ComplyCube that the [workflow has completed](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session), which in turn runs the verification checks defined in the workflow.

If you have [set up webhooks ](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook)as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a workflow session completes.

You can retrieve the details of a workflow session by calling the [retrieve workflow session request](/documentation/api-reference/core-resources/workflow-sessions/get-a-workflow-session).

**Example of a complete workflow session request**

{% tabs %}
{% tab title="cURL" %}

```javascript
curl -X POST https://api.complycube.com/v1/workflowSessions/{:wfSessionId}/complete \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.complete("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.complete('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->complete('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.CompleteAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## SDK reference

This section describes all configurable settings, callbacks, lifecycle methods, and branding options available in the ComplyCube Web SDK.

### Settings

<table><thead><tr><th width="218.09765625">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>token</code></td><td>The SDK token generated by your backend. This is <strong>required</strong>.<br><br><strong>Type</strong>: <code>string</code></td></tr><tr><td><code>workflowTemplateId</code></td><td><p>The ID of the <a href="https://portal.complycube.com/workflowTemplates">workflow template</a> to load for this the session. This is <strong>required</strong>.</p><p><strong>Type:</strong> <code>string</code></p></td></tr><tr><td><code>containerId</code></td><td><p>The ID of the container element where the SDK mounts. This must be an empty element.</p><p><strong>Type:</strong> <code>string</code><br><strong>Default value</strong>: <code>complycube-mount</code></p></td></tr><tr><td><code>useModal</code></td><td>This defines whether the UI screens load into a modal instead of inline.<br><br><strong>Type:</strong> <code>boolean</code><br><strong>Default value</strong>: <code>true</code></td></tr><tr><td><code>useFullScreen</code></td><td>This defines whether the SDK loads in full-screen mode.<br><br><strong>Type:</strong> <code>boolean</code><br><strong>Default value</strong>: <code>false</code></td></tr><tr><td><code>disableClientAnalytics</code></td><td><p>This defines whether we track client analytics or not.<br></p><p><strong>Type:</strong> <code>boolean</code><br><strong>Default value</strong>: <code>false</code></p></td></tr></tbody></table>

### Callback

Callbacks let you respond to SDK lifecycle events.

<table><thead><tr><th width="218.0234375">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>onComplete</code></td><td>Triggered after the customer completes the verification flow. This is used to invoke a <a href="/spaces/kAhgmUKSf8CFUFVL3GEe/pages/8efGZrnBQn2JW1xDuW7Y">workflow session complete request</a>.</td></tr><tr><td><code>onError</code></td><td><p>Triggered when an error occurs. The error object has two attributes:</p><ul><li><p><code>type</code>: This can be:</p><ul><li><code>exception</code></li><li><code>token_expired</code> : indicates the token has expired. When this occurs, a new <strong>SDK token must be provided</strong>.</li></ul></li><li><code>message</code>: Description of the error.</li></ul></td></tr><tr><td><code>onExit</code></td><td>This callback is triggered when your client exits before completing the flow. It will return the exit reason, e.g., <code>USER_CONSENT_NOT_GRANTED</code>.</td></tr><tr><td><code>onModalClose</code></td><td>Triggered when the customer tries to close the modal. You can allow or prevent closure by updating the <code>isModalOpen</code> attribute using <a href="#updating-settings">updateSettings</a>.</td></tr></tbody></table>

### Updating settings

A number of settings can be updated at runtime as follows:

```javascript
complycube = ComplyCube.mount({...});

// Replace the SDK token
complycube.updateSettings({ token: "NEW_SDK_TOKEN" });
...
// Open the modal
complycube.updateSettings({ isModalOpen: true });

//Close the modal
complycube.updateSettings({ isModalOpen: false });

```

### Unmounting the SDK

If you are using the SDK in a Single Page Application (SPA), you can call the unmount function to remove the SDK and reset its state.

```javascript
complycube = ComplyCube.mount({...});
...
complycube.unmount()
```

## Branding

You can customise colours, logos, and other branding elements through the [branding settings page](https://portal.complycube.com/settings/branding), if available on your plan.


# Check-Driven Integration

Build check-driven KYC and identity verification flows with the ComplyCube Web SDK.

## Overview

This guide walks you through integrating the Web SDK with ComplyCube using the check-driven approach, giving you direct control over individual verification steps.

{% hint style="info" %}
For a quick copy-paste example, use our [integration assistant](https://portal.complycube.com/developers).
{% endhint %}

{% hint style="warning" %}
You’re viewing the **check-driven** SDK guide - an approach that provides detailed control but is best suited for **partners** or **advanced use cases.**  We recommend using **workflow integration** for most implementations.
{% endhint %}

## Integration flow

The Web SDK runs as part of your frontend but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### **Import and mount the SDK**

Add the JS and CSS files, then mount the SDK in your web app.
{% endstep %}

{% step %}

#### Capture documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform verification checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

![Web SDK Integration Flow](/files/-M_1rrWcXBID12ktWYA6)

## Integration guide

{% stepper %}
{% step %}

#### Create a client

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token links the SDK session to the client. Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "clientId":"CLIENT_ID",
          "referrer": "https://www.example.com/*"
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const token = await complycube.token.generate("CLIENT_ID", {
    referrer: "https://www.example.com/*"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

token = cc_api.tokens.create('CLIENT_ID','https://www.example.com/*')
```

{% endtab %}

{% tab title="PHP" %}

```php
 use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$report = $ccapi->tokens()->generate('CLIENT_ID', 'https://www.example.com/*');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  referrer = "https://www.example.com/*"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Import the SDK

To import our Web SDK, you need to include it in your target page HTML:

```html
<!DOCTYPE html>
<html>
  <head>
    ...
    <!-- Importing the Javascript library -->
    <script src="complycube.min.js"></script>

    <!-- Importing the default CSS -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
     <!-- This is where the Web SDK will be mounted -->
    <div id="complycube-mount"></div>
  </body>
</html>

```

<details>

<summary><strong>Loading the SDK with Integrity</strong> <em>(Optional)</em></summary>

For additional security, you can optionally load the ComplyCube Web SDK using **Subresource Integrity (SRI)**. This allows the browser to verify that the JavaScript and CSS files have not been modified by validating them against cryptographic checksums.

#### **Retrieve the latest SDK integrity values**

To ensure you always use the latest supported SDK version and integrity hashes, retrieve the asset metadata from the Web SDK info endpoint.

**Example request**

```bash
curl -X POST https://api.complycube.com/v1/webSdk/latest \
     -H 'Authorization: <YOUR_API_KEY>'
```

**Example response**

The response includes the URLs and corresponding integrity values for both the JavaScript and CSS assets.

{% code overflow="wrap" %}

```json
{
  "js": {
    "url": "<JAVASCRIPT_ASSET_URL>/complycube.min.js",
    "integrity": "sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
  },
  "css": {
    "url": "<CSS_ASSET_URL>/style.css",
    "integrity": "sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
  }
}
```

{% endcode %}

#### **Import the SDK using integrity attributes**

Use the returned values to load the SDK in your HTML with `integrity` and `crossorigin` attributes:

```html
<!DOCTYPE html>
<html>
  ...
  <head>
    <!-- Importing the Javascript library -->
    <script
      src="<JAVASCRIPT_ASSET_URL>/sdk.min.js"
      integrity="sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
      crossorigin="anonymous">
    </script>

    <!-- Importing the default CSS -->
    <link
      rel="stylesheet"
      href="<CSS_ASSET_URL>/style.css"
      integrity="sha384-<INTEGRITY_HASH_1> sha384-<INTEGRITY_HASH_2>"
      crossorigin="anonymous">
  </link>
  </head>
  
  <!-- This is where the Web SDK will be mounted -->
  <body>
    <div id="complycube-mount"></div>
  </body>
</html>
```

{% hint style="info" %}

#### Notes

* Using SRI is ***optional***, but recommended for environments with stricter security requirements.
* The crossorigin="anonymous" attribute is required when using SRI with assets served from a different origin.
* Integrity values may change when the SDK is updated. Always retrieve the latest values from the endpoint.
  {% endhint %}

</details>

{% hint style="info" %}
The links to `complycube.min.js` and `style.css` can be found in your [developers portal](https://portal.complycube.com/developers/webSdk).
{% endhint %}
{% endstep %}

{% step %}

#### Mount the SDK

With the generated SDK token, the Web SDK can be initialized in your frontend using the following JavaScript code:

```javascript
ComplyCube.mount({
  token: '<YOUR_WEB_SDK_TOKEN>',
  containerId: 'complycube-mount',
  stages: [
    'intro',
    'documentCapture',
    {
      name: 'faceCapture',
      options: {
        mode: 'video'
      }
    },
    'completion'
  ],
  onComplete: function(data) {
    // Using the data attributes returned, request your
    // backend server to perform the necessary ComplyCube checks
    console.info('Capture complete');
  },
  onModalClose: function() {
    // Handle the modal closure attempt
  },
  onError: function ({ type, message }) {
    if (type === 'token_expired') {
      // Request a new SDK token
    } else {
      // Handle other errors
      console.error(message);
    }
  }
});
```

{% hint style="info" %}
The SDK mount parameters are described in the [SDK settings](#settings) section below.
{% endhint %}

{% hint style="info" %}

#### Referrer policy

To enable successful communication between the SDK and our servers, your web page's **Referrer Policy** header should be set to `strict-origin-when-cross-origin`. This ensures that the referrer information is securely transmitted during HTTP requests.

You can either do it programmatically or add it directly to the web page as follows:\
`<meta name="referrer" content="strict-origin-when-cross-origin">`
{% endhint %}
{% endstep %}

{% step %}

#### Perform checks

Using the `data` returned by the SDK, via the `onComplete` callback, you can now instruct your backend server to run the appropriate checks using the [create a check endpoint](https://docs.complycube.com/api-reference/checks/create-a-check).

For instance, use:

* `documentCapture.documentId` to run a [document check](https://docs.complycube.com/api-reference/check-types/document-check).
* `documentCapture.documentId` and `faceCapture.livePhotoId` to run an[ identity check](https://docs.complycube.com/api-reference/check-types/identity-check).
* `documentCapture.documentId` and `faceCapture.liveVideoId` to run an [enhanced identity check](https://docs.complycube.com/api-reference/check-types/enhanced-identity-check).
* `poaCapture.documentId` to run a [proof of address check](https://docs.complycube.com/api-reference/check-types/proof-of-address-check).

If you have [set up webhooks ](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook)as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](/documentation/api-reference/core-resources/checks/create-a-check).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```javascript
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## SDK reference

This section describes all configurable settings, callbacks, lifecycle methods, and branding options available in the ComplyCube Web SDK.

### Settings

<table><thead><tr><th width="218.09765625">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>token</code></td><td>The SDK token generated by your backend. This is <strong>required</strong>.<br><br><strong>Type</strong>: <code>string</code></td></tr><tr><td><code>containerId</code></td><td><p>The ID of the container element where the SDK mounts. This must be an empty element.</p><p><strong>Type:</strong> <code>string</code><br><strong>Default value</strong>: <code>complycube-mount</code></p></td></tr><tr><td><code>useModal</code></td><td>This defines whether the UI screens load into a modal instead of inline.<br><br><strong>Type:</strong> <code>boolean</code><br><strong>Default value</strong>: <code>true</code></td></tr><tr><td><code>useFullScreen</code></td><td>This defines whether the SDK loads in full-screen mode.<br><br><strong>Type:</strong> <code>boolean</code><br><strong>Default value</strong>: <code>false</code></td></tr><tr><td><code>disableClientAnalytics</code></td><td><p>This defines whether we track client analytics or not.<br></p><p><strong>Type:</strong> <code>boolean</code><br><strong>Default value</strong>: <code>false</code></p></td></tr><tr><td><code>stages</code></td><td><p>This is the list of stages your clients will go through. Stages can be provided as strings or as objects. See <a href="#stages">Stages</a> below to learn more.<br></p><p><strong>Type:</strong> <code>array[object]</code> or <code>array[string]</code></p><p><strong>Default values</strong>: <code>['intro', 'faceCapture, 'documentCapture', 'completion']</code></p></td></tr><tr><td><code>language</code></td><td><p>The UI language. Valid values include:<br></p><p><code>en</code> , <code>ar</code>, <code>br</code>, <code>de</code>, <code>es</code>, <code>fr</code>, <code>hi</code>, <code>hk</code>, <code>id</code>, <code>it</code>, <code>ja</code>, <code>ko</code>, <code>nl</code>, <code>no</code>, <code>pl</code>, <code>pt</code>, <code>sv</code>, <code>th</code>, <code>vi</code>, <code>zh</code><br></p><p><strong>Type:</strong> <code>string</code><br><strong>Default value</strong>: <code>en</code></p></td></tr></tbody></table>

### Callback

Callbacks let you respond to SDK lifecycle events.

<table><thead><tr><th width="218.0234375">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>onComplete</code></td><td><p>Triggered after the client completes the verification flow. Typically used to trigger a check on your backend.<br></p><p>Depending on the stages provided, <code>data</code> may include the following attributes:<br></p><ul><li><p><code>documentCapture</code></p><ul><li><code>documentId</code>: ID of the captured document.</li><li><code>documentType:</code> Type of document uploaded.</li></ul></li><li><p><code>faceCapture</code></p><ul><li><code>liveVideoId</code>: ID of the captured video. <strong>OR</strong>;</li><li><code>livePhotoId</code>: ID of the captired photo.</li></ul></li><li><p><code>poaCapture</code></p><ul><li><code>documentId</code>: ID of the uploaded proof of address document.</li><li><code>documentType</code>: Type of the uploaded proof of address document.</li></ul></li></ul></td></tr><tr><td><code>onError</code></td><td><p>Triggered when an error occurs. The error object has two attributes:</p><ul><li><p><code>type</code>: This can be:</p><ul><li><code>exception</code></li><li><code>token_expired</code> : indicates the token has expired. When this occurs, a new <strong>SDK token must be provided</strong>.</li></ul></li><li><code>message</code>: Description of the error.</li></ul></td></tr><tr><td><code>onExit</code></td><td>This callback is triggered when your client exits before completing the flow. It will return the exit reason, e.g., <code>USER_CONSENT_NOT_GRANTED</code>.</td></tr><tr><td><code>onModalClose</code></td><td>Triggered when the client tries to close the modal. You can allow or prevent closure by updating the <code>isModalOpen</code> attribute using <a href="#updating-settings">updateSettings</a>.</td></tr></tbody></table>

### Updating settings

A number of settings can be updated at runtime as follows:

```javascript
complycube = ComplyCube.mount({...});

// Replace the SDK token
complycube.updateSettings({ token: "NEW_SDK_TOKEN" });
...
// Open the modal
complycube.updateSettings({ isModalOpen: true });

//Close the modal
complycube.updateSettings({ isModalOpen: false });

```

### Unmounting the SDK

If you are using the SDK in a Single Page Application (SPA), you can call the unmount function to remove the SDK and reset its state.

```javascript
complycube = ComplyCube.mount({...});
...
complycube.unmount()
```

## Stages

The `stages` array defines the verification flow. Each stage can be passed as a **string** or as an **object** with options.

#### Supported stage names

* `intro`: Welcome screen.
* `userConsentCapture`: Capture customer consent.
* `documentCapture`: Capture ID documents.
* `faceCapture`: Capture selfies or liveness videos.
* `poaCapture`: Capture proof of address document.
* `completion`: End of flow.

{% hint style="info" %}
When `userConsentCapture` is enabled, always handle the `onExit` callback if the client declines consent.
{% endhint %}

{% hint style="info" %}
Please make sure you pass the [`clientConsent`](https://docs.complycube.com/api-reference/checks) parameter when consent is granted by your client.
{% endhint %}

When a stage is passed as **object**, it will have two attributes, `name` and `options`.

### Name

This is the [stage name](#supported-stage-names)

### Options

This allows you to customize each stage as follows:

<table><thead><tr><th width="171.09765625">Stage Name</th><th>Options</th></tr></thead><tbody><tr><td><code>intro</code></td><td><ul><li><code>heading</code>: Change the intro screen heading.</li><li><code>message</code>: A list of messages to display on the intro screen. Max size <strong>3</strong>.</li><li><code>startButtonText</code>: Change the text of the start button on the intro screen.</li></ul></td></tr><tr><td><code>documentCapture</code></td><td><ul><li><code>crossDeviceOnly</code>: A boolean that indicates whether to force users to capture their document using their phone. This removes the document upload option.</li><li><p><code>documentTypes</code>: The list of ID document types visible to the user. Valid document types include:</p><ul><li><code>passport</code></li><li><code>driving_license</code></li><li><code>national_identity_card</code></li><li><code>residence_permit</code></li></ul><p><br>Each value can be either a <strong>boolean</strong> or a <strong>country object</strong>. A boolean toggles the visibility of the document type, while a country object specifies the issuing country for non-passport documents, bypassing the country selection screen. The country value is the <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">two-letter country ISO code</a>.</p></li></ul></td></tr><tr><td><code>faceCapture</code></td><td><ul><li><code>mode</code>: The mode of the facial capture. Possible values are: <code>photo</code> or <code>video</code>.</li></ul></td></tr><tr><td><code>poaCapture</code></td><td><ul><li><p><code>documentTypes</code>: The list of Proof of Address (POA) document types visible to the client. Valid POA document types include:</p><ul><li><code>bank_statement</code></li><li><code>utility_bill</code></li></ul></li></ul><p>The value of each document type is a boolean that toggles the visibility of the document type.</p></td></tr><tr><td><code>completion</code></td><td><ul><li><code>heading</code>: Change the completion screen heading.</li><li><code>message</code>: A message to display on the completion screen. Max size <strong>1</strong>.</li></ul></td></tr></tbody></table>

#### Example options object

```javascript
stages: [
  {
    name: "intro",
    options: {
      heading: "We need to verify your identity",
      message: [
        "In order to open an account, we need to check a few things.",
        "This will take only a moment",
      ],
      startButtonText: "Start Verification"
    },
  },
  "userConsentCapture",
  {
    name: "documentCapture",
    options: {
      crossDeviceOnly: true,
      documentTypes: {
        passport: true,
        driving_license: false,
        national_identity_card: true,
        residence_permit: {
          country: "GB",
        },
      },
    },
  },
  {
    name: "faceCapture",
    options: {
      mode: "video"
    },
  },
  {
    name: "poaCapture",
    options: {
      documentTypes: {
        bank_statement: true,
        utility_bill: false,
      },
    },
  },
  {
    name: "completion",
    options: {
      heading: "Thank you for completing the process",
      message: ["we will get in touch shortly"]
    },
  }
];

```

## Branding

You can customize the SDK’s look and feel with the `branding` object. It comprises the attributes outlined below.

### Appearance

The `appearance` object allows you to customize the color scheme of the SDK with CSS values (e.g. RGBA, Hex). Customizable attributes include:

<table><thead><tr><th width="314.77779343108637">Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>infoPopupColor</code></td><td>Warning popup background color.</td></tr><tr><td><code>infoPopupTextColor</code></td><td>Warning popup background color.</td></tr><tr><td><code>infoPopupLinkHoverColor</code></td><td>Warning popup fallback Link on hover background color.</td></tr><tr><td><code>infoPopupLinkActiveColor</code></td><td>Warning popup fallback Link active background color.</td></tr><tr><td><code>errorPopupColor</code></td><td>Error popup background color.</td></tr><tr><td><code>errorPopupTextColor</code></td><td>Error popup text color.</td></tr><tr><td><code>errorPopupLinkHoverColor</code></td><td>Error popup fallback Link on hover background color.</td></tr><tr><td><code>errorPopupLinkActiveColor</code></td><td>Error popup fallback Link active background color.</td></tr><tr><td><code>cameraButtonHoverColor</code></td><td>Camera button on hover background color.</td></tr><tr><td><code>cameraButtonActiveColor</code></td><td>Camera button active background color.</td></tr><tr><td><code>iconButtonActiveColor</code></td><td>Icon button active background color.</td></tr><tr><td><code>iconButtonHoverColor</code></td><td>Icon button on hover background color.</td></tr><tr><td><code>primaryButtonColor</code></td><td>Primary button background color.</td></tr><tr><td><code>primaryButtonTextColor</code></td><td>Primary button text color.</td></tr><tr><td><code>primaryButtonActiveColor</code></td><td>Primary button active background color.</td></tr><tr><td><code>primaryButtonHoverColor</code></td><td>Primary button on hover background color.</td></tr><tr><td><code>primaryButtonBorderColor</code></td><td>Primary button border color.</td></tr><tr><td><code>secondaryButtonColor</code></td><td>Secondary button background color.</td></tr><tr><td><code>secondaryButtonTextColor</code></td><td>Secondary button text color.</td></tr><tr><td><code>secondaryButtonActiveColor</code></td><td>Secondary button active background color.</td></tr><tr><td><code>secondaryButtonHoverColor</code></td><td>Secondary button on hover background color.</td></tr><tr><td><code>secondaryButtonBorderColor</code></td><td>Secondary button border color.</td></tr><tr><td><code>documentSelectorColor</code></td><td>Document selector background color.</td></tr><tr><td><code>documentSelectorTextColor</code></td><td>Document selector text color.</td></tr><tr><td><code>documentSelectorActiveBorderColor</code></td><td>Document selector active background color.</td></tr><tr><td><code>documentSelectorHoverBorderColor</code></td><td>Document selector on the hover background color.</td></tr><tr><td><code>linkHoverColor</code></td><td>Link on the hover background color.</td></tr><tr><td><code>linkActiveColor</code></td><td>Link active background color.</td></tr><tr><td><code>linkUnderlineColor</code></td><td>Link underline color.</td></tr><tr><td><code>linkHoverTextColor</code></td><td>Link on the hover text color.</td></tr><tr><td><code>bodyTextColor</code></td><td>SDK content text color.</td></tr><tr><td><code>headingTextColor</code></td><td>SDK heading text color.</td></tr><tr><td><code>subheadingTextColor</code></td><td>SDK subheading text color.</td></tr></tbody></table>

### Logo

The `logo` object has the following attributes:

* `lightLogoUrl`: URL for your logo's light version.
* `darkLogoUrl`:  URL for your logo's dark version.

#### Example of logo branding

```javascript
branding: {
  appearance: {
    primaryButtonColor: '#FF0000',
  },
  logo: {
    lightLogoUrl: 'light_logo_url',
    darkLogoUrl: 'dark_logo_url',
  }
},
```

### Text Brand

The `textBrand` attribute represents the textual format of your brand.

#### Example of text branding

```javascript
branding: {
  appearance: {
    primaryButtonColor: '#FF0000',
  },
  textBrand: 'Acme Bank'
}
```

{% hint style="info" %}
If `logo` and `textBrand` attributes are specified at the same time, `logo` takes precedence.
{% endhint %}


# iOS SDK

Add native KYC and identity verification flows to iOS apps with the ComplyCube SDK.

## Overview

The **ComplyCube iOS SDK** allows you to embed a complete identity verification flow directly into your iOS application using native UI components powered by ComplyCube’s certified machine learning models.

Designed for easy integration, the SDK handles everything from document capture and biometric liveness checks to proof of address and NFC authentication. It’s optimised for speed and accuracy, with features like auto-capture and real-time feedback.

{% embed url="<https://www.youtube.com/watch?v=n8kAGXQykkA>" %}
ComplyCube Mobile SDK Demo
{% endembed %}

## Benefits

The SDK offers several benefits:

* **Mobile-native flow:** Frictionless user experience using mobile-native UI components. Includes guided flows for capturing selfies, videos, identity documents, and proof of address.
* **Flexible integration**: Use [workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate complete verification journeys with minimal code, or configure individual stages (e.g. selfie, document, NFC) for more granular control.
* **Biometric verification**: Supports photo and video-based liveness checks (**PAD Level 2 certified)** using passive and active techniques to detect spoofing.
* **Document & NFC verification:** Supports OCR and RFID reading from passports, ID cards, and other chip-enabled documents. Cross-checks encrypted chip data for added assurance.
* **Smart auto-capture**: Automatically captures selfies and documents with real-time quality checks, reducing user errors and ensuring optimal input for verification.
* **Custom branding**: Customize accent colors, text, and logos to match your app’s visual identity.
* **Global-ready**: Built-in support for multiple languages and localized UI labels.

## Requirements

* **Swift 5**.
* **iOS 13** and above.
* **Xcode 13** and above.

## Integration modes

The iOS SDK can be integrated in two different ways, depending on your needs:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Workflow Integration</strong></mark></td><td>Use the Workflow Designer to build your customer KYC journey and simply load it through the SDK. This is the preferred option for most use cases.</td><td><strong>Recommended</strong></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/JvFsUoa0Tk6rvhbsx0cX">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/JvFsUoa0Tk6rvhbsx0cX</a></td></tr><tr><td><mark style="color:blue;"><strong>Check-Driven Integration</strong></mark></td><td>A lower-level approach where you directly control individual SDK screens and checks. It's best suited for advanced use cases.</td><td></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/sloBuiOxGPJPtche3Fyw">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/sloBuiOxGPJPtche3Fyw</a></td></tr></tbody></table>


# Workflow Integration

Integrate KYC workflows in iOS apps using the ComplyCube iOS SDK.

## Overview

This guide walks you through integrating the **iOS SDK** with ComplyCube [workflows](/documentation/product-guides/compliance-studio/workflows).

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture data, documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/QphA3xsRYHb17fG8zplz" alt=""><figcaption><p>Mobile SDK Integration via Workflows Guide</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-ios-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

1. Before using the ComplyCube SDK, install the **CocoaPods** plugin by running the following command in your terminal:<br>

   ```bash
   sudo gem install cocoapods
   ```

2. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
   source 'https://github.com/CocoaPods/Specs.git'
   …
   platform :iOS, ’13.0’

   target ‘YourApp’ do
       …
     pod 'ComplyCubeMobileSDK'
   end

   post_install do |installer|
       installer.pods_project.targets.each do |target|
           target.build_configurations.each do |build_configuration|
               build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
               build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
               build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.1'
               build_configuration.build_settings['ARCHS'] = ['$(ARCHS_STANDARD)', 'x86_64']
               build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = ['arm64', 'arm64e', 'armv7', 'armv7s']
               build_configuration.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES'
           end
       end
   end
   ```

\
**Application permissions**

Our SDK uses the device camera and microphone for capture. You must add the following keys to your application `Info.plist` file.

1. `NSCameraUsageDescription`

```xml
<key>NSCameraUsageDescription</key>
<string>Used to capture facials biometrics and documents</string>
```

2. `NSMicrophoneUsageDescription`

```xml
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture video biometrics</string>
```

{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

This must be done on your **mobile app backend** server, not the mobile app itself.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables customers to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Initialize the SDK

As part of initializing the SDK, you are required to specify a [workflow template ID](https://portal.complycube.com/workflowTemplates). The SDK will automatically run the **active** version of the selected workflow.

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withSDKToken("SDK_TOKEN")
  .withClientId("CLIENT_ID")
  .withWorkflowTemplateId("WORKFLOW_TEMPLATE_ID")
  .start(fromVc: self)

var clientAuth = ClientAuth("SDK_TOKEN", "CLIENT_ID")
```

{% endstep %}

{% step %}

#### Perform verifications

Once your customer starts the flow, a [workflow session](/documentation/product-guides/compliance-studio/workflows#workflow-session) is automatically created. This session contains all captured data (documents, images, and videos) as well as progress tracking. You can view all of them through the [workflow sessions page](https://portal.complycube.com/workflowSessions) on the portal or through the API.

When the flow finishes, the SDK triggers the `onSuccess` callback. The callback provides a `data` object that includes the `workflowSessionId`. Your **mobile backend** should use this ID to notify ComplyCube that the [workflow has completed](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session), which in turn runs the verification checks defined in the workflow.

If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a workflow session completes.

#### Example of a complete workflow session request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/workflowSessions/{:wfSessionId}/complete \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.complete("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.complete('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->complete('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.CompleteAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve the workflow session details and associated check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

You can retrieve the details of a workflow session by calling the [retrieve workflow session request](/documentation/api-reference/core-resources/workflow-sessions/get-a-workflow-session).

To retrieve the check results, you can perform a [get check request](/documentation/api-reference/core-resources/checks/get-a-check).

**Example of a workflow session retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/workflowSessions/{:workflowSessionId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.get("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.get('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->get('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.GetAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}

**Example of a check retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

{% hint style="info" %}
To use this feature, your app must have the **`Near Field Communication Tag Reading`** capability enabled. To add this capability to your app, refer to [Apple's guide here](https://help.apple.com/xcode/mac/current/#/dev88ff319e7).
{% endhint %}

1. Install the **CocoaPods Artifactory** plugin by running the following command in your terminal:<br>

   ```bash
   gem install cocoapods-art
   ```

2. To add the library, copy your repository credentials into a `.netrc` file to your home directory and setup the repository:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">pod repo-art add cc-cocoapods-release-local "https://complycuberepo.jfrog.io/artifactory/api/pods/cc-cocoapods-release-local"
   </code></pre>

   \
   Remember to fetch your credentials from **JFrog** using the **Set Me Up** button [here](https://complycuberepo.jfrog.io/ui/repos/tree/General/cc-cocoapods-release-local).<br>

3. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
    plugin 'cocoapods-art', :sources => [
      'cc-cocoapods-release-local',
      'trunk'
    ]
    ...
    platform :ios, '13.0' # Or above

    target 'YourApp' do
      use_frameworks!
      use_modular_headers!
      ...
      pod 'ComplyCubeMobileSDK', '2.0.x-nfc'
      ...
    en
   ```

4. You must add the following keys to your application `Info.plist` file:<br>

   ```xml
   <key>NFCReaderUsageDescription</key>
   <string>Required to read from NFC enabled documents</string>
   ```

5. To read NFC tags correctly, you need to add the following entries to your app target's `Info.plist` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
   <array>
     <string>12FC</string>
   </array>
   <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
   <array>
     <string>A0000002471001</string>
     <string>A0000002472001</string>
     <string>00000000000000</string>
     <string>D2760000850101</string>
     <string>E80704007F00070302</string>
     <string>A000000167455349474E</string>
     <string>A00000045645444C2D3031</string>
   </array>
   ```

6. Add the following in your `Runner.entitlements` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.formats</key>
   <array><string>TAG</string></array>
   ```

7. To enable NFC when building your iOS app, pass the `USE_CCNFC` environment variable during the build:<br>

   ```bash
   USE_CCNFC=true flutter build ios
   ```

   \
   To keep this enabled for all iOS builds, add the following line near the top of your `ios/Podfile`:<br>

   ```ruby
   ENV['USE_CCNFC'] ||= 'true'
   ```

## Branding

You can customise colours, logos, and other branding elements through the [branding settings page](https://portal.complycube.com/settings/branding), if available on your plan.

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run a verification session, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger a [workflow session complete requests](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session) from your backend using the workflow session ID returned in the result object.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

```swift
extension ViewController: ComplyCubeMobileSDKDelegate {
  func onSuccess(_ result: ComplyCubeResult) {
   /*
    Handling successful results:
      The 'results' parameter will contain: 
      - "workflowSessionId": "xxxxx"
    */
    print("The flow has completed - here are the ID's returned")
  }
  
  func onError(_ error: ComplyCubeError) {
    // Handle errors
    print("An error has occurred")
  }

  func onCancelled(_ error: ComplyCubeError) {
    // Handle cancellations
    print("The user has cancelled the flow or not accepted the terms")
  }  
}
```

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using `withEventHandler` when initializing the `FlowBuilder`:

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withEventHandler({ (event: Event) -> Void in
    // Insert custom user tracking code here
  })
```

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withTokenExpiryHandler({ () -> String in
    // Insert custom token renewal code here
  })
```


# Check-Driven Integration

Build check-driven KYC and identity verification flows in iOS apps.

## Overview

This guide walks you through integrating the **iOS SDK** with ComplyCube using the check-driven approach, giving you direct control over individual verification steps.

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

{% hint style="warning" %}
You’re viewing the **check-driven** SDK guide - an approach that provides detailed control but is best suited for **partners** or **advanced use cases.**  We recommend using **workflow integration** for most implementations.
{% endhint %}

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/zw3kOMTk0aUWjhA2t9I0" alt=""><figcaption><p>Mobile SDK Integration flow</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-ios-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

1. Before using the ComplyCube SDK, install the **CocoaPods** plugin by running the following command in your terminal:<br>

   ```bash
   sudo gem install cocoapods
   ```

2. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
   source 'https://github.com/CocoaPods/Specs.git'
   …
   platform :iOS, ’13.0’

   target ‘YourApp’ do
       …
     pod 'ComplyCubeMobileSDK'
   end

   post_install do |installer|
       installer.pods_project.targets.each do |target|
           target.build_configurations.each do |build_configuration|
               build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
               build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
               build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.1'
               build_configuration.build_settings['ARCHS'] = ['$(ARCHS_STANDARD)', 'x86_64']
               build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = ['arm64', 'arm64e', 'armv7', 'armv7s']
               build_configuration.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES'
           end
       end
   end
   ```

\
**Application permissions**

Our SDK uses the device camera and microphone for capture. You must add the following keys to your application `Info.plist` file.

1. `NSCameraUsageDescription`

```xml
<key>NSCameraUsageDescription</key>
<string>Used to capture facials biometrics and documents</string>
```

2. `NSMicrophoneUsageDescription`

```xml
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture video biometrics</string>
```

{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to **create the client**.

This must be done on your **mobile app backend** server, not the mobile app itself.

#### Example request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

#### Example response

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables clients to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

#### Example request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

#### Example response

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Prepare the stages

Set up the stages you wish to include in your flow.

```swift
let documentStage = DocumentStageBuilder()
  .setAllowedDocumentTypes(types: [
    .passport,
    .nationalIdentityCard(),
  ])
  .useLiveCaptureOnly(enable: false)
  .build()
```

{% endstep %}

{% step %}

#### Initialize the SDK

You can now initialize a flow. The sequence of stages you specify determines the order in which your client sees those stages.

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withSDKToken("SDK_TOKEN")
  .withClientId("CLIENT_ID")
  .withStages([documentStage, selfieStage])
  .start(fromVc: self)

var clientAuth = ClientAuth("SDK_TOKEN", "CLIENT_ID")
```

{% endstep %}

{% step %}

#### Perform checks

Using the results returned in the `onSuccess` callback, you can trigger your **mobile backend** to run the necessary checks on your client.

For example, use the result of a selfie and document capture as follows:

* `result.documentId` to run a [Document Check](/documentation/api-reference/check-types/document-check).
* `result.documentId` and `result.livePhotoId` to run an [Identity Check](/documentation/api-reference/check-types/identity-check).

#### **Example request for a Document Check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
            "clientId":"CLIENT_ID",
            "type": "document_check",
            "documentId":"DOCUMENT_ID"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.create("CLIENT_ID", {
    type: "document_check",
    documentId: "DOCUMENT_ID"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.create(
    "CLIENT_ID", 
    "document_check", 
    documentId="DOCUMENT_ID"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->checks()->create('CLIENT_ID', [
    'type' => 'document_check',
    'documentId' => 'DOCUMENT_ID'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var checkRequest = new CheckRequest {
  clientId = "CLIENT_ID",
  type = "document_check",
  documentId = "DOCUMENT_ID"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

If you have set up webhooks as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve all check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).

#### Example request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## Stages

Each stage in the flow can be customized to create the ideal journey for your customers.

The snippet below demonstrates how to set up a customized flow using the ComplyCube Mobile SDK.

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withSDKToken("SDK_TOKEN")
  .withClientId("CLIENT_ID")
  .withStages([
    WelcomeStageBuilder().build(),
    UserConsentStageBuilder().build(),
    DocumentStageBuilder().build(),
    BiometricStageBuilder().build(),
    AddressCaptureStageBuilder().build(),
    ProofOfAddressBuilder().build(),
  ])
  .withEnableCompleteScreen(...)
  .withLanguage(...)
  .withLookAndFeel(...)
  .withEventHandler(...)
  .withCallbackHandler(...)
  .start(fromVc: self)
```

### **Welcome**

The Welcome screen is always shown first in the verification flow. It displays a welcome message along with a summary of the configured stages the user will complete.

You can customize the screen title to align with your app’s tone and branding.

```swift
let welcomeStage = WelcomeStageBuilder()
  .setTitle(title: "Custom Screen Title")
  .setMessage(message: "Custom welcome message.")
  .build()
```

### **Consent**

This stage is used to collect explicit user consent before proceeding with the verification flow. It helps you meet regulatory and compliance requirements where applicable.

You can customize the screen title and message to match your legal or branding needs.

```swift
let consentStage = UserConsentStageBuilder()
     .setTitle(title: "Terms of Service")
     .build()
```

### **Selfie photo and video**

You can request either a selfie photo  (i.e. a [Live Photo](/documentation/api-reference/core-resources/live-photos)) or a selfie video (i.e. a [Live Video](/documentation/api-reference/core-resources/live-videos)) from the customer as part of the biometric verification process.

* **Photo**: Captures a still image and performs a passive liveness check before allowing submission.
* **Video**: Records a short video where the user completes an on-screen challenge (e.g. head movement or spoken phrase).

{% hint style="warning" %}
If you attempt to add both types of stages, the SDK will throw a **`ComplyCubeErrorCode.BiometricStageCount`** error stating multiple conflicting stages.
{% endhint %}

```swift
let selfieStage = BiometricStageBuilder()
  .setType(type: .photo)
  // Enable ML assistance during capture
  .setEnableMLAssistant(enable: false)
  .build()
```

```swift
let videoStage = BiometricStageBuilder()
  .setType(type: .video)
  // Enable ML assistance during capture
  .setEnableMLAssistant(enable: false)
  .build()
```

### **Document**

The Document stage allows users to select and capture an identity document for verification (e.g. passport, ID card, residence permit). You can customize these screens to:

* Limit the scope of document types the client can select, e.g., Passport only.
* Set the document issuing countries they are allowed for each document type.
* Add or remove automated capture using smart assistance.
* Show or hide the instruction screens before capture.
* Set a retry limit to allow clients to progress the journey regardless of capture quality.

{% hint style="info" %}
If you provide only one document type, the document type selection screen will be skipped. The country selection screen will be skipped if you provide only a single country for a given document type.
{% endhint %}

You can control whether instructional screens are shown before each camera capture by enabling or disabling guidance mode. Only disable guidance if your users are already clearly informed about the capture steps, as these screens help reduce user error and improve capture quality.

{% hint style="info" %}
Please note the `retryLimit` you set here will take precedence over the retry limit that has been set globally in your [automation settings](https://portal.complycube.com/automations).
{% endhint %}

```swift
let docStage = DocumentStageBuilder()
  // Set document types and limit the enabled countries
  .setAllowedDocumentTypes(types: [
    .passport,
    .drivingLicence(["GB", "US"]),
    .nationalIdentityCard(),
  ])
  // Set a maximum for quality check attempts before uploading
  .setRetryLimit(count: 3)
  // Enable or disable additional guidance for the user
  .setShowGuidance(enable: true)
  // Enable ML assistance during capture
  .setEnableMLAssistant(enable: true)
  .build()
```

### NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

{% hint style="info" %}
To use this feature, your app must have the **`Near Field Communication Tag Reading`** capability enabled. To add this capability to your app, refer to [Apple's guide here](https://help.apple.com/xcode/mac/current/#/dev88ff319e7).
{% endhint %}

1. Install the **CocoaPods Artifactory** plugin by running the following command in your terminal:<br>

   ```bash
   gem install cocoapods-art
   ```

2. To add the library, copy your repository credentials into a `.netrc` file to your home directory and setup the repository:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">pod repo-art add cc-cocoapods-release-local "https://complycuberepo.jfrog.io/artifactory/api/pods/cc-cocoapods-release-local"
   </code></pre>

   \
   Remember to fetch your credentials from **JFrog** using the **Set Me Up** button [here](https://complycuberepo.jfrog.io/ui/repos/tree/General/cc-cocoapods-release-local).<br>

3. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
    plugin 'cocoapods-art', :sources => [
      'cc-cocoapods-release-local',
      'trunk'
    ]
    ...
    platform :ios, '13.0' # Or above

    target 'YourApp' do
      use_frameworks!
      use_modular_headers!
      ...
      pod 'ComplyCubeMobileSDK', '2.0.x-nfc'
      ...
    en
   ```

4. You must add the following keys to your application `Info.plist` file:<br>

   ```xml
   <key>NFCReaderUsageDescription</key>
   <string>Required to read from NFC enabled documents</string>
   ```

5. To read NFC tags correctly, you need to add the following entries to your app target's `Info.plist` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
   <array>
     <string>12FC</string>
   </array>
   <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
   <array>
     <string>A0000002471001</string>
     <string>A0000002472001</string>
     <string>00000000000000</string>
     <string>D2760000850101</string>
     <string>E80704007F00070302</string>
     <string>A000000167455349474E</string>
     <string>A00000045645444C2D3031</string>
   </array>
   ```

6. Add the following in your `Runner.entitlements` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.formats</key>
   <array><string>TAG</string></array>
   ```

7. To enable NFC when building your iOS app, pass the `USE_CCNFC` environment variable during the build:<br>

   ```bash
   USE_CCNFC=true flutter build ios
   ```

   \
   To keep this enabled for all iOS builds, add the following line near the top of your `ios/Podfile`:<br>

   ```ruby
   ENV['USE_CCNFC'] ||= 'true'
   ```

#### Enabling NFC capture

```swift
let docStage = DocumentStageBuilder()
  // Add this property to enable NFC
  .setEnableNFC(enable: true)
  .build()
```

### **Address capture**

This stage allows users to manually enter their residential address. You can customize it to:

* Restrict input to specific countries
* Enable or disable the address autocomplete feature for faster and more accurate entry

```swift
let addressCaptureStage = AddressCaptureStageBuilder()
  // This enables our address autocomplete feature
  .useAutoComplete(enable: false)
  // A list of acceptable countries for address capture feature
  .setAllowedCountries(["GB", "US"])
  .build()
```

### **Proof of address**

This stage allows customers to submit a document verifying their residential address. You can configure which document types are accepted, such as utility bills or bank statements, and choose whether customers can upload a file or must capture the document live using their device camera.

{% hint style="info" %}
By default, this stage includes the **address capture stage** with autocomplete enabled to assist users during entry. Autocomplete can be disabled if not required.
{% endhint %}

```swift
let poaStage = AddressStageBuilder()
  .setAllowedDocumentTypes(types: [
    .utilityBill,
    .bankStatement
  ])
  // When disabled, the client will be forced to perform a live capture
  .useLiveCaptureOnly(enable: false)
  // This enables address capture during the proof of address flow
  .setEnableAddressCapture(true)
  .build()
```

### **Completion**

You can include a completion stage at the end of the flow to confirm that the process has been successfully finished. This screen provides a clear end point for the user and can be customized to display a confirmation message or next steps.

```swift
let completionStage = Complete(
  title: "Thank you!",
  message: "Your KYC submission has been completed"
)
```

## Branding

The SDK allows you to customize the UI to match your application’s visual identity. You can define primary and accent colors during configuration to align the verification flow with your brand guidelines. Learn more about our **appearance properties** (see below).

**Creating a custom appearance**

Before initiating the flow, create your own custom design and integrate it into your Flow Builder.

```swift
let ccLookAndFeel = LookAndFeel()
ccLookAndFeel.primaryButtonBgColor = .green
ccLookAndFeel.uiInterfaceStyle = .dark //can also be .light or .inherited
```

#### **Applying your custom appearance**

Set the custom appearance that you have created using the Flow Builder.

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withLookAndFeel(ccLookAndFeel)
  .start(fromVc: self)
```

<details>

<summary>Appearance properties</summary>

<table><thead><tr><th width="371.70703125">Appearance Property</th><th>Description</th></tr></thead><tbody><tr><td><code>primaryButtonBgColor</code></td><td>Primary action button background color.</td></tr><tr><td><code>primaryButtonTextColor</code></td><td>Primary action button text color.</td></tr><tr><td><code>primaryButtonBorderColor</code></td><td>Primary action button border color.</td></tr><tr><td><code>secondaryButtonBgColor</code></td><td>Secondary button background color.</td></tr><tr><td><code>secondaryButtonPressedBgColor</code></td><td>Secondary action button pressed background color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>secondaryButtonTextColor</code></td><td>Secondary action button text color.</td></tr><tr><td><code>secondaryButtonBorderColor</code></td><td>Secondary action button border color.</td></tr><tr><td><code>documentTypeSelectorBgColor</code></td><td>Document type selection button color.</td></tr><tr><td><code>documentTypeSelectorBorderColor</code></td><td>Document type selection button border color.</td></tr><tr><td><code>documentTypeSelectorTitleTextColor</code></td><td>Document type selection title text color.</td></tr><tr><td><code>documentTypeSelectorDescriptionTextColor</code></td><td>Document type selection description text color.</td></tr><tr><td><code>documentTypeSelectorIconColor</code></td><td>Document type selection icon color.</td></tr><tr><td><code>bodyTextColor</code></td><td>Screen body text color.</td></tr><tr><td><code>linkButtonTextColor</code></td><td>Links color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>headingTextColor</code></td><td>Title heading text color.</td></tr><tr><td><code>subheadingTextColor</code></td><td>Subheading text color.</td></tr><tr><td><code>infoPanelTitleColor</code></td><td>Information panel title color.</td></tr><tr><td><code>infoPanelDescriptionTextColor</code></td><td>Information panel description text color.</td></tr><tr><td><code>infoPanelBgColor</code></td><td>Information panel background color.</td></tr><tr><td><code>infoPanelIconColor</code></td><td>Information panel icon color.</td></tr><tr><td><code>errorPanelTitleColor</code></td><td>Error panel title color.</td></tr><tr><td><code>errorPanelDescriptionTextColor</code></td><td>Error panel description text color.</td></tr><tr><td><code>errorPanelBgColor</code></td><td>Error panel background color.</td></tr><tr><td><code>errorPanelIconColor</code></td><td>Error panel icon color.</td></tr><tr><td><code>cameraButtonBgColor</code></td><td>Camera capture button background color.</td></tr><tr><td><code>uiInterfaceStyle</code></td><td>Set the SDK to use dark mode, light mode, or system Inherited.</td></tr></tbody></table>

</details>

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run verification checks, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger [check requests](/documentation/api-reference/core-resources/checks/create-a-check) from your backend using the resource IDs returned in the result object. These IDs correspond to the uploaded assets (e.g. documents, selfies) and can be used to initiate verification checks via the ComplyCube API.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

```swift
extension ViewController: ComplyCubeMobileSDKDelegate {
  func onSuccess(_ result: ComplyCubeResult) {
   /*
    Handling successful results:
    Our default flow includes three components: an Identity Document,
    a Selfie (Live Photo), and a Proof of Address. Upon successful 
    completion, the 'result' parameter will contain `documentIds`and `livePhotoId`
    */
    print("The flow has completed - here are the ID's returned")
  }
  
  func onError(_ error: ComplyCubeError) {
    // Handle errors
    print("An error has occurred")
  }

  func onCancelled(_ error: ComplyCubeError) {
    // Handle cancellations
    print("The user has cancelled the flow or not accepted the terms")
  }  
}
```

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using `withEventHandler` when initializing the `FlowBuilder`:

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withEventHandler({ (event: Event) -> Void in
    // Insert custom user tracking code here
  })
```

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

```swift
let sdk = ComplyCubeMobileSDK.FlowBuilder()
  .withTokenExpiryHandler({ () -> String in
    // Insert custom token renewal code here
  })
```


# Android SDK

Add native KYC and identity verification flows to Android apps with the ComplyCube SDK.

## Overview

The **ComplyCube Android SDK** enables you to embed a full identity verification flow directly into your Android application using native, mobile-optimized components.

Designed for easy integration, the SDK handles everything from document capture and biometric liveness checks to proof of address and NFC authentication. It’s optimised for speed and accuracy, with features like auto-capture and real-time feedback.

{% embed url="<https://www.youtube.com/watch?v=n8kAGXQykkA>" %}
ComplyCube Mobile SDK Demo
{% endembed %}

## Benefits

The SDK offers several benefits:

* **Mobile-native flow:** Frictionless user experience using mobile-native UI components. Includes guided flows for capturing selfies, videos, identity documents, and proof of address.
* **Flexible integration**: Use [workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate complete verification journeys with minimal code, or configure individual stages (e.g. selfie, document, NFC) for more granular control.
* **Biometric verification**: Supports photo and video-based liveness checks (**PAD Level 2 certified)** using passive and active techniques to detect spoofing.
* **Document & NFC verification:** Supports OCR and RFID reading from passports, ID cards, and other chip-enabled documents. Cross-checks encrypted chip data for added assurance.
* **Smart auto-capture**: Automatically captures selfies and documents with real-time quality checks, reducing user errors and ensuring optimal input for verification.
* **Custom branding**: Customize accent colors, text, and logos to match your app’s visual identity.
* **Global-ready**: Built-in support for multiple languages and localized UI labels.

## Requirements

* **Android 5.0** (API level 21) and above.
* **AndroidX**.
* **Kotlin 1.7** and above.

## Integration modes

The Android SDK can be integrated in two different ways, depending on your needs:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Workflow Integration</strong></mark></td><td>Use the Workflow Designer to build your customer KYC journey and simply load it through the SDK. This is the preferred option for most use cases.</td><td><strong>Recommended</strong></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/4pLkNRkkAfA7NUu0eulz">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/4pLkNRkkAfA7NUu0eulz</a></td></tr><tr><td><mark style="color:blue;"><strong>Check-Driven Integration</strong></mark></td><td>A lower-level approach where you directly control individual SDK screens and checks. It's best suited for advanced use cases.</td><td></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/pzITlQc15NMdU1rqpLgk">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/pzITlQc15NMdU1rqpLgk</a></td></tr></tbody></table>


# Workflow Integration

Integrate KYC workflows in Android apps using the ComplyCube Android SDK.

## Overview

This guide walks you through integrating the **Android SDK** with ComplyCube [workflows](/documentation/product-guides/compliance-studio/workflows).

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture data, documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/QphA3xsRYHb17fG8zplz" alt=""><figcaption><p>Mobile SDK Integration via Workflows Guide</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-android-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

Our SDK requires the repositories below.

```java
repositories {
  mavenCentral()
}

dependencies {
    implementation "com.complycube:complycube-sdk:+"
}
```

{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

This must be done on your **mobile app backend** server, not the mobile app itself.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables customers to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Initialize the SDK

As part of initializing the SDK, you are required to specify a [workflow template ID](https://portal.complycube.com/workflowTemplates). The SDK will automatically run the **active** version of the selected workflow.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val complyCubeBuilder = ComplyCubeSdk.Builder(this, callback =  { }).apply {
    withWorkflowTemplateId( workflowTemplateId = "WORKFLOW_TEMPLATE_ID" )
}.start(
    ClientAuth(
        token = "SDK_TOKEN",
        clientId = "CLIENT_ID"
    )
)
```

{% endtab %}

{% tab title="Java" %}

```java
ComplyCubeSdk.Builder complycubeFlow =
    new ComplyCubeSdk.Builder(this, result -> {});

complycubeFlow.withWorkflowTemplateId("WORKFLOW_TEMPLATE_ID");

complycubeFlow.start(new ClientAuth(
    "SDK_TOKEN",
    "CLIENT_ID"
));
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Perform verification

Once your customer starts the flow, a [workflow session](/documentation/product-guides/compliance-studio/workflows#workflow-session) is automatically created. This session contains all captured data (documents, images, and videos) as well as progress tracking. You can view all of them through the [workflow sessions page](https://portal.complycube.com/workflowSessions) on the portal or through the API.

When the flow finishes, the SDK triggers the `onSuccess` callback. The callback provides a `data` object that includes the `workflowSessionId`. Your **mobile backend** should use this ID to notify ComplyCube that the [workflow has completed](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session), which in turn runs the verification checks defined in the workflow.

If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a workflow session completes.

#### Example of a complete workflow session request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/workflowSessions/{:wfSessionId}/complete \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.complete("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.complete('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->complete('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.CompleteAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve the workflow session details and associated check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

You can retrieve the details of a workflow session by calling the [retrieve workflow session request](/documentation/api-reference/core-resources/workflow-sessions/get-a-workflow-session).

To retrieve the check results, you can perform a [get check request](/documentation/api-reference/core-resources/checks/get-a-check).

**Example of a workflow session retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/workflowSessions/{:workflowSessionId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.get("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.get('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->get('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.GetAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}

**Example of a check retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

1. Start by adding your access credentials for the ComplyCube NFC-Enabled SDK repository to the `gradle.properties` file of your **mobile app**:

```gradle
artifactory_user= "USERNAME"
artifactory_password= "ENCRYPTED PASS"
artifactory_contextUrl= https://complycuberepo.jfrog.io/artifactory
```

2. Then, update your project level `build.gradle` file with the ComplyCube SDK repository Maven settings:

```gradle
buildscript {
    repositories {
        ...
    }
    dependencies {
        ....
        // Check for the latest version here: 
        // http://plugins.gradle.org/plugin/com.jfrog.artifactory
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
    }
    ...
}

allprojects {
    apply plugin: "com.jfrog.artifactory"
    repositories {
        maven { url "https://complycuberepo.jfrog.io/artifactory/cc-gradle-release" }
    }
    ...
}

artifactory {
  contextUrl = "${artifactory_contextUrl}"  
  resolve {
    repository {
      repoKey = 'cc-gradle-release'
      username = "${artifactory_user}"
      password = "${artifactory_password}"
      maven = true
    }
  }
}
```

3. Update your module level `build.gradle` file with the SDK dependency:

```gradle
dependencies {
    implementation "com.complycube:complycube-sdk:+"
    implementation "com.complycube:nfc-plugin:+"
}
```

## Branding

You can customise colours, logos, and other branding elements through the [branding settings page](https://portal.complycube.com/settings/branding), if available on your plan.

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run a verification session, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger a [workflow session complete requests](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session) from your backend using the workflow session ID returned in the result object.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
//Register a result handler to process the outcome of the flow.
var complycubeFlow =
    ComplyCubeSdk.Builder(
        this,
        callback = { result ->
            when (result) {
                is Result.Success -> { 
                /*
                    Handling successful results:
                    The 'results' parameter will contain: 
                      - "workflowSessionId": "xxxxx"
                */
                }
                is Result.Cancelled -> { /* Handle Cancelled result */ }
                is Result.Error -> {
                    // Handle errors
                    when (result.errorCode) {
                        ComplyCubeErrorCode.UploadError -> {
                            // Handle Upload error
                        }
                        ComplyCubeErrorCode.BiometricStageCount -> {
                            // Handle BiometricStageCount error
                        }
                        // ...other error handlers
                    }
                }
                else -> {}
            }
        }
    )

complycubeFlow.start(clientAuth)
```

{% endtab %}

{% tab title="Java" %}

```java
//Register a result handler to process the outcome of the flow.
ComplyCubeSdk.Builder complycubeFlow = new ComplyCubeSdk.Builder(this, result -> {
    if (result instanceof Result.Success) {
     /*
        Handling successful results:
        The 'results' parameter will contain: 
          - "workflowSessionId": "xxxxx"
     */
    } else if (result instanceof Result.Error) {
        switch (((Result.Error) result).getErrorCode()) {
            case ComplyCubeErrorCode.UploadError.INSTANCE:
                // Handle upload error
                break;
            case ComplyCubeErrorCode.BiometricStageCount.INSTANCE:
                // Handle BiometricStageCountError
                break;
                // ... other error handlers
            default:
        }
    } else if (result instanceof Result.Canceled) {
        // Handle Cancelled result
    }
    return null;
});
```

{% endtab %}
{% endtabs %}

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using `withEventHandler` when initializing the `Builder`:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
complycubeBuilder.withEventHandler(true) { event ->
    // Insert custom user tracking here
}
```

{% endtab %}

{% tab title="Java" %}

```java
complycubeFlow.withEventHandler(true, analyticsEvent ->
    // Insert custom user tracking here
);
```

{% endtab %}
{% endtabs %}

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var complyCubeBuilder = ComplyCubeSdk.Builder(this,
    callback = { result ->
        if (result is Result.Error) {
            if (result.errorCode is ComplyCubeErrorCode.ExpiredToken) {
                // Insert custom token renewal code here
            }
        }
    }
)
```

{% endtab %}

{% tab title="Java" %}

```java
ComplyCubeSdk.Builder complyCubeBuilder =
    new ComplyCubeSdk.Builder(this, result -> {
        if (result instanceof Result.Error) {
            if (((Result.Error) result).getErrorCode() == ComplyCubeErrorCode.ExpiredToken.INSTANCE) {
                // Insert custom token renewal code here
            }
        }
        return null;
    });
```

{% endtab %}
{% endtabs %}


# Check-Driven Integration

Build check-driven KYC and identity verification flows in Android apps.

## Overview

This guide walks you through integrating the **Android SDK** with ComplyCube using the check-driven approach, giving you direct control over individual verification steps.

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

{% hint style="warning" %}
You’re viewing the **check-driven** SDK guide - an approach that provides detailed control but is best suited for **partners** or **advanced use cases.**  We recommend using **workflow integration** for most implementations.
{% endhint %}

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/zw3kOMTk0aUWjhA2t9I0" alt=""><figcaption><p>Mobile SDK Integration flow</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-android-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

Our SDK requires the repositories below.

```java
repositories {
  mavenCentral()
}

dependencies {
    implementation "com.complycube:complycube-sdk:+"
}
```

{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

This must be done on your **mobile app backend** server, not the mobile app itself.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables customers to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Prepare the stages

Set up the stages you wish to include in your flow.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val complyCubeBuilder = ComplyCubeSdk.Builder(this, callback =  { }).apply {
    withStages(
        Document(
            identityDocumentType = Passport(), DrivingLicence(),
            useLiveCaptureOnly = false
        ),
        SelfiePhoto()
    )
}
```

{% endtab %}

{% tab title="Java" %}

```java
IdentityDocumentType[] identityDocumentTypes;

identityDocumentTypes = new IdentityDocumentType[1];

identityDocumentTypes[0] = new DrivingLicence();

Document document = new Document(
    // documentType
    null,
    // documentTypes
    identityDocumentTypes,
    // isGuidanceEnabled
    true,
    // useLiveCaptureOnly
    false,
    // isMLAssistanceEnabled
    true,
    // retryLimit
    5,
    // isNFCEnabled
    true
);
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Initialize the SDK

You can now initialize a flow. The sequence of stages you specify determines the order in which your client sees those stages.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val complyCubeBuilder = ComplyCubeSdk.Builder(this, callback =  { }).apply {
    withStages(
        Document(
            identityDocumentType = Passport(), DrivingLicence(),
            useLiveCaptureOnly = false
        ),
        SelfiePhoto()
    )
}.start(
    ClientAuth(
        token = "SDK_TOKEN",
        clientId = "CLIENT_ID"
    )
)
```

{% endtab %}

{% tab title="Java" %}

```java
ComplyCubeSdk.Builder complycubeFlow =
    new ComplyCubeSdk.Builder(this, result - > {});

complycubeFlow.withStages(
    document,
    new SelfiePhoto()
);

complycubeFlow.start(new ClientAuth(
    "SDK_TOKEN",
    "CLIENT_ID"
));
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Perform checks

Using the `StageResults` returned by the flow, you can trigger your **mobile backend** to run the necessary checks on your client.

For example, use the result of a selfie and document capture as follows:

* `StageResult.Document.Id` to run a [Document Check](https://docs.complycube.com/api-reference/check-types/document-check).
* `StageResult.Document.Id` and `StageResult.LivePhoto.Id` to run an [Identity Check](https://docs.complycube.com/api-reference/check-types/identity-check).

**Example request for a Document Check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
            "clientId":"CLIENT_ID",
            "type": "document_check",
            "documentId":"DOCUMENT_ID"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.create("CLIENT_ID", {
    type: "document_check",
    documentId: "DOCUMENT_ID"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.create(
    "CLIENT_ID", 
    "document_check", 
    documentId="DOCUMENT_ID"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->checks()->create('CLIENT_ID', [
    'type' => 'document_check',
    'documentId' => 'DOCUMENT_ID'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var checkRequest = new CheckRequest {
  clientId = "CLIENT_ID",
  type = "document_check",
  documentId = "DOCUMENT_ID"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve all check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## Stages

Each stage in the flow can be customized to create the ideal journey for your customers.

The snippet below demonstrates how to set up a customized flow using the ComplyCube Mobile SDK.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var complycubeFlow = ComplyCubeSdk.Builder(this, callback = ...)
  .withSDKToken("SDK_Token")
  .withClientId("CLIENT_ID")
  .withStages(
    Welcome(...),
    Consent(...),
    Document(...),
    SelfiePhoto(...),
    AddressCapture(...),
    ProofOfAddress(...),
    Complete(...)
  )
  .withLookAndFeel(...)
  .withCustomLanguage(...)

complycubeFlow.start()
```

{% endtab %}

{% tab title="Java" %}

```java
complycubeFlow.withStages(
    new Welcome(...),
    new UserConsent(...),
    new Document(...),
    new SelfiePhoto(...),
    new AddressCapture(...),
    new ProofOfAddress(...),
    new Complete(...)
);

complycubeFlow.withLookAndFeel(...);
complycubeFlow.withCustomLanguage(..);
```

{% endtab %}
{% endtabs %}

### **Welcome**

The Welcome screen is always shown first in the verification flow. It displays a welcome message along with a summary of the configured stages the user will complete.

You can customize the screen title to align with your app’s tone and branding.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var welcomeStage = Welcome(
    title = "Custom Screen Title",
    message = "Custom welcome message."
)
```

{% endtab %}

{% tab title="Java" %}

```java
 Welcome welcome = new Welcome(
     "Custom Screen Title",
     "Custom welcome message",
     null
 );
```

{% endtab %}
{% endtabs %}

### **Consent**

This stage is used to collect explicit user consent before proceeding with the verification flow. It helps you meet regulatory and compliance requirements where applicable.

You can customize the screen title and message to match your legal or branding needs.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var consentStage = Consent(
    title = "Custom Consent Screen Title"
)
```

{% endtab %}

{% tab title="Java" %}

```java
UserConsent userConsent = new UserConsent(
    "Custom Consent Screen Title",
    null,
    null
);
```

{% endtab %}
{% endtabs %}

### **Selfie photo and video**

You can request either a selfie photo  (i.e. a [Live Photo](/documentation/api-reference/core-resources/live-photos)) or a selfie video (i.e. a [Live Video](/documentation/api-reference/core-resources/live-videos)) from the customer as part of the biometric verification process.

* **Photo**: Captures a still image and performs a passive liveness check before allowing submission.
* **Video**: Records a short video where the user completes an on-screen challenge (e.g. head movement or spoken phrase).

{% hint style="warning" %}
If you attempt to add both types of stages, the SDK will throw a **`ComplyCubeErrorCode.BiometricStageCount`** error stating multiple conflicting stages.
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var selfiePhoto = SelfiePhoto(
    // Enable ML assistance during capture
    isMLAssistantEnabled = false
)
```

{% endtab %}

{% tab title="Java" %}

```java
SelfiePhoto selfiePhoto = new SelfiePhoto(
    // isGuidanceEnabled
    true,
    // useLiveCaptureOnly
    true,
    // isMLAssistanceEnabled
    false,
    // retryLimit
    5
);
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var selfieVideo = SelfieVideo(
    // Enable ML assistance during capture
    isMLAssistantEnabled = false
)
```

{% endtab %}

{% tab title="Java" %}

```java
 SelfieVideo selfieVideo = new SelfieVideo(
     // isGuidanceEnabled
     true,
     // isMLAssistanceEnabled
     false,
     // retryLimit
     5
 );
```

{% endtab %}
{% endtabs %}

### **Document**

The Document stage allows users to select and capture an identity document for verification (e.g. passport, ID card, residence permit). You can customize these screens to:

* Limit the scope of document types the client can select, e.g., Passport only.
* Set the document issuing countries they are allowed for each document type.
* Add or remove automated capture using smart assistance.
* Show or hide the instruction screens before capture.
* Set a retry limit to allow clients to progress the journey regardless of capture quality.

{% hint style="info" %}
If you provide only one document type, the document type selection screen will be skipped. The country selection screen will be skipped if you provide only a single country for a given document type.
{% endhint %}

You can control whether instructional screens are shown before each camera capture by enabling or disabling guidance mode. Only disable guidance if your users are already clearly informed about the capture steps, as these screens help reduce user error and improve capture quality.

{% hint style="info" %}
Please note the `retryLimit` you set here will take precedence over the retry limit that has been set globally in your [automation settings](https://portal.complycube.com/automations).
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var documentStage = Document(
    // Set document types and limit the enabled countries
    Passport(), DrivingLicence((Country.GB, Country.US)),

    // Enable or disable additional guidance for the user
    isGuidanceEnabled = true,

    // Enable or disable the ability to upload an image from file
    useLiveCaptureOnly = true,

    // Enable ML assistance during capture
    isMLAssistantEnabled = true,
    
    // Set a maximum for quality check attempts before uploadingoft checks
    retryLimit = 3
)
```

{% endtab %}

{% tab title="Java" %}

```java
IdentityDocumentType[] identityDocumentTypes;

identityDocumentTypes = new IdentityDocumentType[1];

identityDocumentTypes[0] = new DrivingLicence();

Document document = new Document(
    null,
    identityDocumentTypes, // documentTypes
    true, // isGuidanceEnabled
    false, // useLiveCaptureOnly
    true, // isMLAssistanceEnabled
    5, // retryLimit
    true // isNFCEnabled
);
```

{% endtab %}
{% endtabs %}

### NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

1. Start by adding your access credentials for the ComplyCube NFC-Enabled SDK repository to the `gradle.properties` file of your **mobile app**:

```gradle
artifactory_user= "USERNAME"
artifactory_password= "ENCRYPTED PASS"
artifactory_contextUrl= https://complycuberepo.jfrog.io/artifactory
```

2. Then, update your project level `build.gradle` file with the ComplyCube SDK repository Maven settings:

```gradle
buildscript {
    repositories {
        ...
    }
    dependencies {
        ....
        // Check for the latest version here: 
        // http://plugins.gradle.org/plugin/com.jfrog.artifactory
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
    }
    ...
}

allprojects {
    apply plugin: "com.jfrog.artifactory"
    ...
}

artifactory {
  contextUrl = "${artifactory_contextUrl}"  
  resolve {
    repository {
      repoKey = 'cc-gradle-release'
      username = "${artifactory_user}"
      password = "${artifactory_password}"
      maven = true
    }
  }
}
```

3. Update your module level `build.gradle` file with the SDK dependency:

```gradle
dependencies {
    implementation "com.complycube:complycube-sdk:+"
    implementation "com.complycube:nfc-plugin:+"
}
```

#### Enabling NFC capture

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var documentStage = Document(
    // Add this property to enable NFC
    isNFCEnabled = true,
)
```

{% endtab %}

{% tab title="Java" %}

```java
IdentityDocumentType[] identityDocumentTypes;

identityDocumentTypes = new IdentityDocumentType[1];

identityDocumentTypes[0] = new Passport();

Document document = new Document(
    null,
    // documentTypes
    identityDocumentTypes,
    // isGuidanceEnabled
    true,
    // useLiveCaptureOnly
    false,
    // isMLAssistanceEnabled
    true,
    // retryLimit
    5,
    // isNFCEnabled
    true
);
```

{% endtab %}
{% endtabs %}

### **Address capture**

This stage allows users to manually enter their residential address. You can customize it to:

* Restrict input to specific countries
* Enable or disable the address autocomplete feature for faster and more accurate entry

{% tabs %}
{% tab title="Kotlin" %}
{% code fullWidth="false" %}

```kotlin
var addressCaptureStage = AddressCapture(
    // This enables our address autocomplete
    useAutoComplete = true,
    
    // A list of acceptable countries for address capture feature
    allowedCountries = setOf(Country.GB,Country.US)
)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}

```java
Set<Country> countries = new HashSet<> ();

countries.add(Country.GB);
countries.add(Country.US);

AddressCapture addressCapture = new AddressCapture(
    // useAutoComplete
    true,
    // allowedCountries
    countries
);
```

{% endtab %}
{% endtabs %}

### **Proof of address**

This stage allows customers to submit a document verifying their residential address. You can configure which document types are accepted, such as utility bills or bank statements, and choose whether customers can upload a file or must capture the document live using their device camera.

{% hint style="info" %}
By default, this stage includes the **address capture stage** with autocomplete enabled to assist users during entry. Autocomplete can be disabled if not required.
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}
{% code fullWidth="false" %}

```kotlin
var poaStage = ProofOfAddress(
    // A list of supported document types that can be submitted
    UtilityBill(), BankStatement(),

    // When disabled, the client will be forced to perform a live capture
    useLiveCaptureOnly = false,

    // This enables address capture during the proof of address flow
    isAddressCaptureEnabled = false
    ...
)
```

{% endcode %}
{% endtab %}

{% tab title="Java" %}

```java
LinkedHashSet<ProofOfAddressDocumentType> documentTypes =
    new LinkedHashSet<ProofOfAddressDocumentType> ();

documentTypes.add(new UtilityBill());
documentTypes.add(new BankStatement());

ProofOfAddress poaStage = new ProofOfAddress(
    documentTypes,
    // isGuidanceEnabled
    true,
    // useLiveCaptureOnly
    false,
    // isMLAssistanceEnabled
    true,
    // retryLimit
    5,
    // isAddressCaptureEnabled
    false
);
```

{% endtab %}
{% endtabs %}

### **Completion**

You can include a completion stage at the end of the flow to confirm that the process has been successfully finished. This screen provides a clear end point for the user and can be customized to display a confirmation message or next steps.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val completionStage = Complete(
    title = "Thank you!",
    message = "Your KYC submission has been completed"
)
```

{% endtab %}

{% tab title="Java" %}

```java
Complete complete = new Complete(
    "Custom Complete Title",
    "Custom Complete Message",
    null
);
```

{% endtab %}
{% endtabs %}

## Branding

The SDK allows you to customize the UI to match your application’s visual identity. You can define primary and accent colors during configuration to align the verification flow with your brand guidelines. Learn more about our **appearance properties** (see below).

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
complycubeFlow.withLookAndFeel(
    lookAndFeel = LookAndFeel(
        primaryButtonBgColor = Color.RED,
        /* Can also be set to UIInterfaceStyle.LIGHT 
        or UIInterfaceStyle.INHERITED */
        uiInterfaceStyle = UIInterfaceStyle.DARK
    )
)
```

{% endtab %}

{% tab title="Java" %}

```java
complycubeFlow.withLookAndFeel(new LookAndFeel(
    // primaryButtonBGColor
    Color.parseColor("#FF0000"),
    // uiInterfaceStyle
    UIInterfaceStyle.DARK,
    ...
));
```

{% endtab %}
{% endtabs %}

<details>

<summary>Appearance properties</summary>

<table><thead><tr><th width="371.70703125">Appearance Property</th><th>Description</th></tr></thead><tbody><tr><td><code>primaryButtonBgColor</code></td><td>Primary action button background color.</td></tr><tr><td><code>primaryButtonTextColor</code></td><td>Primary action button text color.</td></tr><tr><td><code>primaryButtonBorderColor</code></td><td>Primary action button border color.</td></tr><tr><td><code>secondaryButtonBgColor</code></td><td>Secondary button background color.</td></tr><tr><td><code>secondaryButtonPressedBgColor</code></td><td>Secondary action button pressed background color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>secondaryButtonTextColor</code></td><td>Secondary action button text color.</td></tr><tr><td><code>secondaryButtonBorderColor</code></td><td>Secondary action button border color.</td></tr><tr><td><code>documentTypeSelectorBgColor</code></td><td>Document type selection button color.</td></tr><tr><td><code>documentTypeSelectorBorderColor</code></td><td>Document type selection button border color.</td></tr><tr><td><code>documentTypeSelectorTitleTextColor</code></td><td>Document type selection title text color.</td></tr><tr><td><code>documentTypeSelectorDescriptionTextColor</code></td><td>Document type selection description text color.</td></tr><tr><td><code>documentTypeSelectorIconColor</code></td><td>Document type selection icon color.</td></tr><tr><td><code>bodyTextColor</code></td><td>Screen body text color.</td></tr><tr><td><code>linkButtonTextColor</code></td><td>Links color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>headingTextColor</code></td><td>Title heading text color.</td></tr><tr><td><code>subheadingTextColor</code></td><td>Subheading text color.</td></tr><tr><td><code>infoPanelTitleColor</code></td><td>Information panel title color.</td></tr><tr><td><code>infoPanelDescriptionTextColor</code></td><td>Information panel description text color.</td></tr><tr><td><code>infoPanelBgColor</code></td><td>Information panel background color.</td></tr><tr><td><code>infoPanelIconColor</code></td><td>Information panel icon color.</td></tr><tr><td><code>errorPanelTitleColor</code></td><td>Error panel title color.</td></tr><tr><td><code>errorPanelDescriptionTextColor</code></td><td>Error panel description text color.</td></tr><tr><td><code>errorPanelBgColor</code></td><td>Error panel background color.</td></tr><tr><td><code>errorPanelIconColor</code></td><td>Error panel icon color.</td></tr><tr><td><code>cameraButtonBgColor</code></td><td>Camera capture button background color.</td></tr><tr><td><code>uiInterfaceStyle</code></td><td>Set the SDK to use dark mode, light mode, or system Inherited.</td></tr></tbody></table>

</details>

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run verification checks, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger [check requests](/documentation/api-reference/core-resources/checks/create-a-check) from your backend using the resource IDs returned in the result object. These IDs correspond to the uploaded assets (e.g. documents, selfies) and can be used to initiate verification checks via the ComplyCube API.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
//Register a result handler to process the outcome of the flow.
var complycubeFlow =
    ComplyCubeSdk.Builder(
        this,
        callback = { result ->
            when (result) {
                is Result.Success -> { 
                /*
                Handling successful results:
                Our default flow includes three components: an Identity Document,
                a Selfie (Live Photo), and a Proof of Address. Upon successful 
                completion, the 'Result' will contain an array of stage results.
                Each stage result provides the ID of the uploaded item:
                  - 'StageResult.Document.Id': the uploaded Document ID.
                  - 'StageResult.LivePhoto.Id': the uploaded Live Photo ID.
                  - 'StageResult.ProofOfAddress.Id': the uploaded PA Document ID.
                */
                }
                is Result.Cancelled -> { /* Handle Cancelled result */ }
                is Result.Error -> {
                    // Handle errors
                    when (result.errorCode) {
                        ComplyCubeErrorCode.UploadError -> {
                            // Handle Upload error
                        }
                        ComplyCubeErrorCode.BiometricStageCount -> {
                            // Handle BiometricStageCount error
                        }
                        // ...other error handlers
                    }
                }
                else -> {}
            }
        }
    )

complycubeFlow.start(clientAuth)
```

{% endtab %}

{% tab title="Java" %}

```java
//Register a result handler to process the outcome of the flow.
ComplyCubeSdk.Builder complycubeFlow = new ComplyCubeSdk.Builder(this, result -> {
    if (result instanceof Result.Success) {
        /*
        Handling successful results:
        Our default flow includes three components: an Identity Document,
        a Selfie (Live Photo), and a Proof of Address. Upon successful 
        completion, the 'Result' will contain an array of stage results.
        Each stage result provides the ID of the uploaded item:
          - 'StageResult.Document.Id': the uploaded Document ID.
          - 'StageResult.LivePhoto.Id': the uploaded Live Photo ID.
          - 'StageResult.ProofOfAddress.Id': the uploaded PA Document ID.
        */
    } else if (result instanceof Result.Error) {
        switch (((Result.Error) result).getErrorCode()) {
            case ComplyCubeErrorCode.UploadError.INSTANCE:
                // Handle upload error
                break;
            case ComplyCubeErrorCode.BiometricStageCount.INSTANCE:
                // Handle BiometricStageCountError
                break;
                // ... other error handlers
            default:
        }
    } else if (result instanceof Result.Canceled) {
        // Handle Cancelled result
    }
    return null;
});
```

{% endtab %}
{% endtabs %}

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using `withEventHandler` when initializing the `Builder`:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
complycubeBuilder.withEventHandler(true) { event ->
    // Insert custom user tracking here
}
```

{% endtab %}

{% tab title="Java" %}

```java
complycubeFlow.withEventHandler(true, analyticsEvent ->
    // Insert custom user tracking here
);
```

{% endtab %}
{% endtabs %}

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var complyCubeBuilder = ComplyCubeSdk.Builder(this,
    callback = { result ->
        if (result is Result.Error) {
            if (result.errorCode is ComplyCubeErrorCode.ExpiredToken) {
                // Insert custom token renewal code here
            }
        }
    }
)
```

{% endtab %}

{% tab title="Java" %}

```java
ComplyCubeSdk.Builder complyCubeBuilder =
    new ComplyCubeSdk.Builder(this, result -> {
        if (result instanceof Result.Error) {
            if (((Result.Error) result).getErrorCode() == ComplyCubeErrorCode.ExpiredToken.INSTANCE) {
                // Insert custom token renewal code here
            }
        }
        return null;
    });
```

{% endtab %}
{% endtabs %}


# React Native SDK

Embed KYC and identity verification flows in React Native apps with ComplyCube.

## Overview

The ComplyCube **React Native SDK** enables you to embed a full identity verification flow directly into your React Native application using native, mobile-optimized components.

Designed for easy integration, the SDK handles everything from document capture and biometric liveness checks to proof of address and NFC authentication. It’s optimised for speed and accuracy, with features like auto-capture and real-time feedback.

{% embed url="<https://www.youtube.com/watch?v=n8kAGXQykkA>" %}
ComplyCube Mobile SDK Demo
{% endembed %}

## Benefits

The SDK offers several benefits:

* **Mobile-native flow:** Frictionless user experience using mobile-native UI components. Includes guided flows for capturing selfies, videos, identity documents, and proof of address.
* **Flexible integration**: Use [workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate complete verification journeys with minimal code, or configure individual stages (e.g. selfie, document, NFC) for more granular control.
* **Biometric verification**: Supports photo and video-based liveness checks (**PAD Level 2 certified)** using passive and active techniques to detect spoofing.
* **Document & NFC verification:** Supports OCR and RFID reading from passports, ID cards, and other chip-enabled documents. Cross-checks encrypted chip data for added assurance.
* **Smart auto-capture**: Automatically captures selfies and documents with real-time quality checks, reducing user errors and ensuring optimal input for verification.
* **Custom branding**: Customize accent colors, text, and logos to match your app’s visual identity.
* **Global-ready**: Built-in support for multiple languages and localized UI labels.

## Requirements

{% tabs %}
{% tab title="React Native" %}

* **React Native** 0.71 and above.
  {% endtab %}

{% tab title="iOS" %}

* **Swift 5**.
* **iOS 13** and above.
* **Xcode 13** and above.
  {% endtab %}

{% tab title="Android" %}

* **Android 5.0** (API level 21) and above.
* **AndroidX**.
* **Kotlin 1.7** and above.
  {% endtab %}
  {% endtabs %}

## Integration modes

The React Native SDK can be integrated in two different ways, depending on your needs:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Workflow Integration</strong></mark></td><td>Use the Workflow Designer to build your customer KYC journey and simply load it through the SDK. This is the preferred option for most use cases.</td><td><strong>Recommended</strong></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/RGXAw64yhpFLaBQtCiVA">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/RGXAw64yhpFLaBQtCiVA</a></td></tr><tr><td><mark style="color:blue;"><strong>Check-Driven Integration</strong></mark></td><td>A lower-level approach where you directly control individual SDK screens and checks. It's best suited for advanced use cases.</td><td></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/n8mAhmF9mvzlVHyvIN3r">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/n8mAhmF9mvzlVHyvIN3r</a></td></tr></tbody></table>


# Workflow Integration

Integrate KYC workflows in React Native apps using the ComplyCube SDK.

## Overview

This guide walks you through integrating the **React Native SDK** with ComplyCube [workflows](/documentation/product-guides/compliance-studio/workflows).

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture data, documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/QphA3xsRYHb17fG8zplz" alt=""><figcaption><p>Mobile SDK Integration via Workflows Guide</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-react-native-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

{% tabs %}
{% tab title="React Native" %}

1. Install the React Native library by running:

```bash
npm i -s @complycube/react-native
```

2. Complete the steps in the **iOS** and **Android** tabs.

{% hint style="danger" %}

#### Sentry integration

If you’re integrating Sentry into your React Native project, you might encounter the following compiler error:

```javascript
'SentryDefines.h' file cannot be found.
```

This issue occurs due to a version incompatibility between the Sentry React Native package and the native Sentry SDK.

To resolve this error (as of **@sentry/react-native v5.31.0** and **iOS Sentry v8.36.0**), update the import statements in your code.

In `SentrySdkInfo.h` and `SentryInternalSerializable.h`, replace:

```javascript
// Replace
#import "SentryDefines.h"

// With
#import <Sentry/SentryDefines.h>
```

{% endhint %}
{% endtab %}

{% tab title="iOS" %}

1. Before using the ComplyCube SDK, install the **CocoaPods** plugin by running the following command in your terminal:<br>

   ```bash
   sudo gem install cocoapods
   ```

2. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
   source 'https://github.com/CocoaPods/Specs.git'
   …
   platform :iOS, ’13.0’

   target ‘YourApp’ do
       …
     pod 'ComplyCubeMobileSDK'
   end

   post_install do |installer|
       installer.pods_project.targets.each do |target|
           target.build_configurations.each do |build_configuration|
               build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
               build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
               build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.1'
               build_configuration.build_settings['ARCHS'] = ['$(ARCHS_STANDARD)', 'x86_64']
               build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = ['arm64', 'arm64e', 'armv7', 'armv7s']
               build_configuration.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES'
           end
       end
   end
   ```

\
**Application permissions**

Our SDK uses the device camera and microphone for capture. You must add the following keys to your application `Info.plist` file.

1. `NSCameraUsageDescription`

```xml
<key>NSCameraUsageDescription</key>
<string>Used to capture facials biometrics and documents</string>
```

2. `NSMicrophoneUsageDescription`

```xml
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture video biometrics</string>
```

{% endtab %}

{% tab title="Android" %}
Our SDK requires the repositories below.

```java
repositories {
  mavenCentral()
}

dependencies {
    implementation "com.complycube:complycube-sdk:+"
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

This must be done on your **mobile app backend** server, not the mobile app itself.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables customers to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Initialize the SDK

As part of initializing the SDK, you are required to specify a [workflow template ID](https://portal.complycube.com/workflowTemplates). The SDK will automatically run the **active** version of the selected workflow.

```jsx
import { ComplyCube } from "@complycube/react-native";
// ...

const settings = {
  clientID: "<CLIENT_ID>",
  clientToken: "<CLIENT_TOKEN>",
  workflowTemplateId: "<WORKFLOW_TEMPLATE_ID>",
  // ... other settings
};

return (
  <View style={styles.container}>
    <ComplyCube settings={settings} />
  </View>
);
```

{% endstep %}

{% step %}

#### Perform checks

Once your customer starts the flow, a [workflow session](/documentation/product-guides/compliance-studio/workflows#workflow-session) is automatically created. This session contains all captured data (documents, images, and videos) as well as progress tracking. You can view all of them through the [workflow sessions page](https://portal.complycube.com/workflowSessions) on the portal or through the API.

When the flow finishes, the SDK triggers the `onSuccess` callback. The callback provides a `data` object that includes the `workflowSessionId`. Your **mobile backend** should use this ID to notify ComplyCube that the [workflow has completed](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session), which in turn runs the verification checks defined in the workflow.

If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a workflow session completes.

#### Example of a complete workflow session request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/workflowSessions/{:wfSessionId}/complete \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.complete("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.complete('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->complete('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.CompleteAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve the workflow session details and associated check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

You can retrieve the details of a workflow session by calling the [retrieve workflow session request](/documentation/api-reference/core-resources/workflow-sessions/get-a-workflow-session).

To retrieve the check results, you can perform a [get check request](/documentation/api-reference/core-resources/checks/get-a-check).

**Example of a workflow session retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/workflowSessions/{:workflowSessionId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.get("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.get('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->get('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.GetAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}

**Example of a check retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

{% tabs %}
{% tab title="iOS" %}
{% hint style="info" %}
To use this feature, your app must have the **`Near Field Communication Tag Reading`** capability enabled. To add this capability to your app, refer to [Apple's guide here](https://help.apple.com/xcode/mac/current/#/dev88ff319e7).
{% endhint %}

1. Install the **CocoaPods Artifactory** plugin by running the following command in your terminal:<br>

   ```bash
   gem install cocoapods-art
   ```

2. To add the library, copy your repository credentials into a `.netrc` file to your home directory and setup the repository:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">pod repo-art add cc-cocoapods-release-local "https://complycuberepo.jfrog.io/artifactory/api/pods/cc-cocoapods-release-local"
   </code></pre>

   \
   Remember to fetch your credentials from **JFrog** using the **Set Me Up** button [here](https://complycuberepo.jfrog.io/ui/repos/tree/General/cc-cocoapods-release-local).<br>

3. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
    plugin 'cocoapods-art', :sources => [
      'cc-cocoapods-release-local',
      'trunk'
    ]
    ...
    platform :ios, '13.0' # Or above

    target 'YourApp' do
      use_frameworks!
      use_modular_headers!
      ...
      pod 'ComplyCubeMobileSDK', '2.0.x-nfc'
      ...
    en
   ```

4. You must add the following keys to your application `Info.plist` file:<br>

   ```xml
   <key>NFCReaderUsageDescription</key>
   <string>Required to read from NFC enabled documents</string>
   ```

5. To read NFC tags correctly, you need to add the following entries to your app target's `Info.plist` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
   <array>
     <string>12FC</string>
   </array>
   <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
   <array>
     <string>A0000002471001</string>
     <string>A0000002472001</string>
     <string>00000000000000</string>
     <string>D2760000850101</string>
     <string>E80704007F00070302</string>
     <string>A000000167455349474E</string>
     <string>A00000045645444C2D3031</string>
   </array>
   ```

6. Add the following in your `Runner.entitlements` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.formats</key>
   <array><string>TAG</string></array>
   ```

7. To enable NFC when building your iOS app, pass the `USE_CCNFC` environment variable during the build:<br>

   ```bash
   USE_CCNFC=true flutter build ios
   ```

   \
   To keep this enabled for all iOS builds, add the following line near the top of your `ios/Podfile`:<br>

   ```ruby
   ENV['USE_CCNFC'] ||= 'true'
   ```

{% endtab %}

{% tab title="Android" %}

1. Start by adding your access credentials for the ComplyCube NFC-Enabled SDK repository to the `gradle.properties` file of your **mobile app**:

```gradle
USE_NFC=true
artifactory_contextUrl=https://complycuberepo.jfrog.io/artifactory/cc-gradle-release
artifactory_user=<YOUR_USERNAME>
artifactory_password=<YOUR_PASSWORD>
```

> Replace <**YOUR\_USERNAME**> and <**YOUR\_PASSWORD**> with your ComplyCube Artifactory credentials. If you don’t have access, contact ComplyCube Support to request credentials.

2. Then, update your project level `build.gradle` or `build.gradle.kts` file with the ComplyCube SDK repository Maven settings:

{% tabs %}
{% tab title="Groovy" %}

```javascript
repositories {
    google()
    mavenCentral()
    maven {
        url project.findProperty("artifactory_contextUrl")
        credentials {
            username = project.findProperty("artifactory_user")
            password = project.findProperty("artifactory_password")
        }
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```python
repositories {
    google()
    mavenCentral()
    maven {
        url = uri(project.findProperty("artifactory_contextUrl") as String)
        credentials {
            username = project.findProperty("artifactory_user") as String?
            password = project.findProperty("artifactory_password") as String?
        }
    }
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

## Branding

You can customise colours, logos, and other branding elements through the [branding settings page](https://portal.complycube.com/settings/branding), if available on your plan.

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run a verification session, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger a [workflow session complete requests](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session) from your backend using the workflow session ID returned in the result object.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

```jsx
function onSuccess(results){
  /*
    Handling successful results:
    The 'results' parameter will contain: 
      - "workflowSessionId": "xxxxx"
  */
  console.log(results);
}

function onCancelled(){
  console.log("The user cancelled");
}

function onError(error){
  console.log(error);
}

return(<View>
    <ComplyCube 
      settings={settings}
      onSuccess={onSuccess}
      onCancel={onCancelled}
      onError={onError}
       />
  </View>
)
```

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using the `eventHandler` property in your `settings`:

```jsx
function myCustomEventHandler(event){
  // Insert custom user tracking code here
  console.log(event.code);
  console.log(event.message);
}

const settings = {
  eventHandler: myCustomEventHandler,
  // ... other settings
}
```

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

```jsx
function myCustomExpiryHandler(){
  // Insert custom token renewal code here
}

const settings = {
  tokenExpiryHandler: myCustomExpiryHandler,
  // ... other settings
}
```


# Check-Driven Integration

Build check-driven KYC and identity verification flows in React Native apps.

## Overview

This guide walks you through integrating the **React Native SDK** with ComplyCube using the check-driven approach, giving you direct control over individual verification steps.

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

{% hint style="warning" %}
You’re viewing the **check-driven** SDK guide - an approach that provides detailed control but is best suited for **partners** or **advanced use cases.**  We recommend using **workflow integration** for most implementations.
{% endhint %}

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/zw3kOMTk0aUWjhA2t9I0" alt=""><figcaption><p>Mobile SDK Integration flow</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-react-native-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

{% tabs %}
{% tab title="React Native" %}

1. Install the React Native library by running:

```bash
npm i -s @complycube/react-native
```

2. Complete the steps in the **iOS** and **Android** tabs.

{% hint style="danger" %}

#### Sentry integration

If you’re integrating Sentry into your React Native project, you might encounter the following compiler error:

```javascript
'SentryDefines.h' file cannot be found.
```

This issue occurs due to a version incompatibility between the Sentry React Native package and the native Sentry SDK.

To resolve this error (as of **@sentry/react-native v5.31.0** and **iOS Sentry v8.36.0**), update the import statements in your code.

In `SentrySdkInfo.h` and `SentryInternalSerializable.h`, replace:

```javascript
// Replace
#import "SentryDefines.h"

// With
#import <Sentry/SentryDefines.h>
```

{% endhint %}
{% endtab %}

{% tab title="iOS" %}

1. Before using the ComplyCube SDK, install the **CocoaPods** plugin by running the following command in your terminal:<br>

   ```bash
   sudo gem install cocoapods
   ```

2. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
   source 'https://github.com/CocoaPods/Specs.git'
   …
   platform :iOS, ’13.0’

   target ‘YourApp’ do
       …
     pod 'ComplyCubeMobileSDK'
   end

   post_install do |installer|
       installer.pods_project.targets.each do |target|
           target.build_configurations.each do |build_configuration|
               build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
               build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
               build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.1'
               build_configuration.build_settings['ARCHS'] = ['$(ARCHS_STANDARD)', 'x86_64']
               build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = ['arm64', 'arm64e', 'armv7', 'armv7s']
               build_configuration.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES'
           end
       end
   end
   ```

\
**Application permissions**

Our SDK uses the device camera and microphone for capture. You must add the following keys to your application `Info.plist` file.

1. `NSCameraUsageDescription`

```xml
<key>NSCameraUsageDescription</key>
<string>Used to capture facials biometrics and documents</string>
```

2. `NSMicrophoneUsageDescription`

```xml
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture video biometrics</string>
```

{% endtab %}

{% tab title="Android" %}
Our SDK requires the repositories below.

```java
repositories {
  mavenCentral()
}

dependencies {
    implementation "com.complycube:complycube-sdk:+"
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

This must be done on your **mobile app backend** server, not the mobile app itself.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables customers to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Prepare the stages

Set up the stages you wish to include in your flow.

```jsx
const stages = [
  {
    name: "intro",
    heading: "Green Bank ID verification",
  },
  {
    name: "documentCapture",
    showGuidance: false,
    useMLAssistance: true,
    retryLimit: 1,
    documentTypes: {
      passport: true,
      driving_license: ["GB", "FR"],
    },
  },
  "faceCapture",
];
```

{% endstep %}

{% step %}

#### Initialize the SDK

You can now initialize a flow. The sequence of stages you specify determines the order in which your client sees those stages.

```jsx
import { ComplyCube } from "@complycube/react-native";
// ...

const settings = {
  clientID: "<CLIENT_ID>",
  clientToken: "<CLIENT_TOKEN>",
  stages: stages,
  // ... other settings
};

return (
  <View style={styles.container}>
    <ComplyCube settings={settings} />
  </View>
);
```

{% endstep %}

{% step %}

#### Perform checks

Using the results returned in the `onSuccess` callback, you can trigger your **mobile backend** to run the necessary checks on your client.

For example, use the result of a selfie and document capture as follows:

* `result.documentId` to run a [Document Check](https://docs.complycube.com/api-reference/check-types/document-check).
* `result.documentId` and `result.livePhotoId` to run an [Identity Check](https://docs.complycube.com/api-reference/check-types/identity-check).

**Example request for a Document Check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
            "clientId":"CLIENT_ID",
            "type": "document_check",
            "documentId":"DOCUMENT_ID"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.create("CLIENT_ID", {
    type: "document_check",
    documentId: "DOCUMENT_ID"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.create(
    "CLIENT_ID", 
    "document_check", 
    documentId="DOCUMENT_ID"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->checks()->create('CLIENT_ID', [
    'type' => 'document_check',
    'documentId' => 'DOCUMENT_ID'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var checkRequest = new CheckRequest {
  clientId = "CLIENT_ID",
  type = "document_check",
  documentId = "DOCUMENT_ID"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve all check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).

#### Example request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## Stages

Each stage in the flow can be customized to create the ideal journey for your customers.

The snippet below demonstrates how to set up a customized flow using the ComplyCube Mobile SDK.

```jsx
const stages = [
  {
    name: 'intro',
    // ... other settings
  },
  {
    name: "consent",
    // ... other settings
  },
  {
    name: 'documentCapture',
    // ... other settings
  },
  {
    name: "faceCapture",
    // ... other settings
  },
  {
    name: "poaCapture",
    // ... other settings
  },
  {
    name: "complete",
    // ... other settings
  }
];

const settings = {
  clientID: "CLIENT_ID",
  clientToken: "SDK_TOKEN",
  stages: stages,
  language: "en",
  lookAndFeel: {/*...*/}
}

<ComplyCube
  settings={settings} 
  onSuccess={/*...*/} 
  onCancel={/*...*/}
  onError={/*...*/}
  onEventCallback={/*...*/}
/>
```

### **Welcome**

The Welcome screen is always shown first in the verification flow. It displays a welcome message along with a summary of the configured stages the user will complete.

You can customize the screen title to align with your app’s tone and branding.

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "intro",
      heading: "Custom Screen Title",
      message: "Custom welcome message.",
    },
    // ... other stages
  ],
};
```

### **Consent**

This stage is used to collect explicit user consent before proceeding with the verification flow. It helps you meet regulatory and compliance requirements where applicable.

You can customize the screen title and message to match your legal or branding needs.

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "consent",
      heading: "Custom Consent Screen Title"
    },
    // ... other stages
  ],
};
```

### **Selfie photo and video**

You can request either a selfie photo  (i.e. a [Live Photo](/documentation/api-reference/core-resources/live-photos)) or a selfie video (i.e. a [Live Video](/documentation/api-reference/core-resources/live-videos)) from the customer as part of the biometric verification process.

* **Photo**: Captures a still image and performs a passive liveness check before allowing submission.
* **Video**: Records a short video where the user completes an on-screen challenge (e.g. head movement or spoken phrase).

{% hint style="warning" %}
If you attempt to add both types of stages, the SDK will throw a **`ComplyCubeErrorCode.BiometricStageCount`** error stating multiple conflicting stages.
{% endhint %}

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "faceCapture",
      mode: "photo",
      // Enable ML assistance during capture
      useMLAssistance: false,
    },
    // ... other stages
  ],
};
```

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "faceCapture",
      mode: "video",
      // Enable ML assistance during capture
      useMLAssistance: false,
    },
    // ... other stages
  ],
};
```

### **Document**

The Document stage allows users to select and capture an identity document for verification (e.g. passport, ID card, residence permit). You can customize these screens to:

* Limit the scope of document types the client can select, e.g., Passport only.
* Set the document issuing countries they are allowed for each document type.
* Add or remove automated capture using smart assistance.
* Show or hide the instruction screens before capture.
* Set a retry limit to allow clients to progress the journey regardless of capture quality.

{% hint style="info" %}
If you provide only one document type, the document type selection screen will be skipped. The country selection screen will be skipped if you provide only a single country for a given document type.
{% endhint %}

You can control whether instructional screens are shown before each camera capture by enabling or disabling guidance mode. Only disable guidance if your users are already clearly informed about the capture steps, as these screens help reduce user error and improve capture quality.

{% hint style="info" %}
Please note the `retryLimit` you set here will take precedence over the retry limit that has been set globally in your [automation settings](https://portal.complycube.com/automations).
{% endhint %}

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "documentCapture",

      // Enable or disable additional guidance for the user
      showGuidance: false,

      // Enable ML assistance during capture
      useMLAssistance: true,

      // Set a maximum for quality check attempts before uploading
      retryLimit: 1,

      // Enable or disable the ability to upload an image from file
      liveCapture: false,

      // Set document types and limit the enabled countries
      documentTypes: {
        passport: true,
        driving_license: ["GB", "US"],
      },
    },
    // ... other stages
  ],
};
```

### NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

{% tabs %}
{% tab title="iOS" %}
{% hint style="info" %}
To use this feature, your app must have the **`Near Field Communication Tag Reading`** capability enabled. To add this capability to your app, refer to [Apple's guide here](https://help.apple.com/xcode/mac/current/#/dev88ff319e7).
{% endhint %}

1. Install the **CocoaPods Artifactory** plugin by running the following command in your terminal:<br>

   ```bash
   gem install cocoapods-art
   ```

2. To add the library, copy your repository credentials into a `.netrc` file to your home directory and setup the repository:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">pod repo-art add cc-cocoapods-release-local "https://complycuberepo.jfrog.io/artifactory/api/pods/cc-cocoapods-release-local"
   </code></pre>

   \
   Remember to fetch your credentials from **JFrog** using the **Set Me Up** button [here](https://complycuberepo.jfrog.io/ui/repos/tree/General/cc-cocoapods-release-local).<br>

3. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
    plugin 'cocoapods-art', :sources => [
      'cc-cocoapods-release-local',
      'trunk'
    ]
    ...
    platform :ios, '13.0' # Or above

    target 'YourApp' do
      use_frameworks!
      use_modular_headers!
      ...
      pod 'ComplyCubeMobileSDK', '2.0.x-nfc'
      ...
    en
   ```

4. You must add the following keys to your application `Info.plist` file:<br>

   ```xml
   <key>NFCReaderUsageDescription</key>
   <string>Required to read from NFC enabled documents</string>
   ```

5. To read NFC tags correctly, you need to add the following entries to your app target's `Info.plist` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
   <array>
     <string>12FC</string>
   </array>
   <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
   <array>
     <string>A0000002471001</string>
     <string>A0000002472001</string>
     <string>00000000000000</string>
     <string>D2760000850101</string>
     <string>E80704007F00070302</string>
     <string>A000000167455349474E</string>
     <string>A00000045645444C2D3031</string>
   </array>
   ```

6. Add the following in your `Runner.entitlements` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.formats</key>
   <array><string>TAG</string></array>
   ```

7. To enable NFC when building your iOS app, pass the `USE_CCNFC` environment variable during the build:<br>

   ```bash
   USE_CCNFC=true flutter build ios
   ```

   \
   To keep this enabled for all iOS builds, add the following line near the top of your `ios/Podfile`:<br>

   ```ruby
   ENV['USE_CCNFC'] ||= 'true'
   ```

{% endtab %}

{% tab title="Android" %}

1. Start by adding your access credentials for the ComplyCube NFC-Enabled SDK repository to the `gradle.properties` file of your **mobile app**:

```gradle
USE_NFC=true
artifactory_contextUrl=https://complycuberepo.jfrog.io/artifactory/cc-gradle-release
artifactory_user=<YOUR_USERNAME>
artifactory_password=<YOUR_PASSWORD>
```

> Replace <**YOUR\_USERNAME**> and <**YOUR\_PASSWORD**> with your ComplyCube Artifactory credentials. If you don’t have access, contact ComplyCube Support to request credentials.

2. Then, update your project level `build.gradle` or `build.gradle.kts` file with the ComplyCube SDK repository Maven settings:

{% tabs %}
{% tab title="Groovy" %}

```javascript
repositories {
    google()
    mavenCentral()
    maven {
        url project.findProperty("artifactory_contextUrl")
        credentials {
            username = project.findProperty("artifactory_user")
            password = project.findProperty("artifactory_password")
        }
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```python
repositories {
    google()
    mavenCentral()
    maven {
        url = uri(project.findProperty("artifactory_contextUrl") as String)
        credentials {
            username = project.findProperty("artifactory_user") as String?
            password = project.findProperty("artifactory_password") as String?
        }
    }
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

#### Enabling NFC capture

```jsx
const settings = {
    // ... other settings
    stages : [
      {
        name: 'documentCapture',
        // Add this property to enable NFC
        nfcEnabled: true
        ...
      },
      // ... other stages
    ]
}
```

### **Address capture**

This stage allows users to manually enter their residential address. You can customize it to:

* Restrict input to specific countries
* Enable or disable the address autocomplete feature for faster and more accurate entry

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "addressCapture",

      // This enables our address autocomplete feature
      useAutoComplete: false,
      
      // A list of acceptable countries for address capture
      allowedCountries: ['GB','US']
    },
    // ... other stages
  ],
};
```

### **Proof of address**

This stage allows customers to submit a document verifying their residential address. You can configure which document types are accepted, such as utility bills or bank statements, and choose whether customers can upload a file or must capture the document live using their device camera.

{% hint style="info" %}
By default, this stage includes the **address capture stage** with autocomplete enabled to assist users during entry. Autocomplete can be disabled if not required.
{% endhint %}

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "poaCapture",

      // When disabled, the client will be forced to perform a live capture
      liveCapture: false,
    },
    // ... other stages
  ],
};
```

### **Completion**

You can include a completion stage at the end of the flow to confirm that the process has been successfully finished. This screen provides a clear end point for the user and can be customized to display a confirmation message or next steps.

```jsx
const settings = {
  // ... other settings
  stages: [
    {
      name: "complete",
      heading: "Thank you!",
      message: "Your KYC submission has been completed.",
    },
    // ... other stages
  ],
};
```

## Branding

The SDK allows you to customize the UI to match your application’s visual identity. You can define primary and accent colors during configuration to align the verification flow with your brand guidelines. Learn more about our **appearance properties** (see below).

```jsx
const settings = {
  // ...
  lookAndFeel: {
    // Primary action button background color
    primaryButtonBgColor: "#FFFFFF",

    // Force SDK to 'dark', 'light', or 'inherit' mode
    uiInterfaceStyle: "dark",
  },
};
```

<details>

<summary>Appearance properties</summary>

<table><thead><tr><th width="371.70703125">Appearance Property</th><th>Description</th></tr></thead><tbody><tr><td><code>primaryButtonBgColor</code></td><td>Primary action button background color.</td></tr><tr><td><code>primaryButtonTextColor</code></td><td>Primary action button text color.</td></tr><tr><td><code>primaryButtonBorderColor</code></td><td>Primary action button border color.</td></tr><tr><td><code>secondaryButtonBgColor</code></td><td>Secondary button background color.</td></tr><tr><td><code>secondaryButtonPressedBgColor</code></td><td>Secondary action button pressed background color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>secondaryButtonTextColor</code></td><td>Secondary action button text color.</td></tr><tr><td><code>secondaryButtonBorderColor</code></td><td>Secondary action button border color.</td></tr><tr><td><code>documentTypeSelectorBgColor</code></td><td>Document type selection button color.</td></tr><tr><td><code>documentTypeSelectorBorderColor</code></td><td>Document type selection button border color.</td></tr><tr><td><code>documentTypeSelectorTitleTextColor</code></td><td>Document type selection title text color.</td></tr><tr><td><code>documentTypeSelectorDescriptionTextColor</code></td><td>Document type selection description text color.</td></tr><tr><td><code>documentTypeSelectorIconColor</code></td><td>Document type selection icon color.</td></tr><tr><td><code>bodyTextColor</code></td><td>Screen body text color.</td></tr><tr><td><code>linkButtonTextColor</code></td><td>Links color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>headingTextColor</code></td><td>Title heading text color.</td></tr><tr><td><code>subheadingTextColor</code></td><td>Subheading text color.</td></tr><tr><td><code>infoPanelTitleColor</code></td><td>Information panel title color.</td></tr><tr><td><code>infoPanelDescriptionTextColor</code></td><td>Information panel description text color.</td></tr><tr><td><code>infoPanelBgColor</code></td><td>Information panel background color.</td></tr><tr><td><code>infoPanelIconColor</code></td><td>Information panel icon color.</td></tr><tr><td><code>errorPanelTitleColor</code></td><td>Error panel title color.</td></tr><tr><td><code>errorPanelDescriptionTextColor</code></td><td>Error panel description text color.</td></tr><tr><td><code>errorPanelBgColor</code></td><td>Error panel background color.</td></tr><tr><td><code>errorPanelIconColor</code></td><td>Error panel icon color.</td></tr><tr><td><code>cameraButtonBgColor</code></td><td>Camera capture button background color.</td></tr><tr><td><code>uiInterfaceStyle</code></td><td>Set the SDK to use dark mode, light mode, or system Inherited.</td></tr></tbody></table>

</details>

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run verification checks, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger [check requests](/documentation/api-reference/core-resources/checks/create-a-check) from your backend using the resource IDs returned in the result object. These IDs correspond to the uploaded assets (e.g. documents, selfies) and can be used to initiate verification checks via the ComplyCube API.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

```jsx
function onSuccess(results){
  /*
    Handling successful results:
    Our default flow includes three components: an Identity Document,
    a Selfie (Live Photo), and a Proof of Address. Upon successful 
    completion, the 'results' parameter will contain: 
      - "documentIds": ["xxxxx"]
      - "livePhotoIds": ["xxxxx"]
      - "poaIds": ["xxxxxx"]
  */
  console.log(results);
}

function onCancelled(){
  console.log("The user cancelled");
}

function onError(error){
  console.log(error);
}

return(<View>
    <ComplyCube 
      settings={settings}
      onSuccess={onSuccess}
      onCancel={onCancelled}
      onError={onError}
       />
  </View>
)
```

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using the `eventHandler` property in your `settings`:

```jsx
function myCustomEventHandler(event){
  // Insert custom user tracking code here
  console.log(event.code);
  console.log(event.message);
}

const settings = {
  eventHandler: myCustomEventHandler,
  // ... other settings
}
```

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

```jsx
function myCustomExpiryHandler(){
  // Insert custom token renewal code here
}

const settings = {
  tokenExpiryHandler: myCustomExpiryHandler,
  // ... other settings
}
```


# Flutter SDK

Embed KYC and identity verification flows in Flutter apps with ComplyCube.

## Overview

The **ComplyCube Flutter SDK** enables you to embed a full identity verification flow directly into your Flutter application using native, mobile-optimized components.

Designed for easy integration, the SDK handles everything from document capture and biometric liveness checks to proof of address and NFC authentication. It’s optimised for speed and accuracy, with features like auto-capture and real-time feedback.

{% embed url="<https://www.youtube.com/watch?v=n8kAGXQykkA>" %}
ComplyCube Mobile SDK Demo
{% endembed %}

## Benefits

The SDK offers several benefits:

* **Mobile-native flow:** Frictionless user experience using mobile-native UI components. Includes guided flows for capturing selfies, videos, identity documents, and proof of address.
* **Flexible integration**: Use [workflows](/documentation/product-guides/compliance-studio/workflows) to orchestrate complete verification journeys with minimal code, or configure individual stages (e.g. selfie, document, NFC) for more granular control.
* **Biometric verification**: Supports photo and video-based liveness checks (**PAD Level 2 certified)** using passive and active techniques to detect spoofing.
* **Document & NFC verification:** Supports OCR and RFID reading from passports, ID cards, and other chip-enabled documents. Cross-checks encrypted chip data for added assurance.
* **Smart auto-capture**: Automatically captures selfies and documents with real-time quality checks, reducing user errors and ensuring optimal input for verification.
* **Custom branding**: Customize accent colors, text, and logos to match your app’s visual identity.
* **Global-ready**: Built-in support for multiple languages and localized UI labels.

## Requirements

{% tabs %}
{% tab title="Flutter" %}

* **Flutter** 3.3.0 and above.
* **Dart** 3.1.3 and above.
  {% endtab %}

{% tab title="iOS" %}

* **Swift 5**.
* **iOS 13** and above.
* **Xcode 13** and above.
  {% endtab %}

{% tab title="Android" %}

* **Android 5.0** (API level 21) and above.
* **AndroidX**.
* **Kotlin 1.7** and above.
  {% endtab %}
  {% endtabs %}

## Integration modes

The Flutter SDK can be integrated in two different ways, depending on your needs:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Workflow Integration</strong></mark></td><td>Use the Workflow Designer to build your customer KYC journey and simply load it through the SDK. This is the preferred option for most use cases.</td><td><strong>Recommended</strong></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/QJdOIhXaRqxgs1r0MVJ4">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/QJdOIhXaRqxgs1r0MVJ4</a></td></tr><tr><td><mark style="color:blue;"><strong>Check-Driven Integration</strong></mark></td><td>A lower-level approach where you directly control individual SDK screens and checks. It's best suited for advanced use cases.</td><td></td><td><a href="/spaces/lv7UhJvTbxeq4s3KwQpn/pages/UdonE6mNIR4Dg5J3e9fB">/spaces/lv7UhJvTbxeq4s3KwQpn/pages/UdonE6mNIR4Dg5J3e9fB</a></td></tr></tbody></table>


# Workflow Integration

Integrate KYC workflows in Flutter apps using the ComplyCube SDK.

## Overview

This guide walks you through integrating the **Flutter SDK** with ComplyCube [workflows](/documentation/product-guides/compliance-studio/workflows).

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture data, documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/QphA3xsRYHb17fG8zplz" alt=""><figcaption><p>Mobile SDK Integration via Workflows Guide</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-flutter-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

{% tabs %}
{% tab title="Flutter" %}

1. Install the **ComplyCube Flutter** package by running:

   ```bash
   flutter pub add complycube
   ```
2. **iOS**
   1. Complete the **steps 1 and 2** in the **iOS** tabs.
   2. Add the snippet below to your `ios/PodFile` and run the `pod install` command.<br>

      ````ruby
      source 'https://github.com/CocoaPods/Specs.git'

      platform :iOS, '13.0'

      target 'Runner' do
        use_frameworks!
        use_modular_headers!
          ...
          ...
      end
      ...
      post_install do |installer|
       installer.pods_project.targets.each do |target|
         flutter_additional_ios_build_settings(target)
         target.build_configurations.each do |config|
           config.build_settings['ENABLE_BITCODE'] = 'NO'
           config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
           config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
           config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
         end
       end
      end```
      ````
   3. Complete **Application permissions steps** in the **iOS** tabs.<br>
3. **Android**
   1. Complete the steps in the **Android** tab.

{% hint style="danger" %}

#### iOS deployment targeting

If you’re targeting a specific iOS version above 13.0 for any of your dependencies, and you face the following error:<br>

{% code overflow="wrap" %}

```
Compiling for iOS 13.0, but module 'CocoaLumberjack' has a minimum deployment target of iOS 15.0
```

{% endcode %}

\
You can use the snippet below in your PodFile `post_install` script.

```ruby
post_install do |installer|
  ios_13_pods = [
    'Sentry',
    'Analytics',
    'Alamofire',
    'SwiftyJSON',
    'JWTDecode',
    'GooglePlaces',
    'lottie-ios'
  ]
  
  installer.pods_project.targets.each do |target|
      ....
      
      # Set deployment target based on pod name
      if ios_13_pods.any? { |pod_name| target.name.start_with?(pod_name) }
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
        puts "Setting #{target.name} to iOS 13.0"
      else
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
      end
      
      ....
```

{% endhint %}
{% endtab %}

{% tab title="iOS" %}

1. Before using the ComplyCube SDK, install the **CocoaPods** plugin by running the following command in your terminal:<br>

   ```bash
   sudo gem install cocoapods
   ```

2. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
   source 'https://github.com/CocoaPods/Specs.git'
   …
   platform :iOS, ’13.0’

   target ‘YourApp’ do
       …
     pod 'ComplyCubeMobileSDK'
   end

   post_install do |installer|
       installer.pods_project.targets.each do |target|
           target.build_configurations.each do |build_configuration|
               build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
               build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
               build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.1'
               build_configuration.build_settings['ARCHS'] = ['$(ARCHS_STANDARD)', 'x86_64']
               build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = ['arm64', 'arm64e', 'armv7', 'armv7s']
               build_configuration.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES'
           end
       end
   end
   ```

\
**Application permissions**

Our SDK uses the device camera and microphone for capture. You must add the following keys to your application `Info.plist` file.

1. `NSCameraUsageDescription`

```xml
<key>NSCameraUsageDescription</key>
<string>Used to capture facials biometrics and documents</string>
```

2. `NSMicrophoneUsageDescription`

```xml
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture video biometrics</string>
```

{% endtab %}

{% tab title="Android" %}
No action required.
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

This must be done on your **mobile app backend** server, not the mobile app itself.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables customers to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Initialize the SDK

As part of initializing the SDK, you are required to specify a [workflow template ID](https://portal.complycube.com/workflowTemplates). The SDK will automatically run the **active** version of the selected workflow.

```dart
import 'package:complycube_flutter/ComplyCubeMobileSDK.dart';
// ...

final settings = {
  "clientID": "<CLIENT_ID>",
  "clientToken": "<CLIENT_TOKEN>",
  "workflowTemplateId": "<WORKFLOW_TEMPLATE_ID>",
  // ...
};

return MaterialApp(
  home: Scaffold(
    appBar: AppBar(
      title: Text('ComplyCube Integration'),
    ),
    body: Column(
      children: [
        ElevatedButton(
          onPressed: () async {
            await ComplyCube.start(settings);
          },
          child: const Text('Start verification'),
        ),
      ],
    ),
  ),
);
```

{% endstep %}

{% step %}

#### Perform verification

Once your customer starts the flow, a [workflow session](/documentation/product-guides/compliance-studio/workflows#workflow-session) is automatically created. This session contains all captured data (documents, images, and videos) as well as progress tracking. You can view all of them through the [workflow sessions page](https://portal.complycube.com/workflowSessions) on the portal or through the API.

When the flow finishes, the SDK triggers the `onSuccess` callback. The callback provides a `data` object that includes the `workflowSessionId`. Your **mobile backend** should use this ID to notify ComplyCube that the [workflow has completed](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session), which in turn runs the verification checks defined in the workflow.

If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a workflow session completes.

#### Example of a complete workflow session request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/workflowSessions/{:wfSessionId}/complete \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.complete("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.complete('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->complete('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.CompleteAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve the workflow session details and associated check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

You can retrieve the details of a workflow session by calling the [retrieve workflow session request](/documentation/api-reference/core-resources/workflow-sessions/get-a-workflow-session).

To retrieve the check results, you can perform a [get check request](/documentation/api-reference/core-resources/checks/get-a-check).

**Example of a workflow session retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/workflowSessions/{:workflowSessionId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const wfSession = await complycube.workflowSession.get("WORKFLOW_SESSION_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

workflow_session = cc_api.workflowsessions.get('WORKFLOW_SESSION_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$workflowSession = $ccapi->workflowSessions()->get('WORKFLOW_SESSION_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.WorkflowSessions;

var wfSessionApi = new WorkflowSessionApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var workflowSession = await wfSessionApi.GetAsync("WORKFLOW_SESSION_ID");
```

{% endtab %}
{% endtabs %}

**Example of a check retrieval request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

{% tabs %}
{% tab title="iOS" %}
{% hint style="info" %}
To use this feature, your app must have the **`Near Field Communication Tag Reading`** capability enabled. To add this capability to your app, refer to [Apple's guide here](https://help.apple.com/xcode/mac/current/#/dev88ff319e7).
{% endhint %}

1. Install the **CocoaPods Artifactory** plugin by running the following command in your terminal:<br>

   ```bash
   gem install cocoapods-art
   ```

2. To add the library, copy your repository credentials into a `.netrc` file to your home directory and setup the repository:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">pod repo-art add cc-cocoapods-release-local "https://complycuberepo.jfrog.io/artifactory/api/pods/cc-cocoapods-release-local"
   </code></pre>

   \
   Remember to fetch your credentials from **JFrog** using the **Set Me Up** button [here](https://complycuberepo.jfrog.io/ui/repos/tree/General/cc-cocoapods-release-local).<br>

3. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
    plugin 'cocoapods-art', :sources => [
      'cc-cocoapods-release-local',
      'trunk'
    ]
    ...
    platform :ios, '13.0' # Or above

    target 'YourApp' do
      use_frameworks!
      use_modular_headers!
      ...
      pod 'ComplyCubeMobileSDK', '2.0.x-nfc'
      ...
    en
   ```

4. You must add the following keys to your application `Info.plist` file:<br>

   ```xml
   <key>NFCReaderUsageDescription</key>
   <string>Required to read from NFC enabled documents</string>
   ```

5. To read NFC tags correctly, you need to add the following entries to your app target's `Info.plist` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
   <array>
     <string>12FC</string>
   </array>
   <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
   <array>
     <string>A0000002471001</string>
     <string>A0000002472001</string>
     <string>00000000000000</string>
     <string>D2760000850101</string>
     <string>E80704007F00070302</string>
     <string>A000000167455349474E</string>
     <string>A00000045645444C2D3031</string>
   </array>
   ```

6. Add the following in your `Runner.entitlements` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.formats</key>
   <array><string>TAG</string></array>
   ```

7. To enable NFC when building your iOS app, pass the `USE_CCNFC` environment variable during the build:<br>

   ```bash
   USE_CCNFC=true flutter build ios
   ```

   \
   To keep this enabled for all iOS builds, add the following line near the top of your `ios/Podfile`:<br>

   ```ruby
   ENV['USE_CCNFC'] ||= 'true'
   ```

{% endtab %}

{% tab title="Android" %}

1. Start by adding your access credentials for the ComplyCube NFC-Enabled SDK repository to the `gradle.properties` file of your **mobile app**:

```gradle
USE_NFC=true
artifactory_contextUrl=https://complycuberepo.jfrog.io/artifactory/cc-gradle-release
artifactory_user=<YOUR_USERNAME>
artifactory_password=<YOUR_PASSWORD>
```

> Replace <**YOUR\_USERNAME**> and <**YOUR\_PASSWORD**> with your ComplyCube Artifactory credentials. If you don’t have access, contact ComplyCube Support to request credentials.

2. Then, update your project level `build.gradle` or `build.gradle.kts` file with the ComplyCube SDK repository Maven settings:

{% tabs %}
{% tab title="Groovy" %}

```javascript
repositories {
    google()
    mavenCentral()
    maven {
        url project.findProperty("artifactory_contextUrl")
        credentials {
            username = project.findProperty("artifactory_user")
            password = project.findProperty("artifactory_password")
        }
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```python
repositories {
    google()
    mavenCentral()
    maven {
        url = uri(project.findProperty("artifactory_contextUrl") as String)
        credentials {
            username = project.findProperty("artifactory_user") as String?
            password = project.findProperty("artifactory_password") as String?
        }
    }
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

## Branding

You can customise colours, logos, and other branding elements through the [branding settings page](https://portal.complycube.com/settings/branding), if available on your plan.

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run a verification session, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger a [workflow session complete requests](/documentation/api-reference/core-resources/workflow-sessions/complete-a-workflow-session) from your backend using the workflow session ID returned in the result object.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

```dart
void onSuccess(dynamic payload) {
  /*
    Handling successful results.
    The 'results' parameter will contain: 
      - "workflowSessionId": "xxxxx"
  */
}

void onSuccess(dynamic payload) {
  /*
    Handling successful results.
    The default flow (Identity Document + Live Photo + Proof of Address)
    delivers a payload shaped like:
      {
        "documentIds":  ["xxxxx"],
        "livePhotoIds": ["xxxxx"],
        "poaIds":       ["xxxxx"],
      }
  */
}

void onCancelled(ComplyCubeCancelled event) {
  // Handle cancellations (event.code, event.reason)
}

void onError(ComplyCubeError error) {
  // Handle errors (error.code, error.message, error.details)
}

// 1. Subscribe to events once (e.g. in initState).
ComplyCube.events.listen((event) {
  if (event is ComplyCubeSuccess)   onSuccess(event.payload);
  else if (event is ComplyCubeCancelled) onCancelled(event);
  else if (event is ComplyCubeError)     onError(event);
});

// 2. Launch the flow.
ComplyCube.start(settings);
```

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using the `onCustomEvent` property when initializing the Flutter widget:

```dart
void onCustomEvent(ComplyCubeCustomEvent event) {
  switch (event.name) {
    case 'BIOMETRICS_STAGE_SELFIE_CAMERA':
      print("The client reached capture camera for a selfie");
      break;
  }
}

ComplyCubeWidget(
  settings: settings,
  onCustomEvent: onCustomEvent,
  // ...
);
```

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

```dart
String onTokenExpiry(String token) {
  // Insert custom token renewal code here
  return "<NEW_CLIENT_TOKEN>";
}

ComplyCubeWidget(
  settings: settings,
  onTokenExpiry: onTokenExpiry,
  // ...
);
```


# Check-Driven Integration

Build check-driven KYC and identity verification flows in Flutter apps.

## Overview

This guide walks you through integrating the **Flutter SDK** with ComplyCube using the check-driven approach, giving you direct control over individual verification steps.

<figure><img src="/files/33oRgJdikwkaH0eGh51V" alt=""><figcaption><p>Mobile SDK View</p></figcaption></figure>

{% hint style="warning" %}
You’re viewing the **check-driven** SDK guide - an approach that provides detailed control but is best suited for **partners** or **advanced use cases.**  We recommend using **workflow integration** for most implementations.
{% endhint %}

## Integration flow

The Mobile SDK runs on your mobile application, but relies on your backend to create **secure tokens**. Here’s how it works:

{% stepper %}
{% step %}

#### **Create a client**

Register a new **client** (i.e. customer) using the ComplyCube API.
{% endstep %}

{% step %}

#### **Generate an SDK token**

Your backend requests a **JWT token** tied to that client.
{% endstep %}

{% step %}

#### Initialize the SDK in your mobile app

Pass the token and settings to the SDK initializer.
{% endstep %}

{% step %}

#### Capture documents, videos, and selfies

The SDK guides your customer through the required steps.
{% endstep %}

{% step %}

#### Perform checks

Captured data is securely sent to ComplyCube for verification checks, and results are delivered in real time through the API or webhooks.
{% endstep %}
{% endstepper %}

<figure><img src="/files/zw3kOMTk0aUWjhA2t9I0" alt=""><figcaption><p>Mobile SDK Integration flow</p></figcaption></figure>

## Integration guide

Explore the source code and sample projects on our repository: [![GitHub](https://img.shields.io/badge/View%20on-GitHub-black?logo=github)](https://github.com/complycube/complycube-flutter-sdk).<br>

{% stepper %}
{% step %}

#### Install the SDK

{% tabs %}
{% tab title="Flutter" %}

1. Install the **ComplyCube Flutter** package by running:

   ```bash
   flutter pub add complycube
   ```
2. **iOS**
   1. Complete the **steps 1 and 2** in the **iOS** tabs.
   2. Add the snippet below to your `ios/PodFile` and run the `pod install` command.<br>

      ````ruby
      source 'https://github.com/CocoaPods/Specs.git'

      platform :iOS, '13.0'

      target 'Runner' do
        use_frameworks!
        use_modular_headers!
          ...
          ...
      end
      ...
      post_install do |installer|
       installer.pods_project.targets.each do |target|
         flutter_additional_ios_build_settings(target)
         target.build_configurations.each do |config|
           config.build_settings['ENABLE_BITCODE'] = 'NO'
           config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
           config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
           config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
         end
       end
      end```
      ````
   3. Complete **Application permissions steps** in the **iOS** tabs.<br>
3. **Android**
   1. Complete the steps in the **Android** tab.

{% hint style="danger" %}

#### iOS deployment targeting

If you’re targeting a specific iOS version above 13.0 for any of your dependencies, and you face the following error:<br>

{% code overflow="wrap" %}

```
Compiling for iOS 13.0, but module 'CocoaLumberjack' has a minimum deployment target of iOS 15.0
```

{% endcode %}

\
You can use the snippet below in your PodFile `post_install` script.

```ruby
post_install do |installer|
  ios_13_pods = [
    'Sentry',
    'Analytics',
    'Alamofire',
    'SwiftyJSON',
    'JWTDecode',
    'GooglePlaces',
    'lottie-ios'
  ]
  
  installer.pods_project.targets.each do |target|
      ....
      
      # Set deployment target based on pod name
      if ios_13_pods.any? { |pod_name| target.name.start_with?(pod_name) }
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
        puts "Setting #{target.name} to iOS 13.0"
      else
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
      end
      
      ....
```

{% endhint %}
{% endtab %}

{% tab title="iOS" %}

1. Before using the ComplyCube SDK, install the **CocoaPods** plugin by running the following command in your terminal:<br>

   ```bash
   sudo gem install cocoapods
   ```

2. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
   source 'https://github.com/CocoaPods/Specs.git'
   …
   platform :iOS, ’13.0’

   target ‘YourApp’ do
       …
     pod 'ComplyCubeMobileSDK'
   end

   post_install do |installer|
       installer.pods_project.targets.each do |target|
           target.build_configurations.each do |build_configuration|
               build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
               build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
               build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.1'
               build_configuration.build_settings['ARCHS'] = ['$(ARCHS_STANDARD)', 'x86_64']
               build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = ['arm64', 'arm64e', 'armv7', 'armv7s']
               build_configuration.build_settings['GENERATE_INFOPLIST_FILE'] = 'YES'
           end
       end
   end
   ```

\
**Application permissions**

Our SDK uses the device camera and microphone for capture. You must add the following keys to your application `Info.plist` file.

1. `NSCameraUsageDescription`

```xml
<key>NSCameraUsageDescription</key>
<string>Used to capture facials biometrics and documents</string>
```

2. `NSMicrophoneUsageDescription`

```xml
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture video biometrics</string>
```

{% endtab %}

{% tab title="Android" %}
Our SDK requires the repositories below.

```java
repositories {
  mavenCentral()
}

dependencies {
    implementation "com.complycube:complycube-sdk:+"
}
```

{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}

#### **Create a client**

Every verification flow starts with a **client** (i.e. customer). Use the API to [create the client](/documentation/api-reference/core-resources/clients/create-a-client).

This must be done on your **mobile app backend** server, not the mobile app itself.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
          "type": "person",
          "email": "john.doe@example.com",
          "personDetails":{
               "firstName": "John",
               "lastName" :"Doe"
          }
        }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const client = await complycube.client.create({
  type: "person",
  email: "john.doe@example.com",
  personDetails: {
    firstName: "John",
    lastName: "Doe"
  }
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

new_client = {
    'type':'person',
    'email':'john.doe@example.com',
    'personDetails': {
        'firstName':'John',
        'lastName':'Doe'
    }
}

client = cc_api.clients.create(**new_client)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->clients()->create([
    'type' => 'person',
    'email' => 'john@doe.com',
    'personDetails' => [
        'firstName' => 'John',
        'lastName' => 'Doe'
    ]
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));
var newClient = new ClientRequest {
  type = "person",
  email = "john@doe.com",
  personDetails = new PersonDetails {
    firstName = "John",
    lastName = "Doe"
  }
}

var client = await clientApi.CreateAsync(newClient);
```

{% endtab %}
{% endtabs %}

**Example response**

The response will contain an `id` (the Client ID). It is required for the next step.

```json
{
    "id": "5eb04fcd0f3e360008035eb1",
    "type": "person",
    "email": "john.doe@example.com",
    "personDetails": {
        "firstName": "John",
        "lastName": "Doe"
    },
    "createdAt": "2020-01-04T17:24:29.146Z",
    "updatedAt": "2020-01-04T17:24:29.146Z"
}
```

{% hint style="info" %}
See [Clients API Reference](/documentation/api-reference/core-resources/clients) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Generate an SDK token

Your backend must create an **SDK token** for each new flow. This token enables customers to send personal data securely from your mobile app to ComplyCube.

Tokens are short-lived and must not be reused.

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/tokens \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
           "clientId":"CLIENT_ID",
           "appId": "com.complycube.SampleApp"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");
​
const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });
​
const token = await complycube.token.generate("CLIENT_ID", {
    appId: "com.complycube.SampleApp"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient
​
cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
​
token = cc_api.tokens.create('CLIENT_ID', appId='com.complycube.SampleApp')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$token = $ccapi->tokens()->generate('CLIENT_ID', 'com.complycube.SampleApp');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.SDKTokens;

var sdkTokenApi = new SDKTokenApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var sdkTokenRequest = {
  clientId = "CLIENT_ID",
  appId = "com.complycube.SampleApp"
}

var sdkToken = await sdkTokenApi.GenerateToken(sdkTokenRequest);
```

{% endtab %}
{% endtabs %}

**Example response**

```json
{
    "token": "<CLIENT_TOKEN>"
}
```

{% hint style="info" %}
See [SDK Token API Reference](/documentation/api-reference/other-resources/tokens) to learn more.
{% endhint %}
{% endstep %}

{% step %}

#### Prepare the stages

Set up the stages you wish to include in your flow.

```dart
final stages = [
  {
    "name": 'intro',
    "heading": 'Green Bank ID verification',
  },
  {
    "name": 'documentCapture',
    "showGuidance": false,
    "useMLAssistance": true,
    "retryLimit": 1,
    "documentTypes": {
      "passport": true,
      "driving_license": ['GB', 'FR'],
    },
  },
  'faceCapture',
];
```

{% endstep %}

{% step %}

#### Initialize the SDK

You can now initialize a flow. The sequence of stages you specify determines the order in which your client sees those stages.

```dart
import 'package:complycube_flutter/ComplyCubeMobileSDK.dart';
// ...

final settings = {
  "clientID": "<CLIENT_ID>",
  "clientToken": "<CLIENT_TOKEN>",
  "stages": stages,
  // ...
}


return MaterialApp(
  home: Scaffold(
    appBar: AppBar(
      title: const Text('ComplyCube Integration'),
    ),
    body: Center(
      child: ElevatedButton(
        onPressed: () => ComplyCube.start(settings),
        child: const Text('Start verification'),
      ),
    ),
  ),
);
```

{% endstep %}

{% step %}

#### Perform checks

Using the results returned in the `onSuccess` callback, you can trigger your **mobile backend** to run the necessary checks on your client.

For example, use the result of a selfie and document capture as follows:

* `result.documentId` to run a [Document Check](https://docs.complycube.com/api-reference/check-types/document-check).
* `result.documentId` and `result.livePhotoId` to run an [Identity Check](https://docs.complycube.com/api-reference/check-types/identity-check).

**Example request for a Document Check**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X POST https://api.complycube.com/v1/checks \
     -H 'Authorization: <YOUR_API_KEY>' \
     -H 'Content-Type: application/json' \
     -d '{
            "clientId":"CLIENT_ID",
            "type": "document_check",
            "documentId":"DOCUMENT_ID"
         }'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.create("CLIENT_ID", {
    type: "document_check",
    documentId: "DOCUMENT_ID"
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.create(
    "CLIENT_ID", 
    "document_check", 
    documentId="DOCUMENT_ID"
)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$result = $ccapi->checks()->create('CLIENT_ID', [
    'type' => 'document_check',
    'documentId' => 'DOCUMENT_ID'
]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var checkRequest = new CheckRequest {
  clientId = "CLIENT_ID",
  type = "document_check",
  documentId = "DOCUMENT_ID"
};

var check = await checkApi.CreateAsync(checkRequest);
```

{% endtab %}
{% endtabs %}

If you have set up webhooks as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).
{% endstep %}

{% step %}

#### Retrieve verification results

Your mobile backend can retrieve all check results using our API.

All our checks are **asynchronous.** If you have [set up webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks/create-a-webhook) as described in our [webhooks guide](https://docs.complycube.com/documentation/guides/webhooks), you will be notified once a check completes.

To retrieve the check results, you can perform a get [check request](https://docs.complycube.com/api-reference/checks/get-a-check).

**Example request**

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/checks/{:checkId} \
     -H 'Authorization: <YOUR_API_KEY>' 
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const check = await complycube.check.get("CHECK_ID");
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

check = cc_api.checks.get('CHECK_ID')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

$check = $ccapi->checks()->get('CHECK_ID');
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Checks;

var checkApi = new CheckApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var check = await checkApi.GetAsync("CHECK_ID");
```

{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## Stages

Each stage in the flow can be customized to create the ideal journey for your customers.

The snippet below demonstrates how to set up a customized flow using the ComplyCube Mobile SDK.

```dart
final stages = [
  {
    name: 'intro',
    // ... other settings
  },
  {
    name: "consent",
    // ... other settings
  },
  {
    name: 'documentCapture',
    // ... other settings
  },
  {
    name: "faceCapture",
    // ... other settings
  },
  {
    name: "poaCapture",
    // ... other settings
  },
  {
    name: "complete",
    // ... other settings
  }
];

final settings = {
  "clientID": "<CLIENT_ID>",
  "clientToken": "<CLIENT_TOKEN>",
  "stages": stages,
  "language": "en",
  "lookAndFeel": {/*...*/}
}

return MaterialApp(
  home: Scaffold(
    appBar: AppBar(
      title: Text('ComplyCube Integration'),
    ),
    body: ComplyCubeWidget(settings: settings),
  ),
);
```

### **Welcome**

The Welcome screen is always shown first in the verification flow. It displays a welcome message along with a summary of the configured stages the user will complete.

You can customize the screen title to align with your app’s tone and branding.

```dart
final settings = {
  // ... other settings
  "stages": [
    {
      "name": "intro",
      "heading": "Custom Screen Title",
      "message": "Custom welcome message.",
    },
    // ... other stages
  ],
};
```

### **Consent**

This stage is used to collect explicit user consent before proceeding with the verification flow. It helps you meet regulatory and compliance requirements where applicable.

You can customize the screen title and message to match your legal or branding needs.

```dart
final settings = {
  // ... other settings
  "stages": [
    {
      "name": "consent",
      "heading": "Custom Consent Screen Title"
    },
    // ... other stages
  ],
};
```

### **Selfie photo and video**

You can request either a selfie photo  (i.e. a [Live Photo](/documentation/api-reference/core-resources/live-photos)) or a selfie video (i.e. a [Live Video](/documentation/api-reference/core-resources/live-videos)) from the customer as part of the biometric verification process.

* **Photo**: Captures a still image and performs a passive liveness check before allowing submission.
* **Video**: Records a short video where the user completes an on-screen challenge (e.g. head movement or spoken phrase).

{% hint style="warning" %}
If you attempt to add both types of stages, the SDK will throw a **`ComplyCubeErrorCode.BiometricStageCount`** error stating multiple conflicting stages.
{% endhint %}

```dart
final settings = {
  // ... other settings
  "stages": [
    {
      "name": "faceCapture",
      "mode": "photo",
      // Enable ML assistance during capture
      "useMLAssistance": false,
    },
    // ... other stages
  ],
};
```

```dart
final settings = {
  // ... other settings
  "stages": [
    {
      "name": "faceCapture",
      "mode": "video",
      // Enable ML assistance during capture
      "useMLAssistance": false,
    },
    // ... other stages
  ],
};
```

### **Document**

The Document stage allows users to select and capture an identity document for verification (e.g. passport, ID card, residence permit). You can customize these screens to:

* Limit the scope of document types the client can select, e.g., Passport only.
* Set the document issuing countries they are allowed for each document type.
* Add or remove automated capture using smart assistance.
* Show or hide the instruction screens before capture.
* Set a retry limit to allow clients to progress the journey regardless of capture quality.

{% hint style="info" %}
If you provide only one document type, the document type selection screen will be skipped. The country selection screen will be skipped if you provide only a single country for a given document type.
{% endhint %}

You can control whether instructional screens are shown before each camera capture by enabling or disabling guidance mode. Only disable guidance if your users are already clearly informed about the capture steps, as these screens help reduce user error and improve capture quality.

{% hint style="info" %}
Please note the `retryLimit` you set here will take precedence over the retry limit that has been set globally in your [automation settings](https://portal.complycube.com/automations).
{% endhint %}

```dart
final settings = {
  // ... other settings
  "stages": [
    {
      "name": "documentCapture",

      // Enable or disable additional guidance for the user
      "showGuidance": false,

      // Enable ML assistance during capture
      "useMLAssistance": true,

      // Set a maximum for quality check attempts before uploading
      "retryLimit": 1,

      // Enable or disable the ability to upload an image from file
      "liveCapture": false,

      // Set document types and limit the enabled countries
      "documentTypes": {
        "passport": true,
        "driving_license": ['GB', 'US'],
      },
    },
    // ... other stages
  ],
};
```

### NFC capture

The ComplyCube mobile SDK supports NFC-based **RFID chip** reading for identity documents equipped with embedded chips. This allows for secure data extraction and high-assurance document authentication.

{% hint style="info" %}
Please get in touch with your **Account Manager** or [support](https://support.complycube.com/hc/en-gb/requests/new) to get access to our NFC-enabled Mobile SDK.
{% endhint %}

#### Pre-requisites

{% tabs %}
{% tab title="iOS" %}
{% hint style="info" %}
To use this feature, your app must have the **`Near Field Communication Tag Reading`** capability enabled. To add this capability to your app, refer to [Apple's guide here](https://help.apple.com/xcode/mac/current/#/dev88ff319e7).
{% endhint %}

1. Install the **CocoaPods Artifactory** plugin by running the following command in your terminal:<br>

   ```bash
   gem install cocoapods-art
   ```

2. To add the library, copy your repository credentials into a `.netrc` file to your home directory and setup the repository:<br>

   <pre class="language-bash" data-overflow="wrap"><code class="lang-bash">pod repo-art add cc-cocoapods-release-local "https://complycuberepo.jfrog.io/artifactory/api/pods/cc-cocoapods-release-local"
   </code></pre>

   \
   Remember to fetch your credentials from **JFrog** using the **Set Me Up** button [here](https://complycuberepo.jfrog.io/ui/repos/tree/General/cc-cocoapods-release-local).<br>

3. Add plugin repos and install the pod using your `Podfile`:<br>

   ```ruby
    plugin 'cocoapods-art', :sources => [
      'cc-cocoapods-release-local',
      'trunk'
    ]
    ...
    platform :ios, '13.0' # Or above

    target 'YourApp' do
      use_frameworks!
      use_modular_headers!
      ...
      pod 'ComplyCubeMobileSDK', '2.0.x-nfc'
      ...
    en
   ```

4. You must add the following keys to your application `Info.plist` file:<br>

   ```xml
   <key>NFCReaderUsageDescription</key>
   <string>Required to read from NFC enabled documents</string>
   ```

5. To read NFC tags correctly, you need to add the following entries to your app target's `Info.plist` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
   <array>
     <string>12FC</string>
   </array>
   <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
   <array>
     <string>A0000002471001</string>
     <string>A0000002472001</string>
     <string>00000000000000</string>
     <string>D2760000850101</string>
     <string>E80704007F00070302</string>
     <string>A000000167455349474E</string>
     <string>A00000045645444C2D3031</string>
   </array>
   ```

6. Add the following in your `Runner.entitlements` file:<br>

   ```xml
   <key>com.apple.developer.nfc.readersession.formats</key>
   <array><string>TAG</string></array>
   ```

7. To enable NFC when building your iOS app, pass the `USE_CCNFC` environment variable during the build:<br>

   ```bash
   USE_CCNFC=true flutter build ios
   ```

   \
   To keep this enabled for all iOS builds, add the following line near the top of your `ios/Podfile`:<br>

   ```ruby
   ENV['USE_CCNFC'] ||= 'true'
   ```

{% endtab %}

{% tab title="Android" %}

1. Start by adding your access credentials for the ComplyCube NFC-Enabled SDK repository to the `gradle.properties` file of your **mobile app**:

```gradle
USE_NFC=true
artifactory_contextUrl=https://complycuberepo.jfrog.io/artifactory/cc-gradle-release
artifactory_user=<YOUR_USERNAME>
artifactory_password=<YOUR_PASSWORD>
```

> Replace <**YOUR\_USERNAME**> and <**YOUR\_PASSWORD**> with your ComplyCube Artifactory credentials. If you don’t have access, contact ComplyCube Support to request credentials.

2. Then, update your project level `build.gradle` or `build.gradle.kts` file with the ComplyCube SDK repository Maven settings:

{% tabs %}
{% tab title="Groovy" %}

```javascript
repositories {
    google()
    mavenCentral()
    maven {
        url project.findProperty("artifactory_contextUrl")
        credentials {
            username = project.findProperty("artifactory_user")
            password = project.findProperty("artifactory_password")
        }
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```python
repositories {
    google()
    mavenCentral()
    maven {
        url = uri(project.findProperty("artifactory_contextUrl") as String)
        credentials {
            username = project.findProperty("artifactory_user") as String?
            password = project.findProperty("artifactory_password") as String?
        }
    }
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

#### Enabling NFC capture

```dart
final settings = {
    // ... other settings
    "stages" : [
      {
        "name": "documentCapture",
        // Add this property to enable NFC
        "nfcEnabled": true
        ...
      },
      // ... other stages
    ]
}
```

### **Address capture**

This stage allows users to manually enter their residential address. You can customize it to:

* Restrict input to specific countries
* Enable or disable the address autocomplete feature for faster and more accurate entry

```dart
final settings = {
  // ... other settings
  stages: [
    {
      "name": "addressCapture",

      // This enables our address autocomplete feature
      "useAutoComplete": false,
      
      // A list of acceptable countries for address capture
      "allowedCountries": ['GB','US']
    },
    // ... other stages
  ],
};
```

### **Proof of address**

This stage allows customers to submit a document verifying their residential address. You can configure which document types are accepted, such as utility bills or bank statements, and choose whether customers can upload a file or must capture the document live using their device camera.

{% hint style="info" %}
By default, this stage includes the **address capture stage** with autocomplete enabled to assist users during entry. Autocomplete can be disabled if not required.
{% endhint %}

```dart
final settings = {
  // ... other settings
  stages: [
    {
      "name": "poaCapture",

      // When disabled, the client will be forced to perform a live capture
      "liveCapture": false,
    },
    // ... other stages
  ],
};
```

### **Completion**

You can include a completion stage at the end of the flow to confirm that the process has been successfully finished. This screen provides a clear end point for the user and can be customized to display a confirmation message or next steps.

```dart
final settings = {
  // ... other settings
  "stages": [
    {
      "name": "complete",
      "heading": "Thank you!",
      "message": "Your KYC submission has been completed.",
    },
    // ... other stages
  ],
};
```

## Branding

The SDK allows you to customize the UI to match your application’s visual identity. You can define primary and accent colors during configuration to align the verification flow with your brand guidelines. Learn more about our **appearance properties** (see below).

```dart
final settings = {
  // ...
  "lookAndFeel": {
    // Primary action button background color
    "primaryButtonBgColor": '#FFFFFF',
    
    // Force SDK to 'dark', 'light', or 'inherit' mode
    "uiInterfaceStyle": "dark"
  }
}
```

To disable the header display in the ComplyCube SDK Widget on **Android**, please insert the following line into `styles.xml`:

```xml
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
  ...
  <item name="windowActionBar">false</item>
  <item name="windowNoTitle">true</item>
  ...
</style>
...
```

<details>

<summary>Appearance properties</summary>

<table><thead><tr><th width="371.70703125">Appearance Property</th><th>Description</th></tr></thead><tbody><tr><td><code>primaryButtonBgColor</code></td><td>Primary action button background color.</td></tr><tr><td><code>primaryButtonTextColor</code></td><td>Primary action button text color.</td></tr><tr><td><code>primaryButtonBorderColor</code></td><td>Primary action button border color.</td></tr><tr><td><code>secondaryButtonBgColor</code></td><td>Secondary button background color.</td></tr><tr><td><code>secondaryButtonPressedBgColor</code></td><td>Secondary action button pressed background color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>secondaryButtonTextColor</code></td><td>Secondary action button text color.</td></tr><tr><td><code>secondaryButtonBorderColor</code></td><td>Secondary action button border color.</td></tr><tr><td><code>documentTypeSelectorBgColor</code></td><td>Document type selection button color.</td></tr><tr><td><code>documentTypeSelectorBorderColor</code></td><td>Document type selection button border color.</td></tr><tr><td><code>documentTypeSelectorTitleTextColor</code></td><td>Document type selection title text color.</td></tr><tr><td><code>documentTypeSelectorDescriptionTextColor</code></td><td>Document type selection description text color.</td></tr><tr><td><code>documentTypeSelectorIconColor</code></td><td>Document type selection icon color.</td></tr><tr><td><code>bodyTextColor</code></td><td>Screen body text color.</td></tr><tr><td><code>linkButtonTextColor</code></td><td>Links color.<br><br><em>Not supported by Android.</em></td></tr><tr><td><code>headingTextColor</code></td><td>Title heading text color.</td></tr><tr><td><code>subheadingTextColor</code></td><td>Subheading text color.</td></tr><tr><td><code>infoPanelTitleColor</code></td><td>Information panel title color.</td></tr><tr><td><code>infoPanelDescriptionTextColor</code></td><td>Information panel description text color.</td></tr><tr><td><code>infoPanelBgColor</code></td><td>Information panel background color.</td></tr><tr><td><code>infoPanelIconColor</code></td><td>Information panel icon color.</td></tr><tr><td><code>errorPanelTitleColor</code></td><td>Error panel title color.</td></tr><tr><td><code>errorPanelDescriptionTextColor</code></td><td>Error panel description text color.</td></tr><tr><td><code>errorPanelBgColor</code></td><td>Error panel background color.</td></tr><tr><td><code>errorPanelIconColor</code></td><td>Error panel icon color.</td></tr><tr><td><code>cameraButtonBgColor</code></td><td>Camera capture button background color.</td></tr><tr><td><code>uiInterfaceStyle</code></td><td>Set the SDK to use dark mode, light mode, or system Inherited.</td></tr></tbody></table>

</details>

## Localization

The SDK supports several languages, including those listed below.

{% columns %}
{% column %}

* Arabic - `ar` 🇦🇪
* Chinese (Simplified) - `zh` 🇨🇳
* Chinese (Traditional) - `hk` 🇨🇳
* Dutch - `nl` 🇳🇱
* English - `en` 🇺🇸
* French - `fr` 🇫🇷
* German - `de` 🇩🇪
* Hindi - `hi` 🇮🇳
* Indonesian -  `id` 🇮🇩
* Italian - `it` 🇮🇹
  {% endcolumn %}

{% column %}

* Japanese -  `ja` 🇯🇵
* Korean -  `ko` 🇰🇷
* Norwegian - `no` 🇳🇴
* Polish - `po` 🇵🇱
* Portuguese - `pt` 🇵🇹
* Spanish - `es` 🇪🇸
* Swedish - `sv` 🇸🇪
* Thai -  `th` 🇹🇭
* Vietnamese -  `vi` 🇻🇳
* and more...
  {% endcolumn %}
  {% endcolumns %}

## Result handling

To run verification checks, you must implement the **success**, **cancelled**, and **error** callbacks.

On a successful completion (`onSuccess`), you can trigger [check requests](/documentation/api-reference/core-resources/checks/create-a-check) from your backend using the resource IDs returned in the result object. These IDs correspond to the uploaded assets (e.g. documents, selfies) and can be used to initiate verification checks via the ComplyCube API.

If the user exits the flow before completion, the `onCancelled` callback is invoked with a descriptive reason indicating why the session was cancelled (e.g. user exit, timeout, permission denied)

{% hint style="info" %}
In some cases, the customer may cancel the flow after completing one or more capture stages. If this occurs, any data captured prior to cancellation, such as documents or biometric media, may have already been uploaded to their client record.
{% endhint %}

If the SDK encounters an issue, the `onError` callback is triggered with a `ComplyCubeError` object containing the error type and message. Refer to the **error codes** (see below), for a full list of possible error cases.

```dart
void onSuccess(dynamic payload) {
  /*
    Handling successful results.
    The default flow (Identity Document + Live Photo + Proof of Address)
    delivers a payload shaped like:
      {
        "documentIds":  ["xxxxx"],
        "livePhotoIds": ["xxxxx"],
        "poaIds":       ["xxxxx"],
      }
  */
}

void onCancelled(ComplyCubeCancelled event) {
  // Handle cancellations (event.code, event.reason)
}

void onError(ComplyCubeError error) {
  // Handle errors (error.code, error.message, error.details)
}

// 1. Subscribe to events once (e.g. in initState).
ComplyCube.events.listen((event) {
  if (event is ComplyCubeSuccess)   onSuccess(event.payload);
  else if (event is ComplyCubeCancelled) onCancelled(event);
  else if (event is ComplyCubeError)     onError(event);
});

// 2. Launch the flow.
ComplyCube.start(settings);
```

<details>

<summary>Error codes</summary>

<table data-full-width="false"><thead><tr><th width="312.48828125">Error Type</th><th>Description</th></tr></thead><tbody><tr><td><code>BiometricStageCount</code></td><td>The configuration includes duplicate <strong>selfie photo</strong> or <strong>selfie video</strong> stages.</td></tr><tr><td><code>Cancelled</code></td><td>The client cancelled the flow and exited the SDK (triggered the <code>onCancelled</code> callback).</td></tr><tr><td><code>Connectivity</code></td><td>A network error has occurred.</td></tr><tr><td><code>DocumentMandatory</code></td><td>A <strong>document stage</strong> is required based on the configured stages but has not been included.</td></tr><tr><td><code>ExpiredToken</code></td><td>The SDK token has expired. Generate a new token and restart the flow.</td></tr><tr><td><code>FlowError</code></td><td>An unrecoverable error occurred during the flow.</td></tr><tr><td><code>InvalidCountryCode</code></td><td>An invalid country code was provided.</td></tr><tr><td><code>JailBroken</code></td><td>The SDK cannot run on this device because it has been jailbroken or compromised.</td></tr><tr><td><code>NoDiskAccess</code></td><td>The client denied disk access permissions required by the SDK.</td></tr><tr><td><code>NoDocumentTypes</code></td><td>A <strong>document stage</strong> was initialized without specifying any document types.</td></tr><tr><td><code>NoResult</code></td><td>No result was returned to the callback. If this persists, please contact support.</td></tr><tr><td><code>NoUserConsent</code></td><td>The client has not provided consent to proceed with the SDK flow.</td></tr><tr><td><code>NotAuthorized</code></td><td>The SDK attempted to access an endpoint it is not authorized to use.</td></tr><tr><td><code>Unknown</code></td><td>An unexpected error occurred. If this happens repeatedly, contact support.</td></tr><tr><td><code>UnsupportedCountryTypeCombination</code></td><td>The selected country and document type combination is not supported.</td></tr><tr><td><code>UnsupportedDocumentType</code></td><td>The provided document type is not supported.</td></tr><tr><td><code>UploadError</code></td><td>An error occurred while uploading a document or selfie.</td></tr><tr><td><code>UploadRequireGuidance</code></td><td>If <code>useLiveCaptureOnly</code> is set to <code>false</code>, guidance must be enabled by setting <code>isGuidanceEnabled</code> to <code>true</code>.</td></tr></tbody></table>

</details>

## Events tracking

The SDK tracks a range of **events** throughout the verification flow, covering all key user interactions across stages. See below for the list of events.

If you need to implement custom analytics, you can hook into these events and trigger your own tracking logic accordingly.

To incorporate your own tracking, define a function and apply it using the `onCustomEvent` property when initializing the Flutter widget:

```dart
void onCustomEvent(ComplyCubeCustomEvent event){
  switch(event.name){
    case 'BIOMETRICS_STAGE_SELFIE_CAMERA':
      print("The client reached capture camera for a selfie")
      break;
  }
}

ComplyCubeWidget(
  settings: settings,
  onCustomEvent: onCustomEvent,
  // ...
),
```

<details>

<summary>Events</summary>

| Event                                                                                                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>INTRO</code><br><br>The client reached the intro screen.</p>                                                                                                                                    |
| <p><code>CONSENT\_STAGE</code><br><br>The client reached the consent screen.</p>                                                                                                                         |
| <p><code>CONSENT\_STAGE\_WARNING</code><br><br>The client attempted to exit without giving consent.</p>                                                                                                  |
| <p><code>CAMERA\_ACCESS\_PERMISSION</code><br><br>The client reached the camera permission request screen.</p>                                                                                           |
| <p><code>DOCUMENT\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the document capture guidance screen.</p>                                                                                   |
| <p><code>DOCUMENT\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client has reached the document type selection screen for a document capture.</p>                                                             |
| <p><code>DOCUMENT\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a document capture.</p>                                                                      |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided ID document.</p>                                                                   |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen of a one-sided ID document.</p>                                              |
| <p><code>DOCUMENT\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client reached the quality preview screen for a one-sided ID document.</p>                                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the camera capture screen for the front side of a two-sided ID document.</p>                                         |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the front side of a two-sided ID document.</p>                    |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br><br>The client reached the quality preview screen for the front side of a two-sided ID document.</p>                                |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the camera capture screen for the back side of a two-sided ID document.</p>                                           |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br><br>The client reached the manual camera capture screen for the back side of a two-sided ID document.</p>                      |
| <p><code>DOCUMENT\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br><br>The client reached the quality preview screen for the back side of a two-sided ID document.</p>                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the selfie capture guidance screen.</p>                                                                           |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA</code><br><br>The client reached the selfie photo capture camera screen.</p>                                                                                  |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual selfie photo capture camera screen.</p>                                                             |
| <p><code>BIOMETRICS\_STAGE\_SELFIE\_CHECK\_QUALITY</code><br><br>The client reached the selfie capture photo review screen.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA</code><br><br>The client reached the video selfie camera screen.</p>                                                                                           |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CAMERA\_MANUAL\_MODE</code><br><br>The client reached the manual capture camera screen for a video selfie.</p>                                                        |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_ONE</code><br><br>The client reached the first action in a video selfie capture.</p>                                                                          |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_ACTION\_TWO</code><br><br>The client reached the second action in a video selfie capture.</p>                                                                         |
| <p><code>BIOMETRICS\_STAGE\_VIDEO\_CHECK\_QUALITY</code><br><br>The client reached the manual selfie video capture camera screen.</p>                                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_CAPTURE\_GUIDANCE</code><br><br>The client reached the proof of address capture guidance screen.</p>                                                                 |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_DOCUMENT\_TYPE</code><br><br>The client reached the document type selection screen for a proof of address capture.</p>                                               |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_SELECT\_COUNTRY</code><br><br>The client reached the country selection screen for a proof of address capture.</p>                                                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA</code><br><br>The client reached the capture camera stage for a one-sided proof of address document.</p>                                           |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CAMERA\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for a one-sided proof of address document.</p>                          |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_ONE\_SIDE\_CHECK\_QUALITY</code><br><br>The client has reached the quality preview screen for a one-sided proof of address document.</p>                             |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT</code><br><br>The client reached the capture camera stage for the front side of a two-sided proof of address document.</p>                  |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_FRONT\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the front side of a two-sided proof of address document.</p> |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_FRONT</code><br>The client reached the quality preview screen for the front side of a two-sided proof of address document.</p>            |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK</code><br><br>The client reached the capture camera stage for the back side of a two-sided proof of address document.</p>                    |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CAMERA\_BACK\_MANUAL\_MODE</code><br>The client reached the manual capture camera stage for the back side of a two-sided proof of address document.</p>   |
| <p><code>PROOF\_OF\_ADDRESS\_STAGE\_TWO\_SIDE\_CHECK\_QUALITY\_BACK</code><br>The client reached the quality preview screen for the back side of a two-sided proof of address document.</p>              |
| <p><code>COMPLETION\_STAGE</code><br><br>The client has reached the completion screen.</p>                                                                                                               |

</details>

## Token expiry handling

To handle token expiration gracefully, you can provide a callback function that generates a new SDK token when needed. This allows the flow to continue seamlessly without requiring the user to restart the session manually.

```dart
String onTokenExpiry(String token){
  // Insert custom token renewal code here
}

ComplyCubeWidget(
  settings: settings,
  onTokenExpiry: onTokenExpiry,
  // ...
),
```


# Zapier

Automate KYC, AML, and identity verification workflows with the ComplyCube Zapier integration.

## Overview

The [ComplyCube Zapier integration](https://zapier.com/apps/complycube/integrations) is a **no-code automation solution** that connects our identity verification platform with **thousands of applications**. You can automate onboarding and compliance workflows by using Zapier’s **triggers**, **actions**, **filters**, and **routing** tools.

With Zapier, you can connect ComplyCube to **CRMs**, **support tools**, **marketing platforms**, and **internal systems** to streamline onboarding, compliance case management, and reporting without writing code.

The ComplyCube Zapier integration lets you create Zaps that trigger actions in other apps whenever verification or AML events occur in real time, for example, when a check completes, a session updates, or a customer is flagged.

## Requirements

* Zapier account (free or paid).
* ComplyCube API key (Test or Live).
* Access to the apps you want to connect (e.g., Slack, WordPress, Shopify, HubSpot, Zendesk).

## Getting started

{% stepper %}
{% step %}

#### Sign in to Zapier

Start by signing up or logging in to [Zapier](https://zapier.com/).

Before creating your first connection, you may also want to review Zapier’s guides on [automation basics, triggers, and actions](https://zapier.com/resources/guides/quick-start/automation-basics).
{% endstep %}

{% step %}

#### Create a new Zap

Once logged in, select **Create Zap**.

You can also browse and use the pre-made [Zapier templates](https://zapier.com/apps/complycube/integrations#zap-template-list), such as the **HubSpot → ComplyCube → Gmail template**.
{% endstep %}

{% step %}

#### Add a Trigger and Action step

In your new Zap, choose a **Trigger event**, for example, *New Contact in HubSpot* or *New Payment in Stripe*.

Now, add an **Action step** and select **ComplyCube** from the Zapier app directory.

<figure><img src="/files/L3jgiRCM0HLsdehfoizZ" alt="" width="563"><figcaption><p>Zapier Trigger Event and ComplyCube Action</p></figcaption></figure>

ComplyCube can also be used as a **Trigger**. This lets your Zap run additional actions in other apps whenever a verification or AML event occurs or completes.
{% endstep %}

{% step %}

#### Authorize the connection to ComplyCube

After creating a ComplyCube step, open the *Setup* tab and select **Sign in** to authenticate your account.

<figure><img src="/files/SOS92e2iXKDBAVzoii1A" alt="" width="563"><figcaption><p>Zapier Authorization</p></figcaption></figure>

To complete the authorization, enter your **Live** or **Test** API key. You can view, copy, and manage your keys on the [API keys page](https://portal.complycube.com/developers/key).

{% hint style="info" %}
If you encounter authorization errors, verify your credentials or contact **ComplyCube Support**.
{% endhint %}
{% endstep %}

{% step %}

#### Complete a test

Add any additional actions as needed, then **test each step** to ensure everything works correctly.

When you’re satisfied, publish the Zap to activate it.

<figure><img src="/files/GHDpyJn9Wm2Qxa2tbT0S" alt="" width="375"><figcaption><p>Test ComplyCube Step on Zapier</p></figcaption></figure>

{% hint style="info" %}
Check the [ComplyCube API Reference](https://docs.complycube.com/documentation/api-reference/) for supported events and full breakdowns of all response fields.
{% endhint %}
{% endstep %}
{% endstepper %}

## Zapier templates

**Zapier templates** provide ready-made automation flows that connect ComplyCube with popular apps. Use them to speed up setup, reduce manual configuration, and launch your first Zaps in minutes.

Examples include:

* **CRM onboarding:** *New HubSpot contact* → *Create ComplyCube verification session* → *Email verification link via Gmail* → *Send Slack alert on completion*.
* **Age verification for e-commerce:** *New Shopify order* → *Create ComplyCube verification* → *Tag customer as "Verified" in Shopify if the check passes*.
* **Payment screening:** *Stripe payment > $10,000* → *Run ComplyCube AML check* → *Notify Finance in Teams if the result is flagged*.
* **Right-to-work checks:** *New BambooHR employee* → *Create ComplyCube Document + Liveness check* → *Update the HR system once verified*.
* **Fraud escalation:** *ComplyCube verification failed* → *Create Jira ticket* → *Send a notification to the risk or support team*.

## Next steps

Once your first Zap is running, you can further enhance and customize your automation with the following options:

* Use **Zapier Filters** to branch logic based on verification outcomes (e.g., *clear*, *attention*).
* Add **Paths** to create dynamic workflows, for example, auto-approve clear cases while routing flagged ones to a review queue.
* Leverage **Delays** to build follow-up sequences (e.g., send reminders to customers who haven’t completed their verification).
* Use **Formatter** utilities to enrich data before sending it to downstream systems (formatting dates, extracting fields, etc.).
* **Sync** verification results into your internal tools, such as CRMs, case management systems, data warehouses, or fraud platforms, to keep all systems aligned.
* Trigger **notifications** in Slack, WhatsApp, Teams, or email whenever AML matches or policy failures occur.


# Salesforce

Sync KYC, identity verification, and AML data to Salesforce with the ComplyCube integration.

## Overview

Our Salesforce integration lets you bring KYC and AML results, documents, and session status into your Salesforce org. Teams can review outcomes, trigger follow-ups, and report on compliance in one place.

It works with both workflow-driven journeys and check-driven events. It also supports real-time updates through webhooks.

## Requirements

* Salesforce Enterprise (or higher) recommended.
* Admin access to install the managed package and create connected apps.
* ComplyCube webhooks enabled for real-time updates.
* Field mappings for your Lead/Contact/Account (or custom objects).

## Availability

The detailed setup guide and managed package are currently available by invitation only. Contact your **Account Manager** to request access and onboarding support.


# Overview

Explore the ComplyCube API for KYC, AML, and identity verification, with guides for authentication, checks, errors, and integration.

[ComplyCube](https://www.complycube.com/) is a cloud-based API platform for automating Identity Verification (ID\&V), Anti-Money Laundering (AML), and Know Your Customer (KYC) compliance workflows.

Our API follows REST principles, with predictable resource-oriented URLs and standard [HTTP response codes](/documentation/api-reference/errors#http-status-codes). All responses, including [errors](/documentation/api-reference/errors), are returned in JSON.

We’ve designed our documentation to be easy to follow. It is grouped by resource type and offers practical examples.

If you’re just getting started, begin with the [user guide](https://docs.complycube.com/documentation/) for an overview of the core concepts and workflows.

{% hint style="info" %}
As a general guideline, if a property has an empty or null value, we drop it from the JSON unless there’s a strong semantic reason for its existence.
{% endhint %}


# Integration

Integrate the ComplyCube KYC API with REST, OpenAPI, client libraries, Web SDK, mobile SDKs, Postman, and hosted identity verification flows.

### REST API

All our services are available through our RESTful API, which works with any language that supports HTTP/cURL, such as **Node**, **PHP**, **Python**, **.NET**, **Java**, and much more.

You can also integrate the API through any third-party platforms that support HTTP requests, including [Zapier](/documentation/sdks/third-party-integrations/zapier), [Salesforce](/documentation/sdks/third-party-integrations/salesforce), [WordPress](/documentation/sdks/third-party-integrations/zapier#zapier-templates), and **Microsoft Power Automate**.

You may also use the [ComplyCube OpenAPI](#openapi-specification) specification to automatically generate code in almost any language, using free or paid tools such as [OpenAPI Generator.](https://openapi-generator.tech)

### Web SDK

ComplyCube officially maintains and supports a [Web SDK for Frontend JavaScript](/documentation/sdks/web-integrations/web-sdk-quick-guide), enabling you to embed identity verification and compliance workflows directly into your web applications.

### Mobile SDKs

For a mobile-native experience, ComplyCube offers SDKs for [iOS](/documentation/sdks/mobile-integrations/ios-sdk), [Android](broken://spaces/lv7UhJvTbxeq4s3KwQpn/pages/BqqriyvRf4ZuvIE4pOiJ), [React Native](broken://spaces/lv7UhJvTbxeq4s3KwQpn/pages/4kuM1C32WGruZNqoVa1o), and [Flutter](broken://spaces/lv7UhJvTbxeq4s3KwQpn/pages/XxERHhey6xLY0OzMUfK9). A [ComplyCube app](https://portal.complycube.com/developers/mobile) is also available to help you explore the SDK in action.

### Hosted solution

[ComplyCube Flow](/documentation/sdks/web-integrations/hosted-solution-quick-guide) is a secure, fully hosted, and customizable KYC and identity verification page that allows you to verify customers with minimal code. It supports branded, conversion-optimized journeys delivered via URL redirects and works across devices.

### Client libraries

ComplyCube provides officially supported client libraries for [Node.js](https://www.npmjs.com/package/@complycube/api), [PHP](https://packagist.org/packages/complycube/complycube-php), [.NET](https://www.nuget.org/packages/Complycube/), and [<mark style="color:blue;">Python</mark>](https://pypi.org/project/complycube/), enabling seamless integration of backend applications with your existing systems and infrastructure.

{% tabs %}
{% tab title="Node.js" %}

```bash
# Install using npm
npm install --save @complycube/api

# Install using Yarn
yarn add @complycube/api
```

{% endtab %}

{% tab title="Python" %}

```bash
# Install using pip
pip install complycube
```

{% endtab %}

{% tab title="PHP" %}

```bash
# Install using composer
composer require complycube/complycube-php
```

{% endtab %}

{% tab title=".NET" %}

```powershell
# Install using package manager
Install-Package Complycube

# Install using .NET CLI
dotnet add package Complycube
```

{% endtab %}
{% endtabs %}

### Postman

If you’re looking to quickly get familiar with the API or test its capabilities, we recommend using the [ComplyCube Postman collection](/documentation/integration-resources/postman).

### Model Context Protocol (MCP)

If you're building with AI tools and agents, use [ComplyCube MCP](/documentation/integration-resources/model-context-protocol-mcp) to connect to ComplyCube from MCP-compatible clients.

### OpenAPI specification

ComplyCube maintains [OpenAPI](https://swagger.io/specification/) (v3) specifications for the latest version of the API.

{% file src="/files/chnBkVpSqKwAAxkjn4bd" %}
ComplyCube OpenAPI v3 Specification
{% endfile %}


# Test and Live

ComplyCube sandbox and live environments for KYC, AML, and identity verification API testing, integration validation, and production launch.

### Environments

ComplyCube provides two environments, **Test** (Sandbox) and **Live**, each with its own set of API keys. This separation allows you to safely explore and integrate with the platform before moving to production.

Use your **test API key** to simulate requests and validate your integration without triggering real verifications or incurring charges. Once you’re ready to process real checks, switch to your **live API key**.

Both API keys can be viewed and managed from the [API keys page](https://portal.complycube.com/developers) in the Web Portal.

### Sandbox

The **ComplyCube Sandbox** is a dedicated safe test environment that simulates the behavior, responses, and errors of the **live** environment.

{% hint style="info" %}
All [checks](/documentation/api-reference/core-resources/checks) conducted on the Sandbox will return dummy responses. Please refer to our [Testing](https://docs.complycube.com/documentation/useful-resources/testing-data) page to learn about **simulating specific test scenarios** as part of your integration.
{% endhint %}

Use the Sandbox to validate key aspects of your implementation before going live, including:

* Network connectivity and authentication with the ComplyCube API.
* Proper formatting of API requests.
* Handling of successful and [error](/documentation/api-reference/errors) responses.
* Implementation and testing of [rate limits](/documentation/api-reference/rate-limits) and [service quota](/documentation/api-reference/service-quota) handling.
* Use of [pagination](/documentation/api-reference/pagination) and [filtering](/documentation/api-reference/filtering).
* Verification that [Webhooks](https://docs.complycube.com/documentation/guides/webhooks) are functioning as expected.

{% hint style="danger" %}
Do not send any confidential or operational data when using the Sandbox.
{% endhint %}

{% hint style="warning" %}
Data in our sandbox environment is periodically deleted.
{% endhint %}

### Live <a href="#go-live" id="go-live"></a>

Once your integration is tested and working as expected, you can [activate your live environment](https://portal.complycube.com/activate) through the Web Portal and begin running real verifications.


# Authentication

Authenticate ComplyCube API requests with test and live API keys, secure HTTPS headers, and backend client libraries.

The ComplyCube API uses API keys to authenticate all requests. You can view, manage, and rotate your keys from the [API keys page](https://portal.complycube.com/developers).

Sandbox environment keys have the prefix `test_` whereas Live environment keys have the prefix `live_`.

{% hint style="info" %}
All API requests must be made over HTTPS. Any requests made over HTTP will fail.
{% endhint %}

{% hint style="warning" %}
Your API keys carry many privileges, so be sure to keep them secure. Do not share your API keys in publicly accessible areas such as GitHub, client-side code, and so forth.
{% endhint %}

#### Example of an authenticated request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/clients \
     -H 'Authorization: <YOUR_API_KEY>'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

const clients = await complycube.client.list();
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');
```

{% endtab %}

{% tab title="C#" %}

```csharp
using ComplyCube.Net;

var client = new ComplyCubeClient("<YOUR_API_KEY>");
```

{% endtab %}
{% endtabs %}


# Rate Limits

Understand ComplyCube API rate limits, retry strategy, exponential backoff, and webhook-based alternatives.

ComplyCube’s API enforces the following maximum request rates:

* **Live environment**: up to **10 requests per second**.
* **Test (Sandbox) environment**: up to **5 requests per second**.

Requests that exceed these limits may be throttled or temporarily blocked.

Any request that exceeds the allowed rate will receive a `429 Too Many Requests` response.

{% hint style="info" %}
You should implement suitable error handling for `429` errors. Using an **exponential backoff** strategy with random jitter is the recommended approach to safely retry requests and avoid repeated throttling.
{% endhint %}

### Avoiding the limit

To help prevent reaching rate limits, consider the following best practices:

* Run non-essential or routine batch jobs outside of peak hours.
* Throttle or limit the frequency of batch jobs.
* Implement exponential backoff for retries, starting with a 30-second delay.
* Prioritize requests that are essential to verifying active clients.
* Use webhooks instead of polling our API for updates.


# Service Quota

ComplyCube API service quotas for KYC, AML, and identity verification checks, including monthly usage limits, covered services, and 429 quota errors.

Based on your subscription plan, there is a monthly limit on the number of verification checks you can perform. This quota applies to requests for [creating checks](/documentation/api-reference/core-resources/checks/create-a-check), [autofill](/documentation/api-reference/other-resources/autofill), [company search](/documentation/api-reference/tools/company-search), and [address search](/documentation/api-reference/tools/address-search).

Other request types are not limited, aside from general [rate limits](/documentation/api-reference/rate-limits).

You can view your monthly quota and current usage from the [plan settings](https://portal.complycube.com/settings/plan) page.

Requests that exceed the quota will return a `429 Too Many Requests` error.


# Filtering

Filter ComplyCube API list responses with query parameters, supported characters, URL encoding, and endpoint-specific filters.

You can filter results returned from the API by passing them as query parameters using a standard URI format.

```
                  host          resource
          ┌────────┴───────┐    ┌──┴──┐
  https://api.complycube.com/v1/clients?type=company&email=example%40example.com
  └─┬─┘                     └┬┘        └───────────────────┬───────────────────┘
  scheme                 API version                     query           
```

### Supported attributes

Each endpoint provides a list of filter attributes.

{% hint style="info" %}
When multiple filters are requested, they are all applied using an **AND** operator.
{% endhint %}

Passing an incorrectly formatted filter or using an unsupported operator will return a `200` response with no results.

### Supported characters

As filters are passed as URL query string parameters, we must ensure all filters are URL safe and are strict about the characters that can be used in a filter.

<table><thead><tr><th width="356.19921875">Characters</th><th>Can it be used in the filter?</th></tr></thead><tbody><tr><td><code>A-Z</code> (upper &#x26; lower case)</td><td>Yes</td></tr><tr><td><code>0-9</code></td><td>Yes</td></tr><tr><td><code>$</code> <code>-</code> <code>_</code> <code>*</code> <code>.</code></td><td>Yes</td></tr><tr><td>(space)</td><td>Yes</td></tr><tr><td><code>+</code></td><td>Only when URL encoded (<code>%2B</code>)</td></tr></tbody></table>

### URL encoding filters

Some characters cannot be part of a URL (for example, space), and some other characters have a special meaning in a URL.

We recommend [URL encoding](https://en.wikipedia.org/wiki/Percent-encoding) filters to escape special characters. For example, you can encode the full filter so that `email=john.doe@example.com`would become `email=john.doe%40example.com`.

It is also recommended that you use URL building libraries to automatically encode your URLs to ensure the URLs are properly escaped before sending them to ComplyCube.

For more detail on filtering, see the **Filtering** section under each endpoint.


# Pagination

Paginate ComplyCube API list responses with parameters, date filters, and examples for common resources.

All top-level API resources support bulk fetches via “**list**” API methods. For instance, among other resources, you can list [clients](/documentation/api-reference/core-resources/clients/list-clients) and [documents](/documentation/api-reference/core-resources/documents/list-documents).

These requests will be paginated to 100 items by default. You can specify further pages using the page query parameter.

You can use the query parameters below for all our **list** API methods:

### Pagination attributes

<table><thead><tr><th width="164.39453125">Query Parameter</th><th>Description</th></tr></thead><tbody><tr><td><code>createdAfter</code></td><td>A "greater than" filter on the list based on the resource <code>createdAt</code> field.</td></tr><tr><td><code>createdBefore</code></td><td>A "less than" filter on the list based on the resource <code>createdAt</code> field.</td></tr><tr><td><code>updatedAfter</code></td><td>A "greater than" filter on the list based on the resource <code>updatedAt</code> field.</td></tr><tr><td><code>updatedBefore</code></td><td>A "less than" filter on the list based on the resource <code>updatedAt</code> field.</td></tr><tr><td><code>pageSize</code></td><td>Indicates how many records each page should contain. The value must be between 1 and 1000. The default is 100.</td></tr><tr><td><code>page</code></td><td>Specifies the page number to retrieve. The value must be equal to or greater than 1.</td></tr></tbody></table>

### Example request

{% tabs %}
{% tab title="cURL" %}

```bash
curl -X GET https://api.complycube.com/v1/clients?page=1&pageSize=20 \
     -H 'Authorization: <YOUR_API_KEY>'
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const { ComplyCube } = require("@complycube/api");

const complycube = new ComplyCube({ apiKey: "<YOUR_API_KEY>" });

// For clients
const clients = await complycube.client.list({
    page: 1,
    pageSize: 20
});

// For documents. Similarly done for addresses, checks, live photos, etc.
const documents = await complycube.document.list("CLIENT_ID", {
    page: 1,
    pageSize: 20
});
```

{% endtab %}

{% tab title="Python" %}

```python
from complycube import ComplyCubeClient

cc_api = ComplyCubeClient(api_key='<YOUR_API_KEY>')

# For clients
clients = cc_api.clients.list(page=1,pageSize=20)

# For documents. Similarly done for addresses, checks, live photos, etc.
documents = cc_api.documents.list('CLIENT_ID',page=1,pageSize=20)
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;

$ccapi = new ComplyCubeClient('<YOUR_API_KEY>');

// For clients
$clients = $ccapi->clients()->list(['page' => 1, 'pageSize' => 20]);

// For documents. Similarly done for addresses, checks, live photos, etc.
$documents = $ccapi->documents()->list('CLIENT_ID', 
                                       ['page' => 1, 'pageSize' => 20]);
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using ComplyCube.Net;
using ComplyCube.Net.Resources.Clients;

var clientApi = new ClientApi(new ComplyCubeClient("<YOUR_API_KEY>"));

var req = new PageRequest { page = 1, pageSize = 20 };

var clients = await clientApi.ListAsync(pageRequest : req);
```

{% endtab %}
{% endtabs %}


# Errors

ComplyCube API error codes for KYC, AML, and identity verification, including HTTP status codes, processing errors, validation failures, and example responses.

ComplyCube uses standard HTTP response codes to indicate the success or failure of an API request.

Codes in the `2xx` range indicate success. Codes in the `4xx` range indicate an error that failed given the information provided. Codes in the `5xx` range indicate an error with ComplyCube's servers.

Some `4xx` errors include an [error code](/documentation/api-reference/errors#example-of-standard-errors) that briefly explains why the error occurred.

## HTTP response codes

<table><thead><tr><th width="329.53515625">Code</th><th>Description</th></tr></thead><tbody><tr><td><code>200</code></td><td>Everything worked as expected.</td></tr><tr><td><code>204</code></td><td>The resource is deleted.</td></tr><tr><td><code>400</code></td><td>The request has missing arguments or is malformed. See an <a href="#bad-request">example</a> of this type of error.</td></tr><tr><td><code>401</code></td><td>The request is not authenticated. See an <a href="#unauthorized">example</a> of this type of error.</td></tr><tr><td><code>402</code></td><td>The request is not available as payment is due. This is only returned for users on our credit-based plans.</td></tr><tr><td><code>403</code></td><td>The request is authenticated but does not have sufficient permissions. See an <a href="#forbidden">example</a> of this type of error.</td></tr><tr><td><code>404</code></td><td>The resource requested does not exist.</td></tr><tr><td><code>413</code></td><td>The request is too large.</td></tr><tr><td><code>422</code></td><td>A <a href="/pages/-M6Tx04RsqEf7zlRminH#processing-errors">processing error</a> has occurred.</td></tr><tr><td><code>429</code></td><td>The <a href="/pages/-M6VCth8GPkdciLwzD-o">rate limit</a> or <a href="/pages/-M71m4twjTuntF4kytPU">service quota</a> has been breached.</td></tr><tr><td><code>500</code></td><td>Something is wrong on our end. Subscribe to our <a href="https://status.complycube.com">status page</a> to be notified of any incident.</td></tr></tbody></table>

## Processing Errors

<table><thead><tr><th width="329.55078125">Error</th><th>Description</th></tr></thead><tbody><tr><td><code>two_sides_expected</code></td><td><p>Returned when only one side of a supported <a href="https://docs.complycube.com/documentation/checks/document-check/document-types-per-country">document type</a> is provided before running a check.</p><p>Applies to <strong>Document Checks</strong>.</p></td></tr><tr><td><code>unsupported_document_format</code></td><td><p>Returned when an unsupported document attachment format is provided before running a check.</p><p>Applies to <strong>Document Checks</strong>.</p></td></tr><tr><td><code>unsupported_document_type_country</code></td><td><p>Returned when a check is run against an unsupported <a href="https://docs.complycube.com/documentation/checks/document-check/document-types-per-country">ID type and country combination</a>.</p><p>Applies to <strong>Document Checks</strong>.</p></td></tr><tr><td><code>document_requires_issuing_country</code></td><td><p>Returned when a check is run against a document with a missing <code>issuingCountry</code> attribute.</p><p>Applies to <strong>Document Checks</strong>.</p></td></tr><tr><td><code>document_type_undetected</code></td><td><p>Returned when an unsupported <a href="https://docs.complycube.com/documentation/checks/document-check/document-types-per-country">document type</a> is checked. It could also be returned when the image quality is inadequate to recognize the document.</p><p>Applies to <strong>Document Checks</strong> and eligible <strong>Document uploads</strong>.</p></td></tr><tr><td><code>invalid_check_update</code></td><td>Returned when an update request is made on an unmodifiable check type.<br><br>Only <strong>Standard Screening Checks</strong> and <strong>Extensive Screening Checks</strong> can be updated.</td></tr><tr><td><code>pending_check_unmodifiable</code></td><td>Returned when an update request is made on a check with a status of 'pending'.</td></tr><tr><td><code>image_unreadable</code></td><td><p>Returned when ComplyCube is not able to read data from a document image. This may occur when the image is of low quality or is incorrectly oriented.</p><p>Applies to <strong>Document Checks</strong> and eligible <strong>Document uploads</strong>.</p></td></tr><tr><td><code>under_exposure</code></td><td><p>Returned when the uploaded document image is too dark. This may occur when the image is underexposed.</p><p>Applies to eligible <strong>Document uploads</strong>.</p></td></tr><tr><td><code>excessive_glare</code></td><td><p>Returned when the uploaded document image has excessive glare.</p><p>Applies to eligible <strong>Document uploads</strong>.</p></td></tr><tr><td><code>document_liveness_failed</code></td><td><p>Returned when a document photo is deemed likely as spoofed, i.e., not live. It could also be returned when the image quality is inadequate to establish the liveness.</p><p>Applies to eligible <strong>Document uploads</strong>.</p></td></tr><tr><td><code>document_photocopy_detected</code></td><td><p>Returned when a document photo is deemed to be a photocopy.</p><p>Applies to eligible <strong>Document uploads</strong>.</p></td></tr><tr><td><code>invalid_image_format</code></td><td><p>Returned when an invalid image format is provided.</p><p><br>Applies to <strong>Live Photo</strong>, <strong>Identity Checks,</strong> and <strong>Document Checks</strong>.</p></td></tr><tr><td><code>liveness_failed</code></td><td><p>Returned when a live photo is deemed likely as spoofed, i.e., not live. It could also be returned when the image quality is inadequate to establish the liveness.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>multiple_faces_detected</code></td><td><p>Returned when multiple faces are detected. The client must retake the live photo.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>no_face_detected</code></td><td><p>Returned when no faces are detected. The client must retake the live photo.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>face_not_centred</code></td><td><p>Returned when a face is not centered. The client must retake the live photo.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>facial_features_obstructed</code></td><td><p>Returned when facial features are obstructed. The client must retake the live photo.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>face_too_small</code></td><td><p>Returned when the face is too small. The client must come closer and retake the live photo.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>face_too_close</code></td><td><p>Returned when the face is too close. The client must move away from the camera and retake the live photo.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>face_not_centered</code></td><td><p>Returned when the face is too close to the edge of the photo. The client must center their face and retake the live photo.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>face_cropped</code></td><td><p>Returned when the face has been cropped. The client must retake the photo with their entire face in the frame.</p><p>Applies to <strong>Live Photo</strong>.</p></td></tr><tr><td><code>unsupported_poa_document_type</code></td><td><p>Returned when a check is run against an unsupported <a href="https://docs.complycube.com/documentation/checks/proof-of-address-check">proof of address document</a>.</p><p>Applies to <strong>Proof of Address Checks</strong>.</p></td></tr><tr><td><code>unsupported_dl_check_document_type</code></td><td><p>Returned when a check is run against an unsupported driving license document.</p><p>Applies to <strong>Driving License Checks</strong>.</p></td></tr><tr><td><code>unsupported_country</code></td><td><p>Returned when a check is run against an <a href="https://docs.complycube.com/documentation/checks/multi-bureau-check/service-coverage#list-of-supported-countries">unsupported country</a>.</p><p>Applies to <strong>Multi-Bureau Checks</strong>.</p></td></tr><tr><td><code>missing_address_attributes</code></td><td><p>Returned when a check is run while lacking the <a href="https://docs.complycube.com/documentation/checks/multi-bureau-check/service-coverage#list-of-supported-countries">minimum required address attributes</a>.</p><p>Applies to <strong>Multi-Bureau Checks</strong>.</p></td></tr><tr><td><code>missing_client_attributes</code></td><td><p>Returned when a check is run while lacking the <a href="https://docs.complycube.com/documentation/checks/multi-bureau-check/service-coverage#list-of-supported-countries">minimum required client attributes</a>.</p><p>Applies to <strong>Multi-Bureau Checks</strong>.</p></td></tr><tr><td><code>invalid_id_number_format</code></td><td><p>Returned when a check is run with an <a href="https://docs.complycube.com/documentation/checks/multi-bureau-check/service-coverage#list-of-supported-countries">incorrectly formatted ID Number</a> for a given country (e.g., SSN, Social Insurance Number).</p><p>Applies to <strong>Multi-Bureau Checks</strong>.</p></td></tr><tr><td><code>image_too_large</code></td><td><p>Returned when the image provided is too large.</p><p>Applies to <strong>Document, Live Photo</strong>, <strong>Identity Checks,</strong> and <strong>Document Checks</strong>.</p></td></tr></tbody></table>

## Example of Standard Errors

Below, you will find some example error responses from the ComplyCube API.

### Unauthorized

You'll most likely receive a `401: Unauthorized` response when you provide an invalid API key.

```json
{
    "type": "unauthorized",
    "message": "The 'Authorization' header is invalid"
}
```

### Forbidden

You'll most likely receive a `403: Forbidden` response when you do not have access to the requested resource.

```json
{
    "type": "unauthorized",
    "message": "Your current plan does not include access to this service"
}
```

### Bad Request

You'll get a `400: Bad Request` when you fail validation.

```json
{
    "type": "invalid_request",
    "message": "'personDetails' must be provided when client type is `person`",
    "param": "personDetails"
}
```

### Not Found

When a resource is not found, you will get a `404: Not Found` response.

```json
{
    "type": "resource_not_found",
    "message": "Invalid client id '123456789'"
}
```

### Rate Limited

You will receive a `429: Too Many Requests` response when you make too many requests.

```json
{
  "type": "rate_limit_exceeded",
  "message": "You have exceeded the rate limit prescribed to your plan"
}
```

### Internal Server Error

You'll receive a `500: Internal Server Error` response when something goes wrong on our side.

```json
{
  "type": "internal_server_error",
  "message": "An error has occurred, try your request again. If you still keep getting this error, please get in touch with Support."
}
```


# Versioning Policy

Review ComplyCube API versioning policy, backward-compatible changes, webhook event updates, and release changelog.

## Backward compatibility <a href="#backwards-compatibility" id="backwards-compatibility"></a>

The following changes are considered backward compatible:

* Adding new API resources.
* Adding new optional request parameters to existing API methods.
* Adding new properties to existing API responses.
* Changing the order of properties in existing API responses.
* Changing the length or format of object IDs or other opaque strings.
* Altering the `message` attributes returned by our [errors](/documentation/api-reference/errors).
* Adding new webhooks [event types](/documentation/api-reference/other-resources/webhooks#event-types). Your webhook listener should gracefully handle unfamiliar event types.

## Changelog <a href="#changelog" id="changelog"></a>

### v1.7.3

* Added new Static Data endpoints.
* Additional webhook [event types](/documentation/api-reference/other-resources/webhooks#event-types) added.

### v1.7.2

* You can now use almost all attributes for [filtering](/documentation/api-reference/filtering).

### v1.7.1

* Added `joinedDate` to [clients](/documentation/api-reference/core-resources/clients) to allow for migrated clients.

### v1.7.0

* Extended [country coverage](https://docs.complycube.com/documentation/checks/document-check/document-types-per-country) for [Document Checks](/documentation/api-reference/check-types/document-check).
* Extended [list coverage](https://docs.complycube.com/documentation/checks/aml-screening-check) for [AML Screening Checks](/documentation/api-reference/check-types/aml-screening-check).
* Added more [test scenarios](https://docs.complycube.com/documentation/useful-resources/testing-data) to the sandbox environment.

### v1.6.0

* Introduced [Service Quota](/documentation/api-reference/service-quota) to API.
* Added more [test scenarios](https://docs.complycube.com/documentation/useful-resources/testing-data) to the sandbox environment.

### v1.5.0

* [Reports](/documentation/api-reference/other-resources/reports) can now generate a summary client report.
* Additional country risk sources were added to [Risk Profile](/documentation/api-reference/core-resources/risk-profile).

### v1.4.1

* Added additional `classifications` for [Documents](/documentation/api-reference/core-resources/documents).

### v1.4.0

* Introduced [Risk Profile](/documentation/api-reference/core-resources/risk-profile).

### v1.3.0

* Added [tokens](/documentation/api-reference/other-resources/tokens) endpoint.
* Added `updatedAt` to [checks](/documentation/api-reference/core-resources/checks).

### v1.2.2

* Added attribute `telephone` to [clients](/documentation/api-reference/core-resources/clients).

### v1.2.1

* Added calculated attribute `entityName` to [clients](/documentation/api-reference/core-resources/clients).

### v1.2.0

* Ability to create [clients](/documentation/api-reference/core-resources/clients) of the type `company`.

### v1.1.0

* Introduced [Extensive AML Screening](/documentation/api-reference/check-types/aml-screening-check).
* Added more [error](/documentation/api-reference/errors) types.

### v1.0.1

* Added additional [address](/documentation/api-reference/core-resources/addresses) types.

### v1.0.0

* Initial release.


# Clients

Clients are a core resource to all ComplyCube services.

A **client** (or customer) represents the individual or company you want to verify. Before running any checks, you must first create a client record.

The API allows you to create, retrieve, update, and delete clients. You can fetch a specific client or retrieve a list of all your clients.

### The Client object

<table data-full-width="false"><thead><tr><th width="240.01171875">Attribute</th><th width="81">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>string</td><td>The unique identifier for a client.</td></tr><tr><td><code>type</code></td><td>string</td><td><p>The type of client. Valid values are:</p><ol><li><code>person</code></li><li><code>company</code></li></ol></td></tr><tr><td><code>entityName</code></td><td>string</td><td>The client's full name.</td></tr><tr><td><code>email</code></td><td>string</td><td>The client's email address.</td></tr><tr><td><code>mobile</code></td><td>string</td><td>The client's mobile number.</td></tr><tr><td><code>telephone</code></td><td>string</td><td>The client's telephone number.</td></tr><tr><td><code>externalId</code></td><td>string</td><td>A unique identifier that you can associate with the client. For example, this can be the client ID in your system.</td></tr><tr><td><code>joinedDate</code></td><td>string</td><td>The date and time when you registered the client. This is relevant for users that migrate existing clients. The format is <code>YYYY-MM-DD</code>.</td></tr><tr><td><code>personDetails</code></td><td>object</td><td>Details for a client of type <code>person</code>.  Also, see the <a href="/pages/-M6VRrtR0EG7-RpEuG3s#the-persondetails-object">personDetails</a> object below.</td></tr><tr><td><code>companyDetails</code></td><td>object</td><td>Details for a client of type <code>company</code>. Also, see the <a href="/pages/-M6VRrtR0EG7-RpEuG3s#the-companydetails-object">companyDetails</a> object below.</td></tr><tr><td><code>metadata</code></td><td>object</td><td>Set of key-value pairs that you can associate with the client object. This is useful for storing additional information about the client in a structured format. You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long.</td></tr><tr><td><code>createdAt</code></td><td>string</td><td>The date and time when the client was created.</td></tr><tr><td><code>updatedAt</code></td><td>string</td><td>The date and time when the client was updated.</td></tr></tbody></table>

#### The `personDetails` object&#x20;

<table data-full-width="false"><thead><tr><th width="240.1171875">Attribute</th><th width="85">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>firstName</code></td><td>string</td><td><p>The client's first name. </p><p>(<strong>Required</strong>)</p></td></tr><tr><td><code>middleName</code></td><td>string</td><td>The client's middle name. (<em>Optional)</em></td></tr><tr><td><code>lastName</code></td><td>string</td><td>The client's last name. (<strong>Required</strong>)</td></tr><tr><td><code>dob</code></td><td>string</td><td>The client's date of birth. The format is <code>YYYY-MM-DD</code>. (<em>Optional)</em></td></tr><tr><td><code>gender</code></td><td>string</td><td><p>The client's gender. Valid values include:</p><ol><li><code>male</code></li><li><code>female</code></li><li><code>other</code></li></ol><p> (<em>Optional)</em></p></td></tr><tr><td><code>nationality</code></td><td>string</td><td>The client's nationality. This will be the <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">two-letter country ISO code</a>. (<em>Optional)</em></td></tr><tr><td><code>birthCountry</code></td><td>string</td><td>The client's birth country. This will be the <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">two-letter country ISO code</a>. (<em>Optional)</em></td></tr><tr><td><code>ssn</code></td><td>string</td><td>The client's SSN (Social Security Number). This is for US clients. (<em>Optional)</em></td></tr><tr><td><code>socialInsuranceNumber</code></td><td>string</td><td>The client's Social Insurance Number. (<em>Optional)</em></td></tr><tr><td><code>nationalIdentityNumber</code></td><td>string</td><td>The client's National Identity Number. (<em>Optional)</em></td></tr><tr><td><code>taxIdentificationNumber</code></td><td>string</td><td>The client's Tax Identification Number (TIN). (<em>Optional)</em></td></tr></tbody></table>

#### The `companyDetails` object&#x20;

<table data-full-width="false"><thead><tr><th width="240.20703125">Attribute</th><th width="86">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td>string</td><td>The client's name. (<strong>Required</strong>)</td></tr><tr><td><code>website</code></td><td>string</td><td>The client's website. (<em>Optional)</em></td></tr><tr><td><code>registrationNumber</code></td><td>string</td><td>The client's registration or incorporation number. (<em>Optional)</em></td></tr><tr><td><code>incorporationCountry</code></td><td>string</td><td>The client's incorporation country. This will be the <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">two-letter country ISO code</a>. (<em>Optional)</em></td></tr><tr><td><code>incorporationType</code></td><td>string</td><td><p>The client's incorporation type. Valid values include:</p><ol><li><code>sole_proprietorship</code></li><li><code>private_limited_company</code></li><li><code>public_limited_company</code></li><li><code>partnership</code></li><li><code>limited_partnership</code></li><li><code>limited_liability_partnership</code></li><li><code>holding_company</code></li><li><code>non_government_organization</code></li><li><code>non_profit_organization</code></li><li><code>governmental_entity</code></li><li><code>statutory_company</code></li><li><code>subsidiary_company</code></li><li><code>unlimited_partnership</code></li><li><code>unlimited_company</code></li><li><code>trust</code></li><li><code>charitable_incorporated_organization</code></li><li><code>chartered_company</code></li><li><code>cooperative</code></li><li><code>professional_association</code></li><li><code>other</code></li></ol><p>(<em>Optional)</em></p></td></tr></tbody></table>




---

[Next Page](/documentation/llms-full.txt/1)

