Skip to main content

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

What Data Does MoonPay Expect?

At minimum, MoonPay expects the applicant data described in the standard onboarding requirements. 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. To keep onboarding smooth and avoid extra steps for your customer:
  • Include the KYC questionnaire in your request. This covers employment status, income, source of wealth, and transaction expectations, which SumSub does not typically collect.
  • Include the EDD questionnaire 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.
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 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 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 to MoonPay.
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.
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.

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 endpoint to PATCH them onto the applicant.
FieldLocationDescription
phoneTop-levelApplicant’s phone number (e.g. +12345678)
nationalityfixedInfoISO 3166-1 alpha-3 country code (e.g. DEU)
tinfixedInfoSSN or ITIN. Required for US citizens and residents. A value starting with 9 is read as an ITIN, otherwise an SSN. Dashes are allowed.
streetfixedInfo.addresses[]Street address
townfixedInfo.addresses[]City
postCodefixedInfo.addresses[]Postal code
countryfixedInfo.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 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 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.
{
  "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"
}
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 to issue a one-time token. This call is made server-side using your SumSub credentials.
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
  }'
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
HeaderRequiredDescription
X-API-KeyYesYour MoonPay API key
Idempotency-KeyYesA unique UUID. Prevents duplicate identifications if retried.
X-Sub-Partner-IDNoSub-partner UUID, if scoped to a sub-partner
Body Parameters
ParameterTypeRequiredDescription
type"Token"YesMust be "Token"
tokenstringYesThe SumSub share token
intended_usestringYesOne of: Investing, PaymentToFriendsFamilyorOthers, PurchaseDigitalAssets, OnlinePurchasesOfGoodsOrServices, Trading
ip_addressstringNoApplicant IP for fraud/geo signals. Optional if captured via SumSub. See IP address. You can omit it when your integration does not require EUR; otherwise supply it (API, SumSub tracking, or applicant metadata).
kyc_questionnaireobjectRecommendedSee KYC questionnaire fields. Omitting this field causes a Pending response requiring a step-up flow for the customer.
edd_questionnaireobjectNoSee EDD questionnaire fields. EDD is only triggered when you include this object. Omitting it means EDD is not applied.
with_edd is a response field only. It reflects whether EDD was applied to the identification. Do not include it in your request body — Iron ignores it.

Basic Request

At minimum, provide the token and intended use:
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:
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:
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

FieldValues
employment_statusEmployed, SelfEmployed, Unemployed, Retired, Student
yearly_gross_incomeLessThan20000, From20001To30000, From30001To40000, From40001To50000, From50001To60000, From60001To70000, From70001To80000, From80001To90000, From90001To100000, From100001To110000, From110001To120000, From120001To130000, From130001To140000, From140001To150000, MoreThan150000, From150001To200000, From200001To500000, MoreThan500000
source_of_wealthSalary, Savings, Investments, CryptoTrading, Other
expected_monthly_transaction_countLessThan5, Between5And10, MoreThan10
expected_monthly_transaction_volumeLessThan500, MoreThan500LessThan2000, MoreThan2000

EDD Questionnaire Fields

FieldValues
occupationAgriculture, ArtsAndEntertainment, Construction, Education, FinancialServices, InformationAndTechnology, Retail, RealEstate, Other, BusinessOwner, Healthcare, Industrial, LegalServices, PublicSector, SeniorManagement
approximate_net_worthUpTo25000, Between25001And50000, Between50001And100000, Between100001And300000, Between300001And500000, Between500001And1000000, Over1000001
source_of_funds_proofBase64-encoded document (jpg, png, pdf, doc, docx, xls, xlsx, odt, ods, txt). Max 10 MB.

3. Handle the Response

The endpoint returns an Identification object:
FieldTypeDescription
idstring (UUID)Unique identification ID
customer_idstring (UUID)The customer this identification belongs to
statusstringCurrent status. See Identification Lifecycle.
with_eddboolean or nullWhether EDD was applied: true, false, or null for pre-feature identifications. See Tracking EDD Status.
urlstring or nullIf Pending, redirect the customer to this URL to complete missing steps
created_atstring (ISO 8601)Creation timestamp
updated_atstring (ISO 8601)Last update timestamp
Sufficient data: onboarding proceeds immediately. with_edd reflects whether EDD was applied — it is set by Iron based on the risk profile, not by your request.
{
  "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:
{
  "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
StatusCause
400Invalid body, customer is not a person, invalid base64 source_of_funds_proof, or source_of_funds_proof exceeds 10 MB
401Invalid API key or missing CreateIdentification permission
403Authenticated, but not authorized for this customer or sub-partner scope
404Customer not found
409An identification is already in progress for this customer
500Internal error while creating the identification. Retry with the same Idempotency-Key.
This endpoint uses two error body shapes. Client errors (400, 401, 403, 404, 409) return a plain JSON string. Server errors (500) return an object with message and trace_id. Quote the trace_id when reporting a 500 to MoonPay.
A client error (4xx) is a JSON string:
"Source of funds proof exceeds 10MB limit"
A server error (500) is an object:
{
  "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 Iron. If you collect POA during your KYC flow, ensure the document is on the SumSub applicant before generating the share token. Iron reads it automatically. If POA is missing when Iron 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.
  2. Redirect to the hosted step-up flow: Use the url returned on the Pending identification. Iron’s hosted flow collects only the missing documents — the customer does not redo full KYC.
The Iron dashboard showing “Proof of Residence: Not Started” means Iron 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 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.
Each identification is immutable once created. A new token submission creates a new identification for the same customer.

4. Identification Lifecycle

StatusDescription
PendingWaiting for the end-user to complete missing steps via the returned URL
ProcessedData submitted and verification is underway
PendingReviewUnder manual review by the compliance team
ApprovedIdentification approved. Customer is verified.
DeclinedIdentification declined
ExpiredIdentification expired due to inactivity
In the best case, an applicant with sufficient data moves from Processed to Approved within seconds.
Subscribe to the identification_status webhook to track status changes in real time rather than polling.