Order Lifecycle
The states an order moves through, and the two time controls that govern it.
The path of an order
Signed. You sign the
OrderDetails(see Signatures & Nonces) and submit over REST or WS Order Entry.Accepted by the matching engine — validated, with 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
expiresAftertimestamp passes — emitting aCANCELLEDorderChange. You can refresh a resting GTT'sexpiresAfterwithmodifyOrderinstead 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 usercancelAllclears both armed triggers and fired children; Cancel-on-Disconnect preserves both. Full contract: Trigger Orders (SL/TP).
Terminal. The order reaches
FILLEDorCANCELLED, and any fills proceed to on-chain settlement (see Trade Settlement).
All orders publish state changes on the orderChanges channel. 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 and Trade Busts.
Average fill price
avgFillPx is the quantity-weighted average execution price across all fills of an order so far, including both maker (passive) and taker (aggressive) fills, excluding fees. It corresponds to the order's cumulative filled quantity, cumQty.
avgFillPx = sum(fill price × fill quantity) / cumQtyThe field is a decimal string, calculated from the exact fill prices and quantities and rounded half-up once to at most 9 decimal places. It is omitted before the first fill, when cumQty is zero. The cumulative average is preserved across amendments of the same order and cancellation; a modify with no new fill keeps the previous average.
The field is included after the first fill on:
REST and WebSocket Order Entry
createOrderandmodifyOrderresponses, including IOC create responses.WebSocket Info
orderChangesupdates and the subscription's open-orders snapshot.REST
openOrdersandorderHistoryrecords.
For example, an order that first takes liquidity and later fills as a maker reports:
New fill
Role
cumQty
avgFillPx
1 at 100
Taker
"1"
"100"
2 at 110
Maker
"3"
"106.666666667"
1 at 120
Maker, after amend
"4"
"110"
execQty reports the quantity filled in the current update, while avgFillPx covers all fills represented by cumQty. Individual settled executions continue to carry their own price. Like the other order-outcome fields, avgFillPx describes matching-engine results before settlement; use the executions channels to confirm settled fills.
deadline vs expiresAfter
Two independent time fields, both signed:
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). See Signatures & Nonces 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 for bounds, request fields, signing, and error codes.
Modifying a resting order
The request rules below follow API 3.6.2; see the changelog for release history.
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
OrderDetailsstate 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 ascreateOrder, but its JSON fields are class-specific: trigger create and modify requiretimeInForceand omitreduceOnlyandpostOnly, includingfalse. Both Boolean fields are reconstructed as fixedfalsefor signing and verification; they are never inherited from stored state. The modifiable set is class-split:LIMIT—limitPx,qty,postOnly,expiresAfter(triggerPxis forbidden):qtyis the total post-modify order quantity and must exceedcumQty(elseMODIFY_QTY_BELOW_FILLED_ERROR).expiresAfter— GTC omits it; GTT must carry a future value greater thandeadline.
STOP_LOSS/TAKE_PROFIT— onlylimitPxandtriggerPx:triggerPxre-prices the armed trigger in place (no cancel-and-recreate) and is required;qtystays 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).
Immutables must be restated to match. The remaining
OrderDetailsfields —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 withINPUT_VALIDATION_ERROR.timeInForceis immutable — you cannot switch GTC ↔ GTT via modify;orderTypeis immutable — a modify re-prices a trigger but never converts betweenLIMITandSTOP_LOSS/TAKE_PROFIT.Target by
orderIdwhen present, otherwise by a non-zeroclientOrderId. The sameclientOrderIdfield restates the resting order's immutable client id for signing. If both identifiers are supplied,orderIdis canonical for lookup andclientOrderIdis the restated immutable. If the resting order has no client id, omitclientOrderId; do not send a placeholder value. Supplying neither is rejected withINPUT_VALIDATION_ERROR.Crossing. For a LIMIT order, a non-post-only modify whose new
limitPxcrosses executes immediately and settles like a crossing create. A post-only modify that would cross is rejected withPOST_ONLY_WOULD_CROSS_ERRORand the resting order is left untouched.Signing. A fresh
OrderDetailsEIP-712 envelope over the full post-modify state with a fresh nonce — the same envelope and type ascreateOrder. Verification uses the restated values plus the fixed trigger Boolean values described above. See Signatures & Nonces.Errors (client-facing codes):
ORDER_NOT_FOUND_ERROR;INPUT_VALIDATION_ERROR(a restated immutable differs from the resting order, ortimeInForce/expiresAfterare 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).
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 rather than cancelling and re-placing. The account-scoped 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.
Matching pauses
When on-chain settlement falls behind, Reya temporarily pauses matching so that unsettled fills stop building up. Order entry stays open: only requests that would fill are refused. Design your client to handle CROSSING_ORDERS_TEMPORARILY_UNAVAILABLE_ERROR as a temporary rejection.
Matching pauses when:
settlement transactions for matched fills are failing to broadcast;
on-chain confirmation of fills already sent for settlement is lagging; or
fills are waiting too long to settle — the oldest waiting fill is more than about 30 seconds old. This cause clears once the backlog drains below about 5 seconds.
Matching resumes automatically once these conditions clear.
While matching is paused:
Orders that would fill are rejected. A
createOrderormodifyOrderthat would cross the book is rejected withCROSSING_ORDERS_TEMPORARILY_UNAVAILABLE_ERROR— including reduce-only orders. Nothing is placed, and a rejected modify leaves the resting order unchanged.Resting orders don't fill. Only an incoming crossing order can trade, so nothing on the book fills until matching resumes.
You can still place and re-price resting orders. A
createOrderthat doesn't cross rests on the book, and amodifyOrderthat re-prices a resting order without crossing is applied. A post-only order that would cross is still rejected withPOST_ONLY_WOULD_CROSS_ERROR.Triggers can be placed and modified, but don't fire. You can create, modify, and cancel
STOP_LOSS/TAKE_PROFITorders. Armed triggers stay armed and can fire once matching resumes; see Trigger Orders (SL/TP).Cancels remain available. You can use
cancelOrder,cancelAll, andcancelAllAfter.
Treat the rejection as temporary. Back off, then retry the crossing request if it is still appropriate — prices and your position may have moved in the meantime. The same error is returned when pre-trade risk checks are temporarily unavailable, and is handled the same way. A rejected crossing request still uses a create/modify operation; see Rate Limits.
Last updated