> ## 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:

<Steps>
  <Step title="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.
  </Step>

  <Step title="Generate a share token">
    Call SumSub's API to create a one-time share token for your applicant.
  </Step>

  <Step title="Submit the token to MoonPay">
    Send the token to MoonPay's identification endpoint with the required parameters.
  </Step>

  <Step title="Handle the response">
    If the data is sufficient, onboarding completes in seconds. If not, redirect the customer to complete the missing steps.
  </Step>
</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](/onboarding#terms-and-conditions).
</Note>

## What Data Does MoonPay Expect?

At minimum, MoonPay expects the applicant data described in the [standard onboarding requirements](/kyc#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](/onboarding#handling-missing-information) for details.
</Note>

## 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>

<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>

### 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](/kyc#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.

<CodeGroup>
  ```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"
  }
  ```
</CodeGroup>

<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.
</Warning>

## 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.

<CodeGroup>
  ```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": "iron.xyz",
      "ttlInSecs": 600
    }'
  ```
</CodeGroup>

<Warning>
  Share tokens are **single-use**: SumSub invalidates a token after it has been consumed. Generate a new token for each submission attempt.
</Warning>

### 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`](/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 | Recommended | See [KYC questionnaire fields](#kyc-questionnaire-fields). Omitting this field 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.
</Note>

#### Basic Request

At minimum, provide the token and intended use:

<CodeGroup>
  ```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"
       }'
  ```
</CodeGroup>

#### With KYC Questionnaire

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

<CodeGroup>
  ```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"
         }
       }'
  ```
</CodeGroup>

#### 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:

<CodeGroup>
  ```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>"
         }
       }'
  ```
</CodeGroup>

#### 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](/onboarding#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.

<CodeGroup>
  ```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"
  }
  ```
</CodeGroup>

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

<CodeGroup>
  ```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"
  }
  ```
</CodeGroup>

**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](/idempotency) |
| `429` | Identification creation rate limit exceeded |
| `500` | Internal error while creating the identification. Retry with the same `Idempotency-Key`. |

<Warning>
  A `409` on the token flow always 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](/sharing#duplicate-submissions).
</Warning>

<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. `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](/errors).
</Note>

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

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

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

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

### 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.
</Note>

### 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.
</Note>

### 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](/webhooks) to track status changes in real time rather than polling.
</Note>
