> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xo.market/llms.txt
> Use this file to discover all available pages before exploring further.

# Order types

> GTC, GTD, FOK, FAK — and how to express market orders on XO.

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`.

| `orderType` | Behavior                                                                                                                                                                              |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GTC`       | **Good-Till-Cancel.** Rests on the book until filled or cancelled. The default for resting liquidity.                                                                                 |
| `GTD`       | **Good-Till-Date.** Same as GTC but with a non-zero `expiration` (Unix seconds) in the signed order. A background sweeper cancels expired orders within \~10 seconds of the deadline. |
| `FAK`       | **Fill-And-Kill** (also called IOC — Immediate-Or-Cancel). Fills as much as the book supports at the signed price, then cancels any unfilled remainder. Never rests.                  |
| `FOK`       | **Fill-Or-Kill.** Fills the entire signed amount at the signed price or rejects with no fills. All-or-nothing.                                                                        |

## 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](/guides/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](/guides/fees).

## Status values on the response

`POST /order` returns a `PlaceOrderResponse` with a `status` field. The three values:

| `status`  | Meaning                                                                                                                                                                               |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `live`    | The order is resting on the book. GTC/GTD with no immediate match, or GTC/GTD with a partial match and remainder.                                                                     |
| `matched` | The order was fully filled. No remainder.                                                                                                                                             |
| `delayed` | The order was queued, an FOK could not fill at the signed price, or otherwise not yet matched. **Not `cancelled`** — XO does not emit a `cancelled` status on the placement response. |

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:

| `type`         | `status`   | Fires when                                                                                                                                                                             |
| -------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PLACEMENT`    | `LIVE`     | Order accepted onto the book (resting).                                                                                                                                                |
| `UPDATE`       | `LIVE`     | Resting order received a partial fill — `size_matched < original_size`.                                                                                                                |
| `UPDATE`       | `MATCHED`  | **Terminal.** Order fully consumed — `size_matched == original_size`. Fires for both a resting maker that was fully eaten, and a taker that fully filled on placement without resting. |
| `CANCELLATION` | `CANCELED` | Order cancelled (explicit, mass-cancel, GTD expiry, market lifecycle, or self-trade prevention).                                                                                       |
| `REJECTED`     | `REJECTED` | XO-only — order rejected pre-rest (rare).                                                                                                                                              |

### 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`).
