> For the complete documentation index, see [llms.txt](https://docs.swapped.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.swapped.com/swapped-ramp/readme-1/sharing-sumsub-verification.md).

# Sharing Sumsub Verification

If you use Sumsub to verify your customers, you can share that verification with Swapped. The customer then skips the identity verification (ID document and liveness check) and the address verification steps that Sumsub already approved for you.

KYC sharing works with Sumsub only. If you use a different provider, or if Swapped cannot use the shared verification, the customer completes the standard verification in the widget.

## How It Works

1. Your backend requests a share token from Sumsub for the customer.
2. Your backend adds the customer's email and the share token to the widget URL, and signs the URL.
3. The customer opens the widget and signs in with the email code that Swapped sends.
4. Swapped imports the approved verification steps from Sumsub. The widget asks the customer only for the steps that are missing.

## Before You Start

* **Enable KYC sharing.** Contact Swapped to enable KYC sharing for your account. Send us your Sumsub client ID.
* **Link the Sumsub accounts.** Ask your Sumsub account manager to enable Reusable KYC between your Sumsub account and the Swapped Sumsub account. If the accounts are not linked, Sumsub rejects every share token.
* **Get customer consent.** You share the customer's personal data with Swapped. Make sure that the customer agrees to this before you generate a share token.
* **Sign your widget URLs.** This page uses the URL signature from [iFrame Initialization](/swapped-ramp/readme-1/iframe-initialization.md#server-side-url-signature).

## Step 1: Generate a Share Token

Your backend requests a share token from Sumsub for the customer. Authenticate the request with your own Sumsub app token and secret key, and sign it as Sumsub requires (`X-App-Token`, `X-App-Access-Ts`, and `X-App-Access-Sig` headers). Refer to the [Sumsub documentation](https://docs.sumsub.com/reference/generate-share-token). These credentials are secret, so send this request from your server only. Never send it from code that runs in the browser.

```
POST https://api.sumsub.com/resources/accessTokens/shareToken
```

```json
{
  "applicantId": "your_applicant_id",
  "forClientId": "bitinvestor_aps",
  "ttlInSecs": 600
}
```

* <mark style="color:$danger;">**`applicantId`**</mark>: The Sumsub applicant ID of the customer. This is the ID that Sumsub gives the applicant, not your `externalUserId`.
* <mark style="color:$danger;">**`forClientId`**</mark>: The Swapped Sumsub client ID. Always use `bitinvestor_aps`. Only Swapped can use the token.
* <mark style="color:$danger;">**`ttlInSecs`**</mark>: The time, in seconds, that the token stays valid. We recommend 600 or more. Refer to [Token Rules](#token-rules).

Sumsub returns the token in the `token` field:

```json
{
  "token": "_act-sbx-jwt-eyJhbGciOiJub25lIn0...",
  "forClientId": "bitinvestor_aps"
}
```

## Step 2: Build the Widget URL

Build the widget URL as described in [iFrame Initialization](/swapped-ramp/readme-1/iframe-initialization.md), then:

1. Add the `email` and `kycShareToken` parameters to the URL. The `email` must be the email on the Sumsub applicant.
2. Create the signature from the query string.
3. Add the signature as the last parameter in the query string.

When the URL contains both `email` and `kycShareToken`, the widget locks the email field. The customer cannot change the email.

```javascript
// Import the crypto module.
import crypto from 'crypto';

// Define the public API key.
const publicKey = 'your_public_key';

// Define the secret API key.
const secretKey = 'your_secret_key';

// Define the currency code.
const currencyCode = 'currency_code';

// Define the wallet address.
const walletAddress = 'your_wallet_address';

// Define the customer's email. This email must be the same as the email on the Sumsub applicant.
const email = 'customer_email';

// Define the share token from Sumsub (the "token" field of the Step 1 response).
const kycShareToken = 'your_share_token';

// Build the URL with the URL-encoded query parameters.
const params = [
  `apiKey=${encodeURIComponent(publicKey)}`,
  `currencyCode=${encodeURIComponent(currencyCode)}`,
  `walletAddress=${encodeURIComponent(walletAddress)}`,
  `email=${encodeURIComponent(email)}`,
  `kycShareToken=${encodeURIComponent(kycShareToken)}`,
].join('&');
const originalUrl = `https://widget.swapped.com/?${params}`;

// Create a SHA-256 HMAC signature from the search string of the URL. Encode the signature in Base64.
const signature = crypto.createHmac('sha256', secretKey).update(new URL(originalUrl).search).digest('base64');

// Add the URL-encoded signature to the end of the URL.
const urlWithSignature = `${originalUrl}&signature=${encodeURIComponent(signature)}`;

// Print the final URL.
console.log(urlWithSignature);
```

```php
<?php

// Define the public API key.
$publicKey = 'your_public_key';

// Define the secret API key.
$secretKey = 'your_secret_key';

// Define the currency code.
$currencyCode = 'currency_code';

// Define the wallet address.
$walletAddress = 'your_wallet_address';

// Define the customer's email. This email must be the same as the email on the Sumsub applicant.
$email = 'customer_email';

// Define the share token from Sumsub (the "token" field of the Step 1 response).
$kycShareToken = 'your_share_token';

// Build the URL with the URL-encoded query parameters.
$query = implode('&', [
    'apiKey=' . rawurlencode($publicKey),
    'currencyCode=' . rawurlencode($currencyCode),
    'walletAddress=' . rawurlencode($walletAddress),
    'email=' . rawurlencode($email),
    'kycShareToken=' . rawurlencode($kycShareToken),
]);
$originalUrl = "https://widget.swapped.com/?{$query}";

// Create a SHA-256 HMAC signature from the query string, including the "?". Encode the signature in Base64.
$signature = base64_encode(hash_hmac('sha256', '?' . $query, $secretKey, true));

// Add the URL-encoded signature to the end of the URL.
$urlWithSignature = "{$originalUrl}&signature=" . rawurlencode($signature);

// Print the final URL.
echo $urlWithSignature;
```

#### Example iFrame URL

```
https://widget.swapped.com/?apiKey={your_api_key}&currencyCode=BTC&walletAddress={your_wallet_address}&email={customer_email}&kycShareToken={share_token}&signature={your_signature}
```

## What the Customer Sees

1. The widget opens with the email already filled in and locked.
2. The customer requests a sign-in code and enters it.
3. The widget skips the verification steps that Swapped imported from Sumsub. If Swapped imported all steps, the customer goes directly to the order.

The customer must sign in with the email code. If the customer signs in with Google, Swapped does not use the share token.

## What Swapped Receives

Swapped accepts each verification step that Sumsub approved for your customer:

* **Proof of ID and Liveness Check**: Sumsub must approve both steps. The customer then skips identity verification. If your Sumsub level does not include a liveness check, Swapped cannot import identity verification.
* **Proof of Address**: Sumsub must approve this step. The customer then skips address verification.

Swapped copies the customer's name, date of birth, country, and address from the Sumsub applicant. If the applicant is approved for only some steps, the widget asks the customer only for the missing steps.

A share token can increase a customer's verification level. A share token cannot decrease it.

## Token Rules

* **Two time limits apply.** The Sumsub token expires `ttlInSecs` after you generate it. Separately, the customer must sign in within 5 minutes of opening the widget. Generate the token immediately before you open the widget, and set `ttlInSecs` to 600 or more, so that the Sumsub token does not expire before the customer signs in.
* **One token per widget open.** You can use a share token only once. Generate a new token each time you open the widget. If you open the widget again for the same customer, the new token replaces the previous one.
* **Bound to the email and your API key.** The token works only with the email in the signed URL, and only in a widget opened with your API key. The email match is not case-sensitive.

## When Swapped Does Not Share the Verification

If Swapped cannot use the shared verification, the customer completes the standard verification flow. The widget does not show an error. This occurs in these conditions:

* KYC sharing is not enabled for your account, or your Sumsub client ID is not set up with Swapped.
* The token expired, or it was already used. For example, the widget was opened two times with the same URL.
* The customer signed in with Google instead of the email code, or with a different email.
* The Sumsub applicant has no email, or has an email that is different from the `email` parameter.
* The applicant has no approved identity step and no approved address step.
* Sumsub rejects the reuse. For example, the applicant's document type is not accepted for Swapped, or the ID or address document is out of date.
* The customer already has full verification with Swapped.
* The applicant is already linked to a different Swapped account, or the customer's Swapped account is already linked to a different Sumsub applicant.
* Swapped does not support the customer's country of residence, or that country requires a manual review.

## Troubleshooting

The widget does not show why a shared verification was not used. To investigate a case, contact Swapped support with the customer's email and the approximate time that the customer opened the widget.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.swapped.com/swapped-ramp/readme-1/sharing-sumsub-verification.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
