> For the complete documentation index, see [llms.txt](https://docs.reya.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.reya.xyz/developers/devnet/order-entry/order-lifecycle.md).

# Order Lifecycle

The states an order moves through, and the two time controls that govern it.

## The path of an order

1. **Signed.** You sign the `OrderDetails` (see [Signatures & Nonces](/developers/devnet/authentication/signatures-and-nonces.md)) and submit over [REST](/developers/devnet/api-reference/rest-api-reference.md) or [WS Order Entry](/developers/devnet/api-reference/ws-exec-api-reference.md).
2. **Accepted by the matching engine** — validated, with [pre-trade risk checks](/developers/devnet/risk/margin-system.md#pre-trade-risk-checks) before fills are committed:
   * **IOC** fills what it can immediately and cancels the remainder. It never rests on the book, but the matching engine still issues an order ID for it.
   * **GTC** rests on the book (with an order ID) until it fills or you cancel it.
   * **GTT** rests like GTC, but it is automatically cancelled once its signed `expiresAfter` timestamp passes — emitting a `CANCELLED` orderChange. You can refresh a resting GTT's `expiresAfter` with [`modifyOrder`](#modifying-a-resting-order) instead of letting it expire.
   * **Trigger (`STOP_LOSS` / `TAKE_PROFIT`)** — durably armed outside the book, then fired against the mark price into the chosen IOC/GTC/GTT child. Only the armed phase is modifiable. A user `cancelAll` clears both armed triggers and fired children; Cancel-on-Disconnect preserves both. Full contract: [Trigger Orders (SL/TP)](/developers/devnet/order-entry/trigger-orders.md).
3. **Terminal.** The order reaches `FILLED` or `CANCELLED`, and any fills proceed to on-chain settlement (see [Trade Settlement](/developers/devnet/executions-and-settlement/settlement.md)).

Status transitions surface on the [`orderChanges`](/developers/devnet/api-reference/websocket-api-reference.md) channel (`OPEN` → `FILLED` / `CANCELLED`) — but remember these are **matching-engine-level** signals. Request errors are returned as errors, not order-status updates. Settled fills are confirmed only on the executions channel; see [Executions & Trade History](/developers/devnet/executions-and-settlement/executions-and-trade-history.md) and [Trade Busts](/developers/devnet/executions-and-settlement/trade-busts.md).

## `deadline` vs `expiresAfter`

Two independent time fields, both signed:

| Field          | Governs                                            | Enforced                                    |
| -------------- | -------------------------------------------------- | ------------------------------------------- |
| `deadline`     | How long the **signed request** is valid for entry | At submission                               |
| `expiresAfter` | When a resting **GTT** order auto-expires          | While the order is active and at settlement |

Both are Unix-second timestamps. `deadline` is required on every order; `expiresAfter` carries a lifetime only for **GTT** orders (where it must be strictly greater than `deadline`) and is omitted for GTC and IOC, including triggers with those TIFs. Once `expiresAfter` passes, the GTT is automatically cancelled with a `CANCELLED` orderChange. A GTT trigger and its fired child instead share an immutable expiry and stop early to allow time for settlement; see [Trigger Orders (SL/TP)](/developers/devnet/order-entry/trigger-orders.md#choosing-the-fired-childs-time-in-force). See [Signatures & Nonces](/developers/devnet/authentication/signatures-and-nonces.md) for the encoding.

## Cancel-on-Disconnect (`cancelAllAfter`)

Cancel-on-Disconnect is an **account-scoped dead-man's switch** driven by `cancelAllAfter`. You arm a countdown; if you don't refresh it before it elapses, the matching engine cancels **every** open order on the account — across all markets, spot and perp — **except** protective stops (`STOP_LOSS` / `TAKE_PROFIT`), which it deliberately keeps. A WebSocket close neither fires nor disarms it — only the countdown elapsing does. See [Cancel-on-Disconnect](/developers/devnet/order-entry/cancel-on-disconnect.md) for bounds, request fields, signing, and error codes.

## Modifying a resting order

The trigger Boolean omission rules below are live in API **3.5.2** as of September 14, 2026; see the [changelog](/developers/devnet/changelog/changelog.md#log) for the matching SDK versions.

`modifyOrder` (REST `POST /v2/modifyOrder`, or the `modifyOrder` WebSocket Order Entry message) amends **one** order **in place** — a resting `LIMIT` (`GTC` or `GTT`, spot or perp) or an **armed `STOP_LOSS` / `TAKE_PROFIT` trigger**. The order **keeps** its `orderId` and `clientOrderId`.

* **Full restate.** The request carries the complete post-modify `OrderDetails` state plus a target id — you restate **every** value, even unchanged ones; omission never inherits from the resting order. It uses the same signed EIP-712 field universe as `createOrder`, but its JSON fields are class-specific: trigger create and modify require `timeInForce` and omit `reduceOnly` and `postOnly`, including `false`. Both Boolean fields are reconstructed as fixed `false` for signing and verification; they are never inherited from stored state. The modifiable set is **class-split**:
  * **`LIMIT`** — `limitPx`, `qty`, `postOnly`, `expiresAfter` (`triggerPx` is forbidden):
    * `qty` is the **total** post-modify order quantity and must exceed `cumQty` (else `MODIFY_QTY_BELOW_FILLED_ERROR`).
    * `expiresAfter` — GTC omits it; GTT must carry a future value greater than `deadline`.
  * **`STOP_LOSS` / `TAKE_PROFIT`** — **only `limitPx` and `triggerPx`**: `triggerPx` re-prices the armed trigger in place (no cancel-and-recreate) and is **required**; `qty` stays **omitted**, both Boolean flags stay omitted, and the originally chosen TIF and original expiry (present only for GTT) are restated immutables. A fired child is cancel-only. See [Trigger Orders (SL/TP)](/developers/devnet/order-entry/trigger-orders.md#re-pricing-modify).
* **Immutables must be restated to match.** The remaining `OrderDetails` fields — `isBuy` / side, `exchangeId`, `orderType`, `timeInForce`, `reduceOnly` (LIMIT only; triggers omit it), `clientOrderId`, `accountId`, `signerWallet` — are **immutable**: restate them at the resting order's values. A mismatch is rejected with `INPUT_VALIDATION_ERROR`. `timeInForce` is immutable — you cannot switch GTC ↔ GTT via modify; `orderType` is immutable — a modify re-prices a trigger but never converts between `LIMIT` and `STOP_LOSS` / `TAKE_PROFIT`.
* **Target** by `orderId` when present, otherwise by a non-zero `clientOrderId`. The same `clientOrderId` field restates the resting order's immutable client id for signing. If both identifiers are supplied, `orderId` is canonical for lookup and `clientOrderId` is the restated immutable. If the resting order has no client id, omit `clientOrderId`; do not send a placeholder value. Supplying neither is rejected with `INPUT_VALIDATION_ERROR`.
* **Crossing.** For a LIMIT order, a non-post-only modify whose new `limitPx` crosses executes **immediately** and settles like a crossing create. A **post-only** modify that would cross is rejected with `POST_ONLY_WOULD_CROSS_ERROR` and the resting order is left untouched.
* **Signing.** A **fresh** `OrderDetails` EIP-712 envelope over the full post-modify state with a **fresh nonce** — the same envelope and type as `createOrder`. Verification uses the restated values plus the fixed trigger Boolean values described above. See [Signatures & Nonces](/developers/devnet/authentication/signatures-and-nonces.md).
* **Errors** (client-facing codes): `ORDER_NOT_FOUND_ERROR`; `INPUT_VALIDATION_ERROR` (a restated immutable differs from the resting order, or `timeInForce`/`expiresAfter` are inconsistent); `EMPTY_MODIFY_ERROR` (no field actually changed); `MODIFY_QTY_BELOW_FILLED_ERROR`; `POST_ONLY_WOULD_CROSS_ERROR`; `MODIFY_ORDER_OTHER_ERROR` (another modify rejection; read the returned message); `UNAUTHORIZED_SIGNATURE_ERROR`; `NUMERIC_OVERFLOW_ERROR`.

`modifyOrder` is also how you **refresh a GTT's `expiresAfter`** without re-placing the order (see [Order Types & Time-in-Force](/developers/devnet/order-entry/order-types-and-tif.md)).

## Cancelling

Cancel a specific order (`cancelOrder`) or all your orders (`cancelAll`) — both require a valid signature, for spot and perp alike. To amend a resting order without losing its ID, use [`modifyOrder`](#modifying-a-resting-order) rather than cancelling and re-placing. The account-scoped [`cancelAllAfter`](#cancel-on-disconnect-cancelallafter) dead-man's switch is a third member of the cancel family: it arms a timer that cancels every open order on the account if you stop refreshing it.

## Trading halts

Reya may temporarily **halt trading**. Design your client to handle `TRADING_HALTED_ERROR` and resume only after trading becomes available again.

While trading is halted:

* **You can't open, increase, or reduce a position.** `createOrder` and `modifyOrder` are **rejected** — including reduce-only orders. The rejection arrives as `TRADING_HALTED_ERROR`.
* **Cancels remain available during a trading halt.** You can use `cancelOrder`, `cancelAll`, and `cancelAllAfter`.

Treat a halt rejection as temporary. Back off, reconcile your orders and positions, and retry when trading resumes. Cancels remain available throughout the halt.
