Skip to main content
Every error, at every HTTP status, has the same shape. Use code in your program logic, the HTTP status as the fallback, and message only for logs.

The error envelope

The envelope is used for unknown paths (404 NotFound), wrong methods (405 MethodNotAllowed) and stream connections refused before the WebSocket upgrade, as well as for every operation’s own errors.

Error codes

For your own retries, use exponential backoff with jitter and a cap, and stop after a bounded number of attempts.

Tolerate new codes

New codes can be added without a new API version. Handle a code you do not recognise by its HTTP status: a 4xx means the request needs to change, a 5xx means the outcome of a command is unknown.
The specification declares ErrorCode as a closed enum. If you generate a client, make sure an unknown value decodes to a fallback instead of failing; otherwise a new code turns a clear error into a parsing failure.

400 or 422

The two statuses separate a malformed request from a request the host will not carry out:
  • 400 InvalidRequest: the request does not match the schema. Examples: a misspelt field such as clientOrderID, an unknown enum value such as "types": ["Swap"], an unknown type variant, a lowercase asset, a decimal sent as a number, or a cursor from another query. The server rejects unknown request fields, even though responses can gain fields.
  • 422: the request is well formed, but the host, the market or Plurex’s validation will not accept it: an unsupported operation (NotSupported), a value that breaks the order rules (Rejected), too little balance (InsufficientFunds), bad exchange credentials (InvalidProviderCredentials) or a limit (AccountLimit).

Order of checks

Operations that need an API key check authentication before they read the body. A request with missing or invalid credentials gets 401 Unauthenticated even if its body is also invalid, so fix credentials first. Public operations have no authentication step.

Retries by operation

An error or timeout does not prove that a command had no effect. Queries (.../query/...) only read, so they are always safe to repeat. Commands follow these rules: The API has no idempotency keys. A clientOrderId correlates an order with your own records and lets you look it up or cancel it; it is not a transport retry key.

Reconciliation rules

When an outcome is unclear, read the state back before acting again:
  • Not found is never success. OrderNotFound can mean the order never existed, the host has forgotten a closed order, or the order is not visible yet. Check with GetOrder or ListOpenOrders, and allow time before concluding it does not exist.
  • Already closed is not cancelled. OrderAlreadyClosed means the order finished, possibly by filling. Read it to find out.
  • An acknowledgement is not a final state. A cancel Ack or a Cancelled batch result means the host accepted the cancel. Confirm with GetOrder or the order stream.
  • Read the right source for each question. Final order state: GetOrder or the order stream. What is still working: ListOpenOrders. Executions: ListFills. Balance postings: ListTransactions. Accounts: accounts/query/List.
  • After a stream disconnect, reconnect and read the REST state again; streams do not replay missed events.