Error Codes
Errors return a JSON body with a message and, where applicable, a code and errorType.
HTTP Status Codes
| Status | When |
|---|---|
| 400 | Invalid request body (schema validation) or a rejected order (e.g. slippage changed between quote and submit on a cross-chain order) |
| 401 | Invalid or missing API key/signature |
| 403 | Access denied or invalid organization ID |
| 408 | Timestamp is too old (>2 minutes) |
| 413 | Request body larger than 1 MB |
| 422 | Request understood but not currently executable (e.g. trading vault still initializing) |
| 429 | Rate limited |
| 500 | Unexpected server error |
Cross-Chain Errors
Cross-chain 4xx responses forward the backend's message verbatim so the reason is actionable.
| Status | errorType | Meaning | What to do |
|---|---|---|---|
| 400 | — | slippageTolerance changed between quote and submit inside the 60s bridge-quote window | Submit with the same slippageTolerance used at quote time, or re-quote |
| 422 | ERROR_TYPE_VAULT_NOT_READY | A trading vault on one of the two chains is still initializing | Retry shortly — quoting auto-provisions missing vaults |
Note: contraChain is only read on market orders. On any other order type the field is ignored rather than rejected — see Cross-Chain Market Order.
Perps Errors
Perps 4xx responses carry a message; 422 responses add a typed errorType when the perps backend classifies the failure.
| Status | errorType | Meaning | What to do |
|---|---|---|---|
| 400 | — | Invalid parameters, an unknown market symbol, or an ambiguous bare symbol (two subvenues list the same base) | Check List Markets; qualify the symbol as subvenue:SYMBOL, e.g. native:BTC |
| 403 | — | Organization API: the portfolio belongs to another organization; or a READ-scoped key called a POST endpoint (/perps/orders/preview, /perps/withdraw..., /perps/deposit/...) | Use a portfolio of your organization / a WRITE-scoped key |
| 404 | — | Organization API: portfolioId not found | Check the portfolio id |
| 422 | PERPS_ACCOUNT_NOT_CONFIGURED | The portfolio has no perps account | Check Account Status; set up in the app |
| 422 | ACCOUNT_NOT_SETUP | The perps account exists but is not yet set up at the venue | Check Account Status; finish setup in the app |
| 422 | WITHDRAW_DESTINATION_NOT_ALLOWED | destination is not one of the portfolio's Arbitrum trading vaults | Omit destination, or pass one of the portfolio's Arbitrum trading vault addresses — see Withdraw |
| 422 | WITHDRAW_DESTINATION_UNAVAILABLE | The portfolio has no Arbitrum trading vault to receive the withdrawal | Create an Arbitrum trading vault for the portfolio in the app |
| 422 | WITHDRAW_INSUFFICIENT_BALANCE, WITHDRAW_SIGNATURE_INVALID, WITHDRAW_NONCE_INVALID, WITHDRAW_REJECTED | The venue rejected the signed withdrawal (best-effort classification) | See Withdraw errors; request a fresh payload, sign it exactly as returned, resubmit |
| 429 | — | Perps rate limit (20 requests/second per key, on top of the standard per-key limit), or the venue rate-limited the request | Back off and retry |
| 503 | — | Perps account data not enabled on this deployment, or the venue is temporarily unavailable | Retry later; market-data endpoints remain available |
Perps deposits
The deposit endpoints are served by the transfers backend rather than the perps service, so they do not use the perps error shape: there is no errorType, and a destination without a perps account is a 404 here where the read endpoints return 422 PERPS_ACCOUNT_NOT_CONFIGURED. Read the status code rather than the body — a rejected key returns { "error": ... }, a malformed body returns a validation object, and an error relayed from the backend returns { "message": "Internal server error", "details": ... } with the cause in details.
| Status | Meaning | What to do |
|---|---|---|
| 400 | Invalid body, or fromAssetAddress is not a recognized asset on the source vault's chain | Check the address against the source vault's chain |
| 401 | The source vault does not belong to the portfolio, or the destination portfolio belongs to another organization | Use a source vault of the portfolio and a destination portfolio of your own organization |
| 403 | READ-scoped key, or Organization API: the portfolio belongs to another organization (both rejected before the request reaches the transfers backend) | Use a WRITE-scoped key / a portfolio of your organization |
| 404 | Source vault not found, destination portfolio not found, or the destination portfolio has no perps account; Organization API: portfolioId not found | Check the ids, and Account Status for the destination |
| 429 | Perps rate limit (20 requests/second per key) | Back off and retry |