Placing orders
How matching works: frequent batch auctions
MNX does not match orders the instant they arrive. Orders are collected into short batches and matched at discrete intervals (about every 200ms) — a Frequent Batch Auction (FBA). Each batch clears at a single uniform clearing price: the price that maximizes matched volume, applied to every trade in the batch. Orders eligible on each side are allocated pro rata (proportionally to their remaining size) rather than by queue position.
Practical consequences for an API client:
- A successful
POST /v0/ordersmeans your order was validated and accepted into the book — not that it traded. Matching happens in a subsequent batch. - Market orders are immediate-or-cancel: whatever matches in the next batch fills, and the rest is cancelled.
- All fills in one batch settle at the same clearing price, which may be better than your limit price.
- Sub-batch-interval speed buys nothing; there is no race to the top of a queue within a batch.
The place-order request
POST /v0/orders (authenticated). The order must carry an EIP-712 signature — see Authentication & signing. A representative limit order:
POST /v0/orders
{
"market_id": 1,
"side": "LONG",
"order_type": "LIMIT",
"price": 2000,
"quantity": 0.5,
"leverage": 2,
"expiration_seconds": 0,
"salt": "123456789",
"signature": "0x...",
"signature_type": 1
}| Field | Meaning |
|---|---|
market_id | The market to trade, from GET /v0/markets. |
side | LONG (buy) or SHORT (sell). |
order_type | MARKET, LIMIT, or a conditional type (below). |
price | Limit price in human units (omit or 0 for market orders). Must be a multiple of the market's tick size (the smallest price increment). |
quantity / usd_amount | Order size in base units, or a USD budget from which the server computes the quantity. Quantity must be a multiple of the step size and at least the minimum order size. |
leverage | Position leverage — how many dollars of exposure per dollar of margin (collateral) you put up. A positive whole number, capped by the market's maximum; defaults to 1. |
expiration_seconds | Unix timestamp (in seconds) after which the order expires, or 0 for good-til-canceled. |
trigger_price | Required for conditional order types. |
reduce_only | If true, the order may only shrink an existing position, never open or grow one. |
salt, signature, signature_type | The EIP-712 signature material; the salt and expiration must match the values signed into the order struct. |
The server validates the signature, checks the order against the market's parameters (tick size, step size, minimum and maximum order size, leverage cap, and price bands around the oracle price), and reserves margin for it. Orders that open or increase a position reserve full margin up front; orders that close an existing position reserve no margin, since they reduce exposure. The exact market parameters are returned by GET /v0/markets.
Two helper endpoints let you pre-check an order: POST /v0/orders/calculate-quantity (size an order from a USD budget, including an estimated clearing price) and POST /v0/orders/estimate (estimate the exact quantity, cost, fees, clearing price, margin health, and any required automatic top-up, while also returning available_margin, max_quantity, and max_notional from the same live snapshot). Send size: 0 when only maximum sizing is needed; limit-order estimates still require price.
Order types
Beyond MARKET and LIMIT, six conditional types wait for the market's mark price (used for unrealized profit and loss and conditional triggers) to cross a trigger before entering the matching pipeline:
| Type | Executes as | Reduce-only |
|---|---|---|
STOP_MARKET / STOP_LIMIT | MARKET / LIMIT | Optional |
TAKE_PROFIT_MARKET / TAKE_PROFIT_LIMIT | MARKET / LIMIT | Always |
STOP_LOSS_MARKET / STOP_LOSS_LIMIT | MARKET / LIMIT | Always |
Conditional orders rest with status PENDING_TRIGGER and reserve margin up front like any other order. Triggers are evaluated after each mark-price update. Stop and stop-loss orders trigger when the mark price moves against the order's direction (mark ≥ trigger for a buy, mark ≤ trigger for a sell); take-profit orders trigger on the favorable crossing (mark ≤ trigger for a buy, mark ≥ trigger for a sell). On trigger, the order becomes a regular market or limit order with status OPEN and enters the next batch.
The response
A successful placement returns the accepted order — including its order_id and order_hash, which you need for cancels and status reads — plus a fills array, an updated balance snapshot when available, and a read_after bookmark you can pass to subsequent reads for read-your-own-writes consistency (see Getting started). Because matching happens at the next batch, expect fills to arrive after placement, not in it.
Cancelling orders
POST /v0/orders/cancel/by-hash/:order_hash— cancel one order by its hash.POST /v0/orders/cancel/all— cancel all of your open orders, optionally scoped with amarket_id.POST /v0/orders/cancel/batch— cancel a specific list oforderHashesin one call. This variant requires acancelSignature: an EIP-712 signature over the order hashes (theOrderSignerlibrary's cancel-order signing), so it can also be authorized by a session key with thecan_cancel_orderspermission.
Cancel responses include an is_duplicate flag: retrying a cancel that already succeeded is safe and reports itself as a duplicate rather than failing.
Reading order status and fills
Order status is one of OPEN, FILLED, CANCELLED, EXPIRED, PENDING_TRIGGER, or CANCEL_PENDING_FINALIZE (a cancel accepted while a batch containing the order is settling).
GET /v0/orders/by-user/:user_id— your orders, filterable by market, status, and side.GET /v0/orders/:order_id— one order's current state.GET /v0/orders/:order_id/fills— the fills (individual matched executions) of one order.GET /v0/orders/:order_id/eventsandGET /v0/users/:user_id/order-events— the lifecycle event log (CREATED,PARTIALLY_FILLED,FILLED,CANCELLED,EXPIRED).GET /v0/orders/:order_id/fill-processing-status— whether fills are still being settled on-chain.
For push-based updates instead of polling, subscribe to your user topic on the WebSocket feed — see WebSockets.