Errors

Every 4xx and 5xx response from the Yieldforce B2B API uses RFC 9457 application/problem+json. The code field is a stable, snake_case string you can branch on programmatically — HTTP status codes alone are not sufficient for error handling.

Format

Every error response has Content-Type: application/problem+json. If you receive a different content type on an error, something intercepted the request before it reached the API (a proxy, firewall, or load balancer).

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json
X-Yieldforce-Request-Id: req_01J8Z3K2V7BMQ...
X-Yieldforce-Api-Version: 1.0.0
 
{
  "type": "https://docs.yieldforce.io/errors/insufficient_balance",
  "title": "Insufficient balance",
  "status": 422,
  "detail": "Wallet 0xabc...12f has 42.15 USDC available; requested 100.00",
  "instance": "/v1/end_users/eu_01HX/portfolios/pf_01HY/withdrawals",
  "code": "insufficient_balance",
  "param": "amount",
  "request_id": "req_01J8Z3K2V7BMQ...",
  "doc_url": "https://docs.yieldforce.io/errors/insufficient_balance"
}

Fields

Response body

typestring (URI)required

Stable URL identifying the error class. Always resolves to human-readable documentation for this error.

titlestringrequired

Short human-readable label (5–8 words). Stable per code — safe to display to developers, not to end users.

statusnumberrequired

HTTP status code, mirroring the response status. Numeric.

detailstringrequired

Human-readable explanation specific to this instance, including dynamic context (amounts, IDs, wallet addresses). Do not parse this field programmatically — it may change. Use code instead.

instancestringrequired

URI path of the request that failed.

codestringrequired

Stable, snake_case, machine-readable identifier. Branch your error-handling logic on this field. Codes are never renamed or renumbered within a major API version.

paramstringoptional

Name of the request parameter that caused the error (Stripe convention). Present only when the error is field-specific (e.g., "param": "amount").

request_idstringrequired

Opaque request identifier. Include this in support tickets so the team can locate the request in logs.

doc_urlstringrequired

Link to the docs page for this specific error code.

Request ID for support

Every response — success or error — includes the X-Yieldforce-Request-Id response header. Its value matches request_id in error bodies. Always include it when opening a support ticket; it lets the team pull the full request trace immediately.

HTTP status code conventions

StatusWhen
400Malformed request — bad JSON, missing required field, malformed parameter
401Authentication failed — JWT invalid, expired, or signature mismatch
403Authenticated but caller lacks permission — wrong role, wrong tenant, inactive account
404Resource not found or belongs to a different tenant (no enumeration leak)
409Conflict — idempotency key in-flight, duplicate resource, version conflict
410Gone — cursor expired
422Semantically invalid — insufficient balance, invalid amount, bad address
429Rate limit exceeded
5xxServer error — safe to retry with exponential backoff

Error code catalog

Authentication — 401

CodeStatusMeaningCommon triggerFix
unauthenticated401No valid credentials foundMissing Authorization header or X-User-TokenAdd the required auth header
invalid_token401JWT failed signature / format validationMalformed token, wrong signing keyRe-fetch a fresh token; check your signing key
invalid_entra_token401Entra (M2M) token is invalidWrong audience, expired, bad signatureRe-fetch Entra token via client credentials grant
invalid_user_token401Partner-signed user JWT is invalidWrong RSA key, bad format, expired expReissue a fresh partner JWT

Authorization — 403

CodeStatusMeaningCommon triggerFix
unknown_partner403Tenant not found in the registryWrong Entra tenant ID in tokenVerify your Azure AD tenant is registered with Yieldforce
unknown_partner_issuer403JWKS issuer not recognizedPartner JWT issuer (iss) not in tenant configRegister your JWKS endpoint with Yieldforce
cross_tenant_jwt403JWT belongs to a different tenantUsing another tenant's token on your endpointEnsure you're using your own credentials
sub_url_mismatch403JWT sub does not match the end user in the URL pathEnd user ID in URL doesn't match the JWT subPass the correct end user ID matching the token
insufficient_role403Caller's role is not authorized for this actionWrong scope or role on Entra app registrationContact Yieldforce to check tenant role assignment

Idempotency — 409 / 422

CodeStatusMeaningCommon triggerFix
idempotency_key_required400Idempotency-Key header missing on a money-moving endpointForgot the header on deposit/withdrawAdd the header with a UUID v4 value
idempotency_key_in_progress409Same key is in-flight in an ongoing requestConcurrent duplicate requestWait for the original request to complete, then replay
idempotency_key_in_use_with_different_params422Same key, different request bodyReused a key for a logically different operationGenerate a new key for the new operation

Pagination — 400 / 410

CodeStatusMeaningCommon triggerFix
cursor_invalid400Cursor is malformed or tamperedManually constructing or modifying cursor stringsUse the next_cursor / prev_cursor values exactly as returned
cursor_expired410Cursor TTL (7 days) has elapsedStoring a cursor and using it weeks laterRe-fetch the first page to get a fresh cursor

End user / Portfolio — 400 / 404

CodeStatusMeaningCommon triggerFix
end_user_not_found404End user does not exist or belongs to another tenantWrong end_user_idVerify the ID or create the end user first
end_user_lookup_failed500Internal error resolving end userBackend / DB errorRetry; contact support if persistent
end_user_deleted400End user has been deletedAttempting to act on a deleted userDo not attempt further operations on deleted users
portfolio_not_found404Portfolio not foundWrong portfolio ID or wrong end userVerify both IDs
external_id_jwt_sub_mismatch400external_id in create-user body doesn't match JWT subPassing mismatched IDsEnsure external_id matches the sub in the user JWT

Tenant / Wallet configuration — 400 / 500

CodeStatusMeaningCommon triggerFix
tenant_privy_not_configured500Tenant wallet provisioning is not configuredMissing wallet setup in partner onboardingContact Yieldforce to complete tenant onboarding
privy_provisioning_failed500Wallet provisioning failed for a new end userWallet service error during user creationRetry; contact support if persistent

On-chain — 5xx

CodeStatusMeaningCommon triggerFix
chain_read_failed500Failed to read balance or state from the chainRPC node error or network outageRetry with backoff; check chain status