For the complete documentation index, see llms.txt. This page is also available as Markdown.

Errors

Every failed request returns the same envelope. Handle errors by branching on success and the HTTP status — not by string-matching messages.

{
  "success": false,
  "statusMessage": "Insufficient free balance for this order",
  "error": { "code": "400", "message": "Insufficient free balance for this order" },
  "httpStatusCode": 400
}
Field
Meaning

success

Always false on error — branch on this first.

error.code

String status code, mirrors the HTTP status.

error.message / statusMessage

Human-readable — for logs, not for control flow.

httpStatusCode

Numeric HTTP status, echoed in the body.

Validation errors are 400, often with several issues joined into one message.

Status codes

Status
Meaning
What to do

200

Success (read/action)

Read data.

201

Write accepted

Read data.tempId, then poll.

400

Invalid input / failed rule (e.g. insufficient balance)

Fix the request; don't retry unchanged.

401

Not authenticated

Refresh credentials.

403

Not permitted (missing delegated permission)

Delegate the permission.

404

Resource not found

Check the id / path.

429

Throttled

Back off and retry.

500 / 503

Server / dependency error

Retry with backoff.

Two kinds of failure

Because trades are asynchronous, a trade can fail at two moments:

  1. Request-time (synchronous) — auth, validation, and permission errors come back immediately as a 4xx. The trade never started.

  2. Execution-time (asynchronous) — a trade that was accepted (201 + tempId) can still fail later (solver rejects, order expires, on-chain revert). This surfaces in the status endpoint as a FAILED status, not as an HTTP error on the original call.

A 201 means "accepted for processing," not "filled." Always confirm the terminal state via the matching .../status endpoint. See How trading works.

Retries & rate limits

Specific rate limits aren't published — build as if limits exist and may change.

  • 4xx (except 429) are your bug — fix before retrying; don't hammer them.

  • 429 and 5xx are transient — retry with exponential backoff + jitter.

  • Cap concurrency per key; poll status ~1s apart and stop on a terminal state.

  • For accepted trades that then fail, reconcile with GET /v1/positions/all before resubmitting, so you don't double-open a position that actually filled.