Skip to main content
A business that can already pay domestically cannot necessarily pay internationally. The currency provider has to know who it is dealing with, which means two things beyond ordinary entity creation: a completed business profile, and the people behind the business recorded as beneficial owners. The gate is enforced when you create an international receiving account — POST /accounts with type: international-fx or international-gusd returns 409 ENTITY_ONBOARDING_INCOMPLETE while anything is outstanding — and reported continuously by GET /limitations on payment.international:write.

What is checked

The same dot-paths appear in the 409’s details[].validationErrors[].field and in a limitation’s missingFields, so one mapping in your integration covers both.

Beneficial owners

Read the current set with GET /v2/entities/{entityId}/beneficial-owners, and write it with PUT /v2/entities/{entityId}/beneficial-owners. The PUT replaces the whole set. Entries carrying an id are updated, entries without one are created, and anyone the payload omits is deleted. That is deliberate: ownership percentages are only meaningful as a set — the provider validates their total — so a partial update has no coherent meaning. Read the set, modify it, send it back whole.

The three roles

One person usually holds several roles; the example above is all three. The rules the API enforces:
  • Exactly one fx-account-holder — and its absence is what keeps payment.international:write blocked. More than one is 400.
  • At most one director. A set still being assembled may have none; the missing-director case is reported by GET /limitations rather than by rejecting the write.
  • A ubo must hold at least 0.25 (25%) and carry ownershipPercentage. Anyone below that is not a beneficial owner — give them the director type instead.
  • At most four ubo entries, and their ownershipPercentage values may not total more than 1. Both are checked here rather than left to the provider, whose own error does not say which entry or total was at fault.
  • At most 20 people in one request. firstName/lastName are at least 2 characters, and dateOfBirth must put the person between 18 and 120 years old.

Identification depends on residency

  • usResident: true → taxInfo with an ssn or itin (9 digits, dashes optional).
  • usResident: false → internationalIdType (passport, driver-license or national-id) and internationalId.
Nothing is echoed back in full. GET returns taxInfo.identifierLast4, the last four characters of internationalId, and a hasIdentityDocument boolean — never the document itself.

When an identity document is required

Recording the numbers is not always enough: the provider sometimes wants to see the ID. There are exactly two cases, and both are rejected with 400 VALIDATION_ERROR naming the person, so you never discover them from a failed payment later:
  1. Any non-US resident among the people you record.
  2. Every beneficial owner — including US residents — when the entity’s businessType is sole-proprietorship.
Upload the scan with POST /attachments and reference it on the person:
Only the front is required. The provider’s guidance asks for both sides of a driver’s licence or national ID, and you should send backAttachmentId when you have it, but a front-only upload is accepted. The two ids must differ. The attachment must belong to the same entity as the person — an id from another entity is a 404. Documents are handed to compliance as part of the write: if that hand-off fails the whole request fails with 503 COMPLIANCE_UPLOAD_FAILED and nothing is saved, so a retry is safe and a person can never be left on file claiming a document that was never delivered.

Putting it together

If GET /limitations still reports a reason after that, read its code: MissingInformation lists what to send, while LocationRestricted, AccountBlocked and AccountUnderReview are not something more data will fix — contactEmail, when present, is where to take it.

See also