Skip to main content
XO accepts four signed order types. There is no separate MARKET value — market-style execution is built on top of FAK or FOK.

Time-in-force values

Pass one of these as orderType on POST /order.

Market-style execution

There’s no MARKET enum value. To execute “at the market,” sign a CTFOrder at an aggressive cap price and choose FAK or FOK:
  • BUY market: sign at price 0.99 (or your preferred cap), sized to your budget.
  • SELL market: sign at price 0.001, sized to your position.
Then pick:
  • FAK — fill as deep as the book goes at your cap, cancel the rest. Use this for “take whatever liquidity is available.”
  • FOK — fill the full size or nothing. Use this for “I need exactly this much done at my cap or skip the trade.”
The matching engine walks Complementary → MINT → MERGE on the same order, so a cap-priced order will also match against one-sided books that only have liquidity on the opposite outcome. Marketable orders are held briefly before matching — see Taker delay (500 ms by default; 3 s on sports markets during match time). Fills that take liquidity are charged the taker fee; resting liquidity uses the maker rate — see Fees.

Status values on the response

POST /order returns a PlaceOrderResponse with a status field. The three values: A success: false response with status: "delayed" and an errorMsg populated is the wire shape for “FOK rejected, no fills.” The HTTP status is still 200.

WebSocket lifecycle frames

On /ws/user, every order emits typed lifecycle frames:

Recognising a full fill in-band

The order/UPDATE frame fires twice for any order that ends up fully consumed:
  1. Once per partial step with status=LIVE and size_matched < original_size.
  2. A terminal frame with status=MATCHED and size_matched == original_size.
A maker bot can close out its PLACEMENT view on either signal — the size equality or the status transition to MATCHED. The terminal MATCHED frame is the preferred path for new consumers — it works deterministically across COMPLEMENTARY, MINT, and MERGE matches without polling REST.

Correlating trades to order updates

Each MATCHED order/UPDATE frame has a matching trade event with status: "MATCHED". Join on trade.maker_order_id == order.id — this works deterministically across all match types without needing per-market FIFO heuristics. Both the maker and the taker receive their own copy of the trade frame on their respective /ws/user connections, each with their own trader_side (MAKER or TAKER).