Error handling
Every non-2xx response uses the same envelope. Key on code (stable); never
parse message (human-readable, may change).
{
"error": "Bad Request",
"code": "validation_failed",
"message": "Request body failed validation",
"details": {
"formErrors": [],
"fieldErrors": { "user_email": ["Invalid email"] }
}
}
The fields: error is the HTTP-status label (e.g. "Bad Request") and is
informational only; code is the stable machine-readable value to branch on; message is
human-readable and may change. details appears only on validation_failed and
contains a flattened list of field errors.
Codes by category
| HTTP | code | When |
|---|---|---|
| 401 | auth_missing, auth_invalid_format, auth_unknown_partner, auth_revoked, auth_bad_secret | Authentication (see Authentication). |
| 403 | auth_partner_not_approved | Your account is still pending approval; no endpoint works yet. |
| 400 | validation_failed | Body failed schema validation (see details). |
| 400 | invalid_json | Body was not valid JSON. |
| 400 | body_required | No JSON body (missing, or Content-Type not application/json). |
| 400 | document_path_invalid | A document_refs path is not under the entity+claim prefix. |
| 400 | document_not_uploaded | A referenced file does not exist in storage yet. |
| 403 | entity_not_owned | You have no connection to that entity. |
| 403 | partner_disconnected | The entity disconnected you (writes blocked; listing still works). |
| 404 | entity_not_found | No such entity. |
| 409 | claim_conflict | Internal claim-id collision (rare). Retry the identical request. |
| 409 | connect_token_already_redeemed, entity_already_linked | Connect-flow conflicts (surfaced during user approval). |
| 400 | connect_token_invalid, connect_token_expired | Connect-flow token problems (surfaced during user approval). |
| 422 | onboarding_unavailable | Onboarding cannot complete automatically. Use POST /connect-requests instead. |
| 429 | rate_limited | Rate limit exceeded (see Rate limits). |
| 500 | internal_error | Unexpected server error. |
| 503 | service_unavailable | A dependency is briefly unavailable. Retry after Retry-After. |
| 503 | document_verification_failed | Storage check on an uploaded document failed transiently. Retry. |
Retry guidance
- Retry on
429(afterRetry-After),500(internal_error),503(service_unavailable/document_verification_failed, afterRetry-Afterwhere given), and the internal-id409(claim_conflict). Use exponential backoff with jitter. - Always reuse the same
partner_user_id/partner_claim_idon retries so the idempotency guarantees apply and you don't double-create. - Do not blindly retry
400/401/403/404/422. They are deterministic and need a corrected request or a different flow (e.g.onboarding_unavailable→POST /connect-requests).