Underwriting Exceptions

The in-flight requirements and rejections underwriting surfaces on a business, how to read what's still needed, and the known rough edges to expect.

Some problems can't be judged at submit time; only underwriting can. These in-flight exceptions surface after creation, on each service's errors, missingFields, and missingDocuments, and through the business's status. This page covers reading and resolving them. For the errors PCE returns synchronously on a request (missing or malformed fields, broken KYB rules), see API Error Handling.

📘

Two kinds of failure

Submit-time problems come back synchronously on the request and are covered on API Error Handling. In-flight problems surface later on each service's errors, missingFields, and missingDocuments. See Status lifecycle.


What underwriting still needs

Onboarding has no separate "requirements" resource to poll. Each service object on the business carries three read-only fields that tell you exactly what's outstanding:

FieldMeaning
missingFieldsData the service still needs before it can go to underwriting.
missingDocumentsDocuments that must be bound before approval.
errorsValidation problems blocking the service.

Read them on the business and inspect services.payin.card. Empty arrays with status: PENDING_UNDERWRITING mean the service has everything it needs and is waiting on a decision; non-empty arrays tell you precisely what to fix or add. See Status lifecycle for how to read them and how status advances.


What underwriting reviews

Two kinds of check decide a business, and knowing which is which tells you what to do. Most requirement and format rules are applied the moment you submit or re-read the business: a missing control person, ownership totals that break the rule for the businessType, a missing MCC, or a cardMix that doesn't total 100% surface right away on errors, missingFields, and missingDocuments, and you can fix them yourself. Identity and risk checks (verifying the people, the business, and its documents) are worked by an underwriter, which is why a business can sit in PENDING_UNDERWRITING for a period even when its arrays are empty.

🚧

PENDING-PUBLISH

What sends a business to manual review versus clears it automatically, and whether there is an appeal path for a declined business, are underwriting-policy questions the boarding contract does not define. Confirm the manual-review triggers and the appeal or re-board path. (Open question, owner: product/underwriting.)


Common rejection reasons

Most rejections trace to a handful of causes. Each is reported against the part of the business that produced it, so you correct that part and resend:

  • No single control person. Exactly one owner or signatory must be marked as the control person; both zero and two fail.
  • Ownership totals break the rule for the business type. Partnerships need at least 50% combined beneficial ownership; government, non-profit, and 501(c)(3) businesses must have 0% beneficial ownership.
  • Wrong tax-ID type for the entity. Corporations, S-corporations, LLCs, LLPs, and partnerships must use an EIN.
  • Missing owner identification. Every owner and signatory needs a primary ID (SSN or ITIN) and a secondary government ID.
  • Duplicate owner. The same SSN cannot back more than one owner on a business.
  • Incomplete location processing profile. A location needs an industry MCC and a cardMix that totals 100%.

The rules behind these are owned on Business validation & KYB rules; the exact message each one returns is on API Error Handling.


Resolve and resubmit

To clear a rejection or an in-flight requirement:

  1. Read the business back with ?expand=true and inspect services.payin.card for errors, missingFields, and missingDocuments.
  2. Correct or add the flagged part on its own page: Owners & signatories, Bank accounts, Locations, or Documents.
  3. Read the business again to confirm the arrays cleared. When they do, the service returns to PENDING_UNDERWRITING.
  4. While you wait on the decision, re-read on a gentle cadence and apply exponential backoff between reads rather than tight-looping. See Tracking a business.

Known rough edges

Some messages are accurate but read as technical rather than customer-friendly, and a few behaviors are inconsistent. These are tracked for improvement; call them out to integrators so they aren't surprised.

🚧

PENDING-PUBLISH

The following are known message defects tracked for a fix; confirm status before publish and remove any that are resolved:

  • Stale "acquiring" wording (tracked with QA, remove on fix): some captured messages still read "for acquiring", but the service is now services.payin.card. These messages will be reworded to drop "acquiring" (and other internal or stale vocabulary) once QA ships the error-message fix. This is tracked with QA; when the fix lands, re-capture the messages and update the quoted strings on API Error Handling. Until then the strings are shown verbatim there because they are the current API behavior.
  • Internal linking fields in messages: some messages name individualId/externalId (internal linking fields) or reference an internal service (for example, a document-service UUID). Re-capture the exact messages and reword them before they reach a merchant-facing surface.
  • Circular messages: for example, email must be an email restates the field instead of showing a valid example.
  • Inconsistent auth/error shapes: Unauthorized (no code), Tenant claim missing from token, and framework-default Token expired are three different shapes for auth failures; the orchestration and domain layers also use different codes (MALFORMED_REQUEST vs MALFORMED_BODY, INTERNAL_ERROR for 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 PATCH and 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.


Next steps

See also



Did this page help you?
.readme-logo { display: none !important; }