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

# Identification Errors

> Machine-readable error codes returned by POST /customers/{id}/identifications/v2 when a Business, Person, or Token submission fails validation.

`POST /api/customers/{id}/identifications/v2` validates data-carrying submissions (`Business`, `Person`, and `Token`) synchronously. Under `X-API-Version: 2026-08-01` or later, a failed submission returns `400` with an array of structured error objects instead of the plain string returned by earlier versions:

```json theme={null}
[
  {
    "code": "tin_required",
    "message": "Beneficiary at index 1 is missing a tax identification number",
    "docs_url": "https://docs.iron.xyz/errors#tin_required",
    "beneficiary_index": 1
  }
]
```

The response is always an array. Today it contains exactly one entry — validation stops at the first problem it finds, the same as the plain-string behavior on earlier versions — but the array shape leaves room for returning multiple problems in one response in the future without another change to the response format. Don't assume exactly one entry; iterate the array.

<ResponseField name="code" type="string" required>
  Machine-readable identifier. One of the fixed set of values documented below. Safe to match on in code; it does not change across submissions the way `message` does.
</ResponseField>

<ResponseField name="message" type="string" required>
  Human-readable description of this specific occurrence of the error, for example naming the exact field or beneficiary involved. Useful for logs and support tickets, but don't pattern-match on it: it can be reworded without notice. Match on `code` instead.
</ResponseField>

<ResponseField name="docs_url" type="string" required>
  Link back to this page, anchored to the specific `code` (`https://docs.iron.xyz/errors#<code>`).
</ResponseField>

<ResponseField name="beneficiary_index" type="integer">
  Zero-based index into `company_data.beneficiaries` identifying which beneficiary the error originated from. Present only on `Business` submissions, and only when the error is scoped to a specific beneficiary rather than the submission as a whole.
</ResponseField>

<Note>
  Callers on an earlier or unversioned `X-API-Version` keep receiving today's plain error string on `400`, unchanged. The structured array is opt-in via the version header. See [API Versions](/versioning).
</Note>

<Warning>
  `Link` identifications never return this shape. A `Link` submission only opens a hosted flow, so it has nothing to validate synchronously at creation.
</Warning>

<Heading level={2} id="invalid_request">invalid\_request</Heading>

A catch-all for straightforward, client-preventable problems: a required field was left empty, a value doesn't match the expected format (email, phone, country code, date), a file exceeds its size limit, or too many documents or beneficiaries were submitted. Check `message` for the specific field and reason. Add client-side validation for the same rule so your integration catches it before it reaches the API.

<Heading level={2} id="selfie_required">selfie\_required</Heading>

The submission is missing a selfie where one is required. Every `Director` beneficiary on a `Business` submission needs one, and every `Person` submission needs one, in any country. Capture and submit a selfie along with `selfie_collected_at`.

<Heading level={2} id="selfie_expired">selfie\_expired</Heading>

A selfie was provided, but it's too old to accept: for `Person` submissions, older than 6 months. Capture a fresh selfie and resubmit.

<Heading level={2} id="tin_required">tin\_required</Heading>

A tax identification number is missing where one is required. On a `Business` submission, this applies to any beneficiary with the `Director` or `UltimateBeneficialOwner` role, in any country. On a `Person` submission, it applies when the identity document's issuing country (`identity.identity_country_code`) is `US`, regardless of the person's residential address. Provide `tax_identification_number`, and `tax_residence_country` if the identity document's country isn't already `US`.

<Heading level={2} id="identity_document_rejected">identity\_document\_rejected</Heading>

The identity document type provided isn't accepted for this submission. `ResidencePermit` is never accepted. Beneficiaries of US companies (except sole proprietorships) must use `Passport` or a US-issued `DriverLicense`, no other type. Resubmit with an accepted document type.

<Heading level={2} id="identity_document_images_identical">identity\_document\_images\_identical</Heading>

The front and back images submitted for an identity document are byte-identical, which almost always means the same image was uploaded twice by mistake. Capture and submit distinct front and back images.

