Error Handling
How onboarding reports validation and request errors, the common KYB rejection messages, and how to resolve them.
Onboarding validates the whole entity graph atomically at create time. If any check fails, the request returns an error and no business is created — fix the reported problem and resend. This page lists the error shapes and the most common validation messages, grouped by the resource that produces them.
Two kinds of failureSubmit-time problems (missing or malformed fields, broken KYB rules) come back synchronously on the request. In-flight problems (things only underwriting can judge) surface later on each service's
errors,missingFields, andmissingDocuments— see Onboarding statuses.
Error shapes
Field validation errors identify the offending field, a code, and a message:
{ "field": "legalName", "code": "REQUIRED", "message": "legalName is required" }Multiple validation failures are collected under a VALIDATION_FAILED envelope:
{
"errorCode": "VALIDATION_FAILED",
"message": "Validation failed",
"errors": [
{ "field": "addresses.0.type", "code": "INVALID_ENUM",
"message": "addresses.0.type must be one of the following: registered, mailing, physical, headquarters, home, work" }
]
}KYB/business-rule failures return a mandatory-level message tied to a fieldPath:
{
"level": "mandatory",
"message": "Exactly one owner or signatory must be marked as the Control Person.",
"fieldPath": "owners"
}
PENDING-PUBLISHThe onboarding surface currently returns more than one error envelope shape (field-level
{ field, code, message }, aVALIDATION_FAILEDwrapper, and amandatory/fieldPathKYB shape), and some lower-level responses differ again. Confirm the canonical error contract with engineering and document a single shape here before publish; until then these examples mirror observed responses.
Business and identity
| Situation | Message |
|---|---|
legalName missing | legalName is required |
legalName over 255 chars | legalName must be shorter than or equal to 255 characters |
businessDescription over 512 chars | businessDescription must be shorter than or equal to 512 characters |
Invalid email | email must be an email |
itin value not a valid 9-digit ITIN | taxIds.0.value must be a valid 9-digit ITIN beginning with 9 (e.g. 9XX-XX-XXXX) |
| EIN required for entity type | Tax ID type must be EIN for corporations, S-corporations, LLCs, LLPs and partnerships. |
Owners, signatories, and control person
| Situation | Message |
|---|---|
| No control person | Exactly one owner or signatory must be marked as the Control Person. |
| Non-profit/government with ownership > 0 | Beneficial-owner ownership must be 0 for government, non-profit and 501(c)(3) tax exempt. |
| Partnership total ownership < 50% | Total beneficial-owner ownership must be at least 50% for partnerships. |
| Owner missing SSN | Every signatory (control person, owner and guarantor) requires a primary identification (SSN) for acquiring. |
| Owner missing government ID | Every signatory (control person, owner and guarantor) requires a secondary identification (government id) for acquiring. |
| Duplicate owner SSN | Duplicate owner detected. The same SSN cannot be used for more than one owner. |
ownershipPercentage with 3 decimals | ownershipPercentage must be a non-negative amount with at most 2 decimal places |
Locations and processing
| Situation | Message |
|---|---|
| Missing MCC | An industry MCC code is required for acquiring. |
| Missing industry category/description | An industry category or description is required for acquiring. |
cardMix not totaling 100% | MOTO, eCommerce and card-present percentages are required and must total 100% for acquiring. |
| High MOTO+eCom volume without required details | When MOTO + eCommerce volume exceeds 20%, internet business type, marketing method and the monthly/onetime/yearly billing cadence are required for acquiring. |
Invalid address type | addresses.0.type must be one of the following: registered, mailing, physical, headquarters, home, work |
| Invalid postal code | addresses.0.postalCode must be a valid postal code |
Bank accounts
| Situation | Message |
|---|---|
| Invalid routing number | bankAccounts.0.routingNumber must be a valid 9-digit routing number |
Invalid accountType | accountType must be one of: checking, savings |
Duplicate externalId across accounts | Duplicate externalId '…' provided for multiple bank accounts in the same request |
Request-level errors
| HTTP | Situation | Response |
|---|---|---|
400 | Non-JSON body with JSON content-type | Body is not valid JSON but content-type is set to 'application/json' |
400 | Empty body | Body cannot be empty when content-type is set to 'application/json' |
401 | Missing/invalid credential | Unauthorized |
404 | Business not found | Entity not found: … |
409 | Conflicting externalId | Duplicate externalId provided |
422 | Unknown query parameter | property … should not exist |
422 | limit out of range | limit must be an integer between 1 and 250 |
Reading a record and writing it backA
GETreturns masked, read-only fields (lastFour,accountNumberLast4) and computed fields the write endpoints don't accept. Don'tPATCHa record back unmodified — send only the fields you're changing, or the write is rejected for containing read-only properties.
Known rough edges
Some current messages are accurate but not yet customer-friendly, and a few behaviors are inconsistent. These are tracked for improvement; call them out to integrators so they aren't surprised.
PENDING-PUBLISHThe following are documented as known issues pending engineering fixes; confirm status before publish and remove any that are resolved:
- Internal vocabulary in messages — some errors say "for acquiring", name
individualId/externalId(internal linking fields), or reference internal services (e.g. a document-service UUID). These should be reworded before they reach a merchant-facing surface.- Circular messages — e.g.
email must be an emailrestates the field instead of showing a valid example.- Inconsistent auth/error shapes —
Unauthorized(no code),Tenant claim missing from token, and framework-defaultToken expiredare three different shapes for auth failures; the orchestration and domain layers also use different codes (MALFORMED_REQUESTvsMALFORMED_BODY,INTERNAL_ERRORfor a 403).- Silent gaps — going to two control persons is blocked, but going to zero is silently allowed; a personal (owner) address and an SSN can be changed with a plain
PATCHand no re-verification, while a primary location can't be changed after creation at all.See the internal error-scenarios catalog for the full list and per-message rationale.
See also
- Onboarding statuses: in-flight
errors,missingFields, andmissingDocuments - Key concepts: the KYB rules behind these messages
- Create a business: validation performed at create time
Updated about 3 hours ago