> For a complete page index, fetch https://docs.transak.com/llms.txt

# Headless KYC

**Headless KYC** is a UI module that enables partners to integrate the multi-step KYC flow directly into their applications by simply loading Transak's KYC widget.

## Current Limitations

<table>
  <thead>
    <tr>
      <th>
        Limitation
      </th>

      <th>
        Details
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        **Headless KYC APIs ([Transaction Session API](/api/whitelabel/headless-kyc/transaction-session-api))**
      </td>

      <td>
        APIs are to be called only from the partner backend and subjected to the whitelisting of partner IP addresses. We don’t support API calls from the frontend due to security restrictions.
      </td>
    </tr>

    <tr>
      <td>
        **Camera permission**
      </td>

      <td>
        Partner app must grant camera permission at the manifest or browser level. If permission isn't available, the module shows fallback automatically.
      </td>
    </tr>

    <tr>
      <td>
        **Supported for JS, React, and React Native integrations**
      </td>

      <td>
        The Transak UI SDK is available for JS, React, and React Native integrations.
      </td>
    </tr>

    <tr>
      <td>
        **FCA Flow (For UK Users) not supported**
      </td>

      <td>
        Partners can integrate the APIs to submit the FCA requirements. See the [How to Submit FCA Requirements](https://docs.transak.com/guides/how-to-submit-fca) guide for step-by-step instructions.
      </td>
    </tr>
  </tbody>
</table>

## How to integrate?

#### Whitelist Your API Key & Enable Headless KYC

| Action                                                                                                                 |
| ---------------------------------------------------------------------------------------------------------------------- |
| Follow the steps in the [Need help in Integration](/getting-started/help-and-support#need-help-in-integration) section |
| Request **API key whitelisting**                                                                                       |
| Share your public IP addresses with Transak for whitelisting to use our APIs in your backend                           |

#### User Authentication

You can use either of the following authentication options:

| Option               | Description                                                                                                                                                                                                                                                                                 |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **White-label Auth** | Use the standard Transak authentication flow to generate a user access token. Partners can do this by calling the [Send User OTP API](/api/whitelabel/user/send-user-otp) followed by the [Verify User API](/api/whitelabel/user/verify-user-otp) to generate the access token. Learn more  |
| **Auth Reliance**    | Use [Auth Reliance](/features/auth-reliance) by passing these headers with every request: `x-user-identifier` and `x-access-token`                                                                                                                                                          |

Please refer to the tutorial on [how to create partner access token](/guides/how-to-create-partner-access-token).

#### Generate a quote using the Quote API

Call the [Get Quote API](https://docs.transak.com/api/whitelabel/lookup/get-quote) to get a quote for the transaction. Pass the apiKey, fiat amount, fiat currency, crypto currency, network, and order type.

A successful response returns a `quoteId`.

#### Create a transaction session (using Backend only)

Call the [Transaction Session API](/api/whitelabel/headless-kyc/transaction-session-api) from your backend, passing the `quoteId` from the previous step and a new `module` field set to `"kyc"`.

| Parameter | Description                                                                                                                  |
| --------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `quoteId` | Quote ID returned by the [Get Quote API](https://docs.transak.com/api/whitelabel/lookup/get-quote) in the previous step      |
| `module`  | Set to `"kyc"` to initialize a Headless KYC session                                                                          |
| `config`  | Optional. `colorMode` (`DARK` or `LIGHT`) to theme the KYC component and `colors` object to override individual theme colors |

A successful response returns a `sessionId`.

#### Load the Headless KYC Component via Transak UI SDK

Use the Transak UI SDK to render the KYC component. Pass the `sessionId` received in the previous step.

The module renders no Back/Next/Submit buttons of its own, wire your own UI to the SDK's `next()` / `back()` methods.

#### JS

```bash
npm install @transak/ui-components
```

```tsx
import { createTransakKyc } from '@transak/ui-components';

const kyc = createTransakKyc({
  sessionId, // sessionId from previous step
  environment, // 'STAGING' | 'PRODUCTION'
  onReady: () => {
    // Component is ready
  },
  onStateChange: (state) => {
    // Current step changed (e.g. personalDetails, address, idProof) — no user data included.
    // Use this to enable/disable your own Back/Next buttons.
  },
  onSubmitted: ({ kycStatus }) => {
    // All required forms submitted. kycStatus is almost always 'SUBMITTED';
    // track final approval separately via the KYC status API or webhook.
  },
  onError: ({ code }) => {
    // Handle error
  },
});

await kyc.mount('kyc-slot');

// wire to your own Back/Next buttons:
kyc.back();
kyc.next();

// and then
kyc.unmount();
```

#### React

```bash
npm install @transak/ui-components-react
```

```tsx
import { useRef } from 'react';
import { TransakKyc } from '@transak/ui-components-react';

const ref = useRef(null);

<TransakKyc
  ref={ref}
  sessionId={sessionId} // sessionId from previous step
  environment={environment} // 'STAGING' | 'PRODUCTION'
  onReady={() => {
    // Component is ready
  }}
  onStateChange={(state) => {
    // Current step changed — no user data included
  }}
  onSubmitted={({ kycStatus }) => {
    // All required forms submitted
  }}
  onError={({ code }) => {
    // Handle error
  }}
/>

// your own navigation buttons:
<button onClick={() => ref.current?.back()}>Back</button>
<button onClick={() => ref.current?.next()}>Next</button>
```

#### React Native

```bash
npm install @transak/ui-components-rn
```

```tsx
import { useRef } from 'react';
import { TransakKyc } from '@transak/ui-components-rn';

const ref = useRef(null);

<TransakKyc
  ref={ref}
  sessionId={sessionId} // sessionId from previous step
  environment={environment} // 'STAGING' | 'PRODUCTION'
  onReady={() => {
    // Component is ready
  }}
  onStateChange={(state) => {
    // Current step changed — no user data included
  }}
  onSubmitted={({ kycStatus }) => {
    // All required forms submitted
  }}
  onError={({ code }) => {
    // Handle error
  }}
/>

// your own navigation buttons:
<button onClick={() => ref.current?.back()}>Back</button>
<button onClick={() => ref.current?.next()}>Next</button>
```

> **Info**
>
> The React Native wrapper is WebView-based and must set `mediaCapturePermissionGrantType` and camera permissions so `Onfido` can access the camera inside the WebView.

**Error codes**

The `onError` callback receives a `code` value. Use it to handle specific failure scenarios:

| Code                       | Description                                                                         |
| -------------------------- | ----------------------------------------------------------------------------------- |
| `CONFIG_LOAD_FAILED`       | The session could not be loaded covers a missing, invalid, or expired `sessionId`   |
| `STEP_SUBMIT_FAILED`       | A form submission for the current step returned a non-2xx (non-validation) response |
| `FILE_UPLOAD_FAILED`       | Document upload (proof of address / source docs) failed.                            |
| `KYC_PROVIDER_UNAVAILABLE` | Onfido/vendor downtime or workflow-run failure                                      |
| `INVALID_OPTIONS`          | Invalid or missing options passed to the SDK                                        |
| `IFRAME_LOAD_FAILED`       | The embedded iframe failed to load                                                  |
| `INVALID_STATE`            | SDK method called in an unexpected state                                            |

#### Handle the ID proof and selfie step

The ID proof and selfie step is handled inside the module via `Onfido`, no separate integration is required. Keep the following in mind:

* Your app is responsible for granting camera permission (native app manifest or browser).
* If permission isn't available, the module automatically shows a fallback.

#### Track the final KYC status

The module's `onSubmitted` callback fires once all required forms are submitted, it does not guarantee final approval. Use the [Get KYC Requirement API](/api/whitelabel/kyc/get-kyc-requirement) to poll for the final status.

Partner can also use the [KYC Webhooks](/features/webhooks#kyc-webhooks) to receive a notification when the final status is available.

## API Overview

#### [Transaction Session API](/api/whitelabel/headless-kyc/transaction-session-api)

Creates a transaction session using a quote ID and `module: "kyc"`, returns a `sessionId` to initialise the Headless KYC component.

## API Errors

#### Transaction Session API

| HTTP Status | Error Code | Message                                                               |
| ----------- | ---------- | --------------------------------------------------------------------- |
| 401         | 1002       | Invalid or missing authentication token.                              |
| 422         | 6003       | This feature is not enabled for your account. Please contact support. |
| 422         | 6005       | Quote not found or could not be loaded.                               |
| 500         | 6005       | Failed to create a session for the user.                              |