Skip to main content
Branch your client on these stable values. The exchange reports failures two ways: non-2xx responses carry application/problem+json with a stable code (branch on code, not detail), and signed writes return 200 OK with a RequestAck body whose status can be a rejection. The Error Model covers the response shape and why a 200 is not proof of acceptance.

HTTP status codes

These statuses span every endpoint.
StatusMeaning to the callerRetry?
200 OKProcessed. May still be an application-level rejection — read the body.No (resubmit only if the body reports a retryable rejection)
204 No ContentSuccess, no body (e.g. device-key revoke, pairing write).No
400 Bad RequestMalformed payload, invalid request type, bad query parameters, or a request_id outside the skew window.No — fix the request first
401 UnauthorizedMissing credential, or signature/session verification failed.No — fix credentials/signature
404 Not FoundTarget does not exist or is not reachable by your credential.No
409 ConflictThe resource state blocks the operation (e.g. pairing already completed, portfolio close/reopen/name conflict).No
413 Payload Too LargeEncoded request exceeded the size cap. See Rate Limits.No — shrink the request
429 Too Many RequestsAccount exceeded its rate limit.Yes — back off and retry
500 Internal Server ErrorThe exchange hit an internal error.Maybe — retry with backoff
503 Service UnavailableThe exchange is briefly unavailable (at capacity, or the request was dropped before processing).Yes — back off and retry
504 TimeoutThe exchange did not confirm before the deadline. The write may or may not have been applied.Yes — reuse the same request_id
On 500, 503, or 504 you may not know whether a write was applied. Retry with the same request_id (it is the idempotency key). A re-applied request returns duplicate_request_id instead of executing twice.

ProblemDetails codes

These code values appear in the application/problem+json body on non-2xx responses.
codeStatusTrigger
invalid_signature401Signature verification failed, or the credential could not be resolved.
malformed_payload400Submitted payload is not well-formed.
invalid_request_type400Payload does not match the endpoint’s expected request type.
unsupported_request_type400Request type is not currently supported.
unsupported_content_type415Content-Type is neither application/json nor application/octet-stream.
request_timestamp_skew400The request_id’s embedded v7 timestamp is not current (too old or too far ahead).
invalid_portfolio_name400Portfolio name fails length/charset/reserved checks.
duplicate_portfolio_name409Portfolio name already in use.
portfolio_close_conflict409Portfolio cannot be closed (already closed, non-zero balance, open positions/orders).
portfolio_reopen_conflict409Portfolio cannot be reopened (already active, or unavailable).
pairing_already_completed409The device pairing has already been completed.
request_too_large413Encoded request payload exceeded the size cap.
rate_limited429Account exceeded its rate limit.
at_capacity503The exchange is at capacity. Retry.
request_dropped503The request was dropped before processing. Retry.
service_unavailable503The exchange is briefly unavailable. Retry.
retry_required503The request needs to be retried.
ack_failed500The exchange did not return a confirmation.
ack_timeout504The exchange did not confirm before the deadline.
request_timestamp_skew is the most common avoidable rejection. Generate a fresh UUIDv7 request_id at send time and keep your clock in sync.

RequestAck status values

Signed-write endpoints return 200 OK with a RequestAck body. status reports the outcome; processed_at_ns is the exchange processing time (nanoseconds since the Unix epoch).
{ "status": "request_completed", "processed_at_ns": 1719158400000000000 }

Accepted

statusMeaning
request_completedRequest applied.
duplicate_request_idThis request_id was already processed (idempotent replay). Safe — do not resubmit with a new id.
duplicate_request_id is the success signal for a safe retry. After a 504 or a network error on a write, resubmit with the same request_id: if the original was applied you get duplicate_request_id, otherwise it is processed once.

Transient (retry)

The request was not processed. Retry with the same request_id.
statusMeaning
request_droppedThe exchange was busy and dropped the request before processing.
retry_requiredThe request needs to be retried.

Order rejections

statusTrigger
order_rejected_invalidOrder failed validation.
order_rejected_expiredOrder expiry already passed.
order_rejected_internalInternal failure handling the order.
order_rejected_invalid_marketMarket reference is invalid.
rejected_invalid_portfolio_idPortfolio id does not resolve.
rejected_invalid_pricePrice failed validation.
rejected_invalid_sizeSize failed validation.
rejected_size_zeroSize is zero.
rejected_size_not_equalSize mismatch on an amend/replace.
rejected_order_not_foundTarget order does not exist.
rejected_invalid_order_flagsOrder flags combination is invalid.
rejected_invalid_uuidA referenced UUID is invalid.
rejected_max_open_orders_exceededAccount/portfolio is at its open-order cap.
rejected_post_only_would_cross_bookA post-only order would cross the book (it would take, not make).
invalid_reduce_only_orderReduce-only order does not reduce a position.

Market state

statusTrigger
market_closedMarket is closed.
rejected_market_not_foundMarket does not exist.
rejected_market_haltedMarket is halted.
rejected_market_reduce_onlyMarket accepts reduce-only orders only.
rejected_market_post_onlyMarket accepts post-only orders only.
rejected_market_cancel_onlyMarket accepts cancels only.
rejected_mark_price_zeroMark price is zero; order cannot be priced.

Margin and equity

statusTrigger
insufficient_margin_to_placeNot enough margin to place the order.
insufficient_margin_to_tradeNot enough margin to execute the trade.
rejected_insufficient_free_equityNot enough free equity.
rejected_f_o_k_not_fully_filled_insufficient_marginFill-or-kill could not fully fill due to margin.
rejected_f_o_k_not_fully_filled_low_liquidityFill-or-kill could not fully fill due to liquidity.
rejected_slippage_exceeds_maximumSlippage exceeded the allowed maximum.

Auth, account, and rate

statusTrigger
rejected_unauthorizedSigner is not authorized for the action.
rejected_account_suspendedAccount is suspended.
rejected_rate_limitedRejected at the exchange for rate reasons.
self_trade_preventionOrder would trade against your own resting order; STP blocked it.
rejected_self_transferTransfer source and destination are the same.

Conditional orders

These statuses are reserved and will not occur today: conditional order types (stop / take-profit) are not yet available over the REST API, and self-trade-prevention flags are accepted but not yet enforced.
statusTrigger
rejected_max_conditional_orders_exceededAt the conditional-order cap.
rejected_trigger_already_satisfiedTrigger condition is already met.
rejected_conditional_order_expiredConditional order already expired.
rejected_invalid_triggerTrigger parameters are invalid.
conditional_order_on_booksConditional order is resting.
conditional_order_not_foundConditional order does not exist.

Master keys

statusTrigger
master_key_addedMaster key added.
master_key_removedMaster key removed.
master_key_rejected_invalidMaster key is invalid.
master_key_rejected_unauthorizedSigner not authorized to manage this key.
master_key_rejected_self_removalA key cannot remove itself.
master_key_rejected_last_keyCannot remove the last remaining admin key.

Sessions

statusTrigger
session_createdSession created.
session_revokedSession revoked.
session_rejectedSession request rejected (e.g. unknown master key, invalid scope).
session_rejected_max_sessionsAt the session cap.

Account creation

statusTrigger
account_created_with_sessionAccount and initial session created.
account_created_session_failedAccount created, but session registration failed (partial success).
creation_rejectedAccount creation rejected.
Account, master-key, and session endpoints may instead return their own response object with a success boolean (and, for account creation, session_created). Read the body there too — see Error Model.