> ## Documentation Index
> Fetch the complete documentation index at: https://dev.enterprise.moonpay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SumSub Token Sharing

> Share existing SumSub KYC data with MoonPay to onboard verified applicants in seconds.

## Introduction

If your organization already verifies customers through SumSub, you can share that verification data with MoonPay using a **share token**. Your customers do not need to go through KYC again.

This requires a tri-party agreement between MoonPay, your organization, and SumSub. Once signed, the integration is straightforward:

**1. Prepare your SumSub applicant**

The profile must include contact info, address, and (for **US citizens or residents**) an **SSN or ITIN** in `fixedInfo.tin`. For IP, follow [IP address](#ip-address): supply it (or use SumSub IP capture) when you need **EUR**-related capabilities. Otherwise you can omit `ip_address` on the MoonPay request.

**2. Generate a share token**

Call SumSub's API to create a one-time share token for your applicant.

**3. Submit the token to MoonPay**

Send the token to MoonPay's identification endpoint with the required parameters.

**4. Handle the response**

If the data is sufficient, onboarding completes in seconds. If not, redirect the customer to complete the missing steps.

> [!NOTE]
>
> Present and sign the terms and conditions before submitting the share token. Fetch the document via `GET /api/customers/{id}/required-signings` and record acceptance via `POST /api/customers/{id}/signings`. Keep this flow reachable afterwards: customers must sign again when a new document is published. See [Terms and Conditions](https://dev.enterprise.moonpay.com/onboarding.md#terms-and-conditions).

## What Data Does MoonPay Expect?

At minimum, MoonPay expects the applicant data described in the [standard onboarding requirements](https://dev.enterprise.moonpay.com/kyc.md#standard-onboarding-usa-eea-uk-aus-low-risk-row). The share token must carry enough verified data to satisfy these requirements. **US citizens and residents** must also have an **SSN or ITIN** in `fixedInfo.tin` before sharing. See [US citizens and residents: SSN and TIN](#us-citizens-and-residents-ssn-and-tin).

**To keep onboarding smooth and avoid extra steps for your customer:**

* **Include the [KYC questionnaire](#kyc-questionnaire-fields)** in your request. This covers employment status, income, source of wealth, and transaction expectations, which SumSub does not typically collect.
* **Include the [EDD questionnaire](#edd-questionnaire-fields) as well** if you already know the customer will transact large amounts or resides in a higher-risk jurisdiction. This prevents a step-up flow later.

> [!NOTE]
>
> If any required data is missing, MoonPay returns a `Pending` status with a `url`. This URL opens a hosted SumSub flow that **only asks for the missing information**, not a full KYC redo. You should redirect your customer to this URL to complete onboarding. See [handling missing information](https://dev.enterprise.moonpay.com/onboarding.md#handling-missing-information) for details.

## Preparing Your SumSub Applicant

Before generating a share token, the applicant's SumSub profile must contain all the data MoonPay requires. Missing fields are the most common cause of failed or incomplete token shares.

### IP Address

MoonPay uses the applicant's **IP address** for fraud and geo signals (including where **EUR** / euro-denominated or SEPA-related capabilities apply). You can provide it in one of three ways:

1. **SumSub IP tracking**: Enable [SumSub's IP address tracking](https://docs.sumsub.com/docs/advanced-ip-check) so the IP is captured automatically during verification.
2. **Metadata on the applicant**: Store the IP as metadata on the SumSub applicant so it is included in the shared data.
3. **Via the MoonPay API**: Pass the `ip_address` field directly in your [identification request](#2-submit-the-token-to-moonpay) to MoonPay.

> [!NOTE]
>
> If you use SumSub's IP tracking, you do not need to pass `ip_address` in the MoonPay API call. MoonPay reads it from the shared applicant data.

> [!NOTE]
>
> If your integration **does not require EUR** (for example, no euro virtual accounts, SEPA, or other euro-specific MoonPay flows), you can **omit `ip_address`** on the MoonPay identification request. If you **do** need EUR-related capabilities, supply the IP using one of the options above so checks can run reliably.

> [!NOTE]
>
> Depending on your account configuration, an IP address can be required for every customer, in which case applicant metadata is not read for it. Send `ip_address`, or use SumSub IP tracking where Sumsub has recorded an IP for the shared applicant. Without a valid IP address, the identification is accepted but waits in `Pending` for approval, and the customer's requirements list `ip_address` as missing.

### Required Applicant Data

The following fields must be present on the SumSub applicant's `fixedInfo` before sharing. If your KYC flow does not collect them, use SumSub's [Change Provided Info](https://docs.sumsub.com/reference/change-provided-info-fixedinfo) endpoint to PATCH them onto the applicant.

| Field | Location | Description |
| - | - | - |
| `phone` | Top-level | Applicant's phone number (e.g. `+12345678`) |
| `nationality` | `fixedInfo` | ISO 3166-1 alpha-3 country code (e.g. `DEU`) |
| `tin` | `fixedInfo` | SSN or ITIN. **Required for US citizens and residents.** A value starting with `9` is read as an ITIN, otherwise an SSN. Dashes are allowed. |
| `street` | `fixedInfo.addresses[]` | Street address |
| `town` | `fixedInfo.addresses[]` | City |
| `postCode` | `fixedInfo.addresses[]` | Postal code |
| `country` | `fixedInfo.addresses[]` | ISO 3166-1 alpha-3 country code |

### US citizens and residents: SSN and TIN

For **US citizens or US residents**, MoonPay requires a **Social Security Number (SSN)** or **Individual Taxpayer Identification Number (ITIN)**. See [Individual KYC standard onboarding](https://dev.enterprise.moonpay.com/kyc.md#standard-onboarding-usa-eea-uk-aus-low-risk-row) for the full requirement.

Set this value on the applicant's `fixedInfo.tin` field before you generate the share token. If your KYC flow does not collect it, PATCH it onto the applicant with SumSub's [Change Provided Info](https://docs.sumsub.com/reference/change-provided-info-fixedinfo) endpoint. A value starting with `9` is treated as an ITIN, otherwise as an SSN. Dashes are stripped, so `123-45-6789` and `123456789` are equivalent.

### Sample Applicant

Below is a representative SumSub applicant object showing the fields MoonPay needs. Fields extracted automatically by SumSub (document data, review results, questionnaires) are omitted for brevity.

```json theme={null}
{
  "clientId": "iron.xyz",
  "info": {
    "firstName": "John",
    "firstNameEn": "John",
    "lastName": "Doe",
    "lastNameEn": "Doe",
    "dob": "1990-01-11",
    "country": "DEU"
  },
  "fixedInfo": {
    "firstName": "John",
    "firstNameEn": "John",
    "lastName": "Doe",
    "lastNameEn": "Doe",
    "dob": "1990-01-11",
    "country": "DEU",
    "nationality": "DEU",
    "addresses": [
      {
        "street": "5 some street.",
        "streetEn": "5 some street.",
        "stateCode": "DE-BE",
        "town": "Berlin",
        "townEn": "Berlin",
        "postCode": "12345",
        "country": "DEU",
        "formattedAddress": "5 some street., Berlin, Germany, 10247"
      }
    ]
  },
  "email": "john.doe@gmail.com",
  "phone": "+12345678",
  "lang": "en",
  "type": "individual"
}
```

> [!WARNING]
>
> The `fixedInfo` block is the most important section: it contains the data that was provided by the customer and must be collected during your flow or PATCHed via the SumSub API. The `info` block is typically populated by SumSub's document extraction and does not need manual intervention.

## Integration

### 1. Generate a SumSub Share Token

Use [SumSub's share token API](https://docs.sumsub.com/reference/generate-share-token) to issue a one-time token. This call is made **server-side** using your SumSub credentials.

```bash theme={null}
curl --request POST \
  --url https://api.sumsub.com/resources/accessTokens/shareToken \
  --header 'Content-Type: application/json' \
  --header 'X-App-Token: <your-sumsub-app-token>' \
  --data '{
    "applicantId": "YOUR_APPLICANT_ID",
    "forClientId": "Moonpay",
    "ttlInSecs": 600
  }'
```

> [!WARNING]
>
> Share tokens are **single-use**: SumSub invalidates a token after it has been consumed. Generate a new token for each submission attempt.

### 2. Submit the Token to MoonPay

```
POST /api/customers/<customer_id>/identifications/v2
```

**Headers**

| Header | Required | Description |
| - | - | - |
| `X-API-Key` | Yes | Your MoonPay API key |
| `Idempotency-Key` | Yes | A unique UUID. Prevents duplicate identifications if retried. |
| `X-Sub-Partner-ID` | No | Sub-partner UUID, if scoped to a sub-partner |

**Body Parameters**

| Parameter | Type | Required | Description |
| - | - | - | - |
| `type` | `"Token"` | Yes | Must be `"Token"` |
| `token` | string | Yes | The SumSub share token |
| `intended_use` | string | Yes | One of: `Investing`, `PaymentToFriendsAndFamily`, `PaymentToThirdParties`, `PurchaseDigitalAssets`, `OnlinePurchasesOfGoodsOrServices`, `Trading`. `PaymentToFriendsFamilyorOthers` is deprecated and rejected from `X-API-Version: 2026-10-15` with [`intended_use_deprecated`](https://dev.enterprise.moonpay.com/errors#intended_use_deprecated). |
| `ip_address` | string | No | Applicant IP for fraud/geo signals. Optional if captured via SumSub. See [IP address](#ip-address). You can omit it when your integration **does not require EUR**; otherwise supply it (API, SumSub tracking, or applicant metadata). |
| `kyc_questionnaire` | object | Yes | See [KYC questionnaire fields](#kyc-questionnaire-fields). Depending on your account configuration, a request without it returns `400`. Otherwise omitting it causes a `Pending` response requiring a step-up flow for the customer. |
| `edd_questionnaire` | object | No | See [EDD questionnaire fields](#edd-questionnaire-fields). EDD is only triggered when you include this object. Omitting it means EDD is not applied. |

> [!NOTE]
>
> `with_edd` is a **response field only**. It reflects whether EDD was applied to the identification. Do not include it in your request body. MoonPay Enterprise ignores it.

#### Basic Request

At minimum, provide the token and intended use:

```bash theme={null}
curl --request POST \
     --url https://api.sandbox.iron.xyz/api/customers/<customer_id>/identifications/v2 \
     --header 'X-API-Key: <your-api-key>' \
     --header 'Idempotency-Key: <unique-request-id>' \
     --header 'content-type: application/json; charset=utf-8' \
     --data '{
       "type": "Token",
       "token": "sumsub_token",
       "intended_use": "Investing",
       "ip_address": "203.0.113.42"
     }'
```

#### With KYC Questionnaire

Include the questionnaire to avoid the customer being redirected to a step-up flow:

```bash theme={null}
curl --request POST \
     --url https://api.sandbox.iron.xyz/api/customers/<customer_id>/identifications/v2 \
     --header 'X-API-Key: <your-api-key>' \
     --header 'Idempotency-Key: <unique-request-id>' \
     --header 'content-type: application/json; charset=utf-8' \
     --data '{
       "type": "Token",
       "token": "sumsub_token",
       "intended_use": "Investing",
       "ip_address": "203.0.113.42",
       "kyc_questionnaire": {
         "employment_status": "Employed",
         "yearly_gross_income": "From50001To60000",
         "source_of_wealth": "Salary",
         "expected_monthly_transaction_count": "Between5And10",
         "expected_monthly_transaction_volume": "MoreThan500LessThan2000"
       }
     }'
```

#### With KYC + EDD Questionnaire

If the customer resides in a higher-risk jurisdiction or will transact large amounts, include both to complete onboarding in one step:

```bash theme={null}
curl --request POST \
     --url https://api.sandbox.iron.xyz/api/customers/<customer_id>/identifications/v2 \
     --header 'X-API-Key: <your-api-key>' \
     --header 'Idempotency-Key: <unique-request-id>' \
     --header 'content-type: application/json; charset=utf-8' \
     --data '{
       "type": "Token",
       "token": "sumsub_token",
       "intended_use": "Investing",
       "ip_address": "203.0.113.42",
       "kyc_questionnaire": {
         "employment_status": "Employed",
         "yearly_gross_income": "From50001To60000",
         "source_of_wealth": "Salary",
         "expected_monthly_transaction_count": "Between5And10",
         "expected_monthly_transaction_volume": "MoreThan500LessThan2000"
       },
       "edd_questionnaire": {
         "occupation": "FinancialServices",
         "approximate_net_worth": "Between100001And300000",
         "source_of_funds_proof": "<base64-encoded-document>"
       }
     }'
```

#### KYC Questionnaire Fields

| Field | Values |
| - | - |
| `employment_status` | `Employed`, `SelfEmployed`, `Unemployed`, `Retired`, `Student` |
| `yearly_gross_income` | `LessThan20000`, `From20001To30000`, `From30001To40000`, `From40001To50000`, `From50001To60000`, `From60001To70000`, `From70001To80000`, `From80001To90000`, `From90001To100000`, `From100001To110000`, `From110001To120000`, `From120001To130000`, `From130001To140000`, `From140001To150000`, `From150001To200000`, `From200001To500000`, `MoreThan500000`. `MoreThan150000` is deprecated: submissions using it are coerced to `From150001To200000`. Use one of the three bands above `150000` instead. |
| `source_of_wealth` | `Salary`, `Savings`, `Investments`, `CryptoTrading`, `SaleOfAssetsOrSettlement`, `Pension`, `CompanyProfits`, `SoleProprietorIncome`, `RentalIncome`, `Inheritance`, `Other` |
| `expected_monthly_transaction_count` | `LessThan5`, `Between5And10`, `MoreThan10` |
| `expected_monthly_transaction_volume` | `LessThan500`, `MoreThan500LessThan2000`, `MoreThan2000` |

#### EDD Questionnaire Fields

| Field | Values |
| - | - |
| `occupation` | `Agriculture`, `ArtsAndEntertainment`, `Construction`, `Education`, `FinancialServices`, `InformationAndTechnology`, `Retail`, `RealEstate`, `Other`, `BusinessOwner`, `Healthcare`, `Industrial`, `LegalServices`, `PublicSector`, `SeniorManagement` |
| `approximate_net_worth` | `UpTo25000`, `Between25001And50000`, `Between50001And100000`, `Between100001And300000`, `Between300001And500000`, `Between500001And1000000`, `Over1000001` |
| `source_of_funds_proof` | Base64-encoded Source of Wealth proof (jpg, png, pdf, doc, docx, xls, xlsx, odt, ods, txt). Max 10 MB. |

### 3. Handle the Response

The endpoint returns an `Identification` object:

| Field | Type | Description |
| - | - | - |
| `id` | string (UUID) | Unique identification ID |
| `customer_id` | string (UUID) | The customer this identification belongs to |
| `status` | string | Current status. See [Identification Lifecycle](#4-identification-lifecycle). |
| `with_edd` | boolean or null | Whether EDD was applied: `true`, `false`, or `null` for pre-feature identifications. See [Tracking EDD Status](https://dev.enterprise.moonpay.com/onboarding.md#tracking-edd-status). |
| `url` | string or null | If `Pending`, redirect the customer to this URL to complete missing steps |
| `created_at` | string (ISO 8601) | Creation timestamp |
| `updated_at` | string (ISO 8601) | Last update timestamp |

**Sufficient data**: onboarding proceeds immediately. `with_edd` reflects whether EDD was applied. It is set by MoonPay Enterprise based on the risk profile, not by your request.

```json theme={null}
{
  "id": "9a667227-6992-4c6b-951e-63765d5d8f33",
  "customer_id": "c5f2e8a1-3b4d-4e6f-8a9b-1c2d3e4f5a6b",
  "status": "Processed",
  "with_edd": true,
  "url": null,
  "created_at": "2025-01-06T16:54:40.162807+00:00",
  "updated_at": "2025-01-06T16:54:40.162807+00:00"
}
```

**Insufficient data**: redirect the customer to complete the missing information:

```json theme={null}
{
  "id": "9a667227-6992-4c6b-951e-63765d5d8f33",
  "customer_id": "c5f2e8a1-3b4d-4e6f-8a9b-1c2d3e4f5a6b",
  "status": "Pending",
  "with_edd": true,
  "url": "https://in.sumsub.com/idensic/l/#/...",
  "created_at": "2025-01-06T16:54:40.162807+00:00",
  "updated_at": "2025-01-06T16:54:40.162807+00:00"
}
```

**Error Responses**

| Status | Cause |
| - | - |
| `400` | Invalid body, customer is not a person, invalid base64 `source_of_funds_proof`, or `source_of_funds_proof` exceeds 10 MB |
| `401` | Invalid API key or missing `CreateIdentification` permission |
| `403` | Authenticated, but not authorized for this customer or sub-partner scope |
| `404` | Customer not found |
| `409` | The `Idempotency-Key` was already used for a request with a different body. See [Idempotency](https://dev.enterprise.moonpay.com/idempotency.md). A `409` with a `message` means the customer's verification can't take the submission, see below |
| `429` | Identification creation rate limit exceeded |
| `500` | Internal error while creating the identification. Retry with the same `Idempotency-Key`. |

> [!WARNING]
>
> A `409` without a `message` on the token flow means the `Idempotency-Key` was reused with a different body. Send a fresh UUID for each new submission, and reuse a key only when retrying that exact request. Archiving the customer's existing identification does not clear it.
>
> The token flow does not reject duplicate payloads, so a `409` here never points at an existing identification. That check applies to the `Person` and `Business` flows only. See [KYC/KYB Sharing](https://dev.enterprise.moonpay.com/sharing.md#duplicate-submissions).
>
> A `409` with a `message` explains why the submission can't be taken: the customer is already verified, a verification is still in progress (retry once it completes), the customer's verification can't take a submission right now, or the name, date of birth or nationality in the token differs from the verified customer's. Those details can't be changed after verification.

> [!NOTE]
>
> This endpoint uses three error body shapes. `401`, `403`, `404`, and `429` return a plain JSON string. `409` carries no explanatory body, just the status, unless it carries a `message` as described above. `500` returns an object with `message` and `trace_id`. Quote the `trace_id` when reporting a `500` to MoonPay.
>
> `400` depends on your `X-API-Version`: unversioned or earlier callers get a plain JSON string, same as `401`/`403`/`404`. Callers on `2026-08-01` or later get a structured array of error objects instead. See [Identification Errors](https://dev.enterprise.moonpay.com/errors.md).

A client error (`401`, `403`, `404`, or `429`) is a JSON string:

```json theme={null}
"Source of funds proof exceeds 10MB limit"
```

A server error (`500`) is an object:

```json theme={null}
{
  "message": "Create customer identification creation error. Please try again.",
  "trace_id": "0f9c7a1e-3b4d-4e6f-8a9b-1c2d3e4f5a6b"
}
```

### Proof of Address

There is no separate API field for proof of address (POA). POA is expected to come from the SumSub applicant's verified documents: it is read from the shared token, not uploaded directly to MoonPay Enterprise.

**If you collect POA during your KYC flow**, ensure the document is on the SumSub applicant before generating the share token. MoonPay Enterprise reads it automatically.

**If POA is missing when MoonPay Enterprise processes the token**, two options:

1. **Collect POA in SumSub, then re-submit**: Add the document to the SumSub applicant (via your own flow or SumSub's API), generate a new share token, and create a new identification. See [Re-submitting After Missing Document Data](#re-submitting-after-missing-document-data).
2. **Redirect to the hosted step-up flow**: Use the `url` returned on the `Pending` identification. MoonPay Enterprise's hosted flow collects only the missing documents. The customer does not redo full KYC.

> [!NOTE]
>
> The MoonPay Enterprise dashboard showing "Proof of Residence: Not Started" means MoonPay Enterprise determined POA is required but was not present in the shared token. It does not mean the identification has failed.

### Re-submitting After Missing Document Data

If a `Pending` response is caused by missing documents on the SumSub applicant (for example, a missing proof of address that was collected later), you cannot update an existing identification. Instead:

1. Ensure the SumSub applicant has the missing document or data. Use SumSub's [Change Provided Info](https://docs.sumsub.com/reference/change-provided-info-fixedinfo) endpoint to PATCH it if needed.
2. Generate a new share token for the applicant.
3. Create a new identification using `POST /api/customers/<customer_id>/identifications/v2` with the new token.

> [!NOTE]
>
> Each identification is immutable once created. A new token submission creates a new identification for the same customer.

### 4. Identification Lifecycle

| Status | Description |
| - | - |
| `Pending` | Waiting for the end-user to complete missing steps via the returned URL |
| `Processed` | Data submitted and verification is underway |
| `PendingReview` | Under manual review by the compliance team |
| `Approved` | Identification approved. Customer is verified. |
| `Declined` | Identification declined |
| `Expired` | Identification expired due to inactivity |

In the best case, an applicant with sufficient data moves from `Processed` to `Approved` within seconds.

> [!NOTE]
>
> Subscribe to the `identification_status` [webhook](https://dev.enterprise.moonpay.com/webhooks.md) to track status changes in real time rather than polling.