<Heading level={2} id="structure_invalid">structure\_invalid</Heading>

The beneficiary or ownership structure on a `Business` submission violates a structural rule, for example: a sole proprietorship submitted with more than one beneficiary, or one that doesn't own 100%; a nested business beneficiary with no `Director`; or combined ownership percentages exceeding 100%. Check `message` for the specific rule and adjust the `company_data.beneficiaries` array.

<Heading level={2} id="attestation_invalid">attestation\_invalid</Heading>

The beneficial-ownership attestation is missing or invalid on a US `Business` submission. US companies, other than sole proprietorships, need exactly one root-level beneficiary with the `Director` role marked `attesting_party: true` and a past `attested_at` timestamp, certifying the submitted ownership information. Check `message` for the specific problem: a missing attesting party, more than one, or one without the `Director` role or not at the root.

<Heading level={2} id="cdd_certification_invalid">cdd\_certification\_invalid</Heading>

Iron generates a beneficial-ownership certification document for US `Business` submissions automatically, and the submitted data can't produce it. Common causes: no beneficiary owns 25% or more, a beneficiary is missing a required identity or tax number, or the submitted text can't be rendered into the document. Check `message` for the specific gap and provide the missing data.

<Heading level={2} id="business_description_insufficient">business\_description\_insufficient</Heading>

The company is classified under a "Miscellaneous" `industry_type`, which requires a more detailed `business_model_description` than other industries: at least two sentences. Expand the description and resubmit.

<Heading level={2} id="funds_flow_disclosure_required">funds\_flow\_disclosure\_required</Heading>

The questionnaire indicates the company sends funds on behalf of customers (`sends_funds_on_customer_behalf: true`), which requires supporting disclosure that wasn't fully provided. Include a description, a flow-of-funds diagram, and a source-of-funds document together.

<Heading level={2} id="license_details_required">license\_details\_required</Heading>

The questionnaire indicates the company holds licenses or registrations (`has_licenses_or_registrations: true`), which requires details that weren't provided. Provide `license_details`.

<Heading level={2} id="document_requirement_not_met">document\_requirement\_not\_met</Heading>

A required company document group is missing on a US `Business` submission. Unlike non-US businesses, which can be accepted with documents still missing and given a resume URL to complete later, a US submission is rejected outright when a required group is absent. Check `message` for which document category is missing, then resubmit with the complete document set. See [Company Documents](/kyb#company-documents).

<Heading level={2} id="proof_of_address_required_for_edd">proof\_of\_address\_required\_for\_edd</Heading>

A `Person` submission included `edd_questionnaire` without a proof-of-address document. Enhanced Due Diligence requires one. Include a `ProofOfAddress` document alongside the EDD questionnaire.

<Heading level={2} id="outsourcing_agreement_not_signed">outsourcing\_agreement\_not\_signed</Heading>

Your outsourcing agreement with Iron isn't signed yet, so data-carrying identifications can't be processed via the API for this customer type. This is an account configuration issue, not a data problem: contact your Iron partnership representative to get it signed.

<Heading level={2} id="duplicate_upload_blocked">duplicate\_upload\_blocked</Heading>

The verification provider temporarily blocked a duplicate upload of file content that's byte-identical to a very recent upload. This is transient: retry the same submission and it succeeds shortly after.

<Heading level={2} id="provider_rejected_document">provider\_rejected\_document</Heading>

The verification provider rejected a submitted document, for example because it was corrupted, too blurry to read, or the wrong type for the requested document category. Check `message` for the provider's specific rejection reason and resubmit with a corrected file.

<Heading level={2} id="reuse_rejected">reuse\_rejected</Heading>

A `Token` submission tried to reuse an existing verified identity via a share token, and the referenced identity isn't eligible for reuse: it isn't approved, its email doesn't match, or it fails an age restriction. Check `message` for the specific reason. The customer will most likely need to complete a fresh identification instead of reusing this one.
