Matching has already happened when the call returns
POST /v1/orders is not an acknowledgement. By the time you have a response, your
order has been matched against the book and the result is final. The status on that
response is what actually happened:
The six statuses
accepted needs the caveat: it is a transient state you will only ever see on a
read, while the durable record catches up. A create or amend response never returns
it. Without knowing that, a client that sees filled from a create and accepted
from a read a moment later concludes the two endpoints disagree — they do not; one is
ahead of the other.
Treat accepted and open identically in your own bookkeeping.
Filtering by status
GET /v1/orders?status= accepts group names as well as concrete statuses, and
combines them comma-separated (open,filled):
resting is the one a quoter wants each cycle: it is exactly the set of orders that
still have working quantity, and it includes accepted so an order does not vanish
from your view while the read side catches up.
Group names and status values deliberately share no ambiguous token. filled means
the same thing in both. resting is a group name only — no order’s status is
resting.
Budget orders: spend cash instead of counting shares
A create sized in cash instead of shares: sendbudget_cents instead of
qty — “spend $50.00 on yes” — with side: buy and time_in_force ioc or
fok. The engine sizes the order against the live book inside the match step,
fees included, so the budget is consumed exactly; there is no client-side
dollars-to-shares conversion to get wrong.
priceis a slippage bound, not a target. Fills execute at the resting prices, which may be better; nothing executes above your bound.- The response’s
qtyandfilled_qtyare the engine-derived executed size, andspent_centsis the exact realized cost — fill flow plus taker fees, cent for cent what left your balance.spent_cents / qtyis your realized average cost per share. - A budget order never rests.
fokfills the full affordable size or rejects422 budget_not_fillablewhen the book cannot absorb the budget within your bound;iocexecutes whatever is eligible and stops. The budget is also capped at your available cash — spending is bounded bymin(budget_cents, available_cents).
Idempotency, and why it matters more here
POST /v1/orders takes a client_order_id: 1–64 printable ASCII characters, yours
to choose, unique per user. Not globally unique — you never need to coordinate
with anyone else’s ids.
It does one job, and it is the important one: it makes a retry safe. Re-sending with
the same client_order_id returns the existing order instead of creating a second.
It is echoed on the create response and then not stored.
client_order_id does
not come back from GET /v1/orders or GET /v1/orders/{order_id}, so keep your own
client_order_id → order_id mapping. If you lose one, re-sending the identical
create returns the same order — which is also how you recover its order_id.503 result_unknown
— the command reached the matching engine but its outcome did not reach you.
Re-send with the same id, or poll the order. Never re-send with a fresh id. See
result_unknown; it is the paragraph most
worth reading twice before your bot goes live.
Amending and canceling
price, qty, or both; an omitted field keeps its current value
and a body with neither is 400. Any other field you send is ignored.
It takes no idempotency key — the order_id in the path already names one order.
That also means an amend has no dedup to fall back on, so if one returns
503 result_unknown, read the order back before deciding what to do rather than
re-amending blind.
Canceling an order that is already filled, canceled, or expired is
422 order_not_cancelable, not something to retry.
Your own orders will not trade with each other
If your incoming order would match your own resting order, neither trades. Both are reduced by the overlapping quantity, no fill is generated, and no trade prints. An order entirely consumed this way ends upcanceled.
This matters if you quote both sides: crossing your own quotes destroys them instead
of filling them. See
Matching.
After the fill
A fill moves shares and cash immediately. Then:GET /v1/portfolio/fills— your fill history. Each fill carriesoutcome_price(your price) andtrade_price(the tape’s). Reconcile cash againstoutcome_price; see Binary markets.GET /v1/portfolio/positions— what you hold, per outcome.GET /v1/portfolio/balance— cash, and how much of it is reserved against resting orders.