Skip to main content

client_order_id is the contract

You supply client_order_id on every order. It must be unique per order and is the idempotency key for the whole placement path. The rule that matters: on any failure where you are unsure, retry with the same client_order_id. At most one order ever results. Retrying with a new id after a timeout is how duplicate orders happen.

Order states

Filter values → what you get

GET /v1/portfolio/orders?status= takes a comma-separated list of the names above. Common patterns: Terminal rows (executed / canceled / expired / rejects) can disappear from the live list once terminal_cap / reject_cap are hit. Resting rows never evict.

Cancellations arrive as success

A 201 does not mean your order is on the book.Post-only orders that would have crossed, unfillable fok orders, ioc remainders, self-trade prevention, and market buys that would breach max_cost all return a successful response with status: "canceled" and a reason.They are execution outcomes, not errors. Always read status on a success response instead of assuming placement succeeded.

Placement responses are real outcomes

The API holds your request until the order is sequenced, so the response describes what actually happened - filled_qty, resting_qty, and a fills array in stream order. There is no separate “pending” state to poll through. seq on the response is the sequencer stamp, which is your audit join back to canonical history.

Balances are not in the response

Reservation and fee accounting are deliberately absent from placement responses
  • they arrive on a different lane. Get them from GET /v1/portfolio/balance or, better, the user WebSocket channel.

Reading your orders

status takes a comma-separated list. Querying by client_order_id is how you resolve a timeout.

Cancelling

Cancels charge the cancel bucket (2 × write rate), not the write bucket. Places, decrease, and dead-man stay on write. For queue depth before a reprice, call GET …/queue_position. See Rate limits.

Batching

POST /v1/portfolio/orders/batch places several orders in one request, and DELETE /v1/portfolio/orders/batch cancels up to 20 by id. Cost is 1 token per HTTP request, not per item, so a 20-order batch spends one write (place) or one cancel (cancel-batch) token. Exceeding 20 items is 400 batch_too_large and nothing fires.

Direction

Orders are side × outcome × tick in the outcome’s own price space, see Order direction.