Skip to main content
The order action places one or more orders against a contract. A single request can carry up to 10 order objects under one ECDSA signature. Order objects use compact single-letter keys to keep payloads small. Three order shapes are available, selected by the t field: limit (GTC, IOC, or ALO), market, and trigger (stop-loss, take-profit, or breakout entry). A limit or market entry order can also carry inline take-profit and stop-loss levels, so a position and its exits are established in one signed request.
Every order requires a price. p is mandatory for market orders as well as limit orders — the matching price is the price you submit. The server does not compute a marketable price for you. A missing or non-positive p returns 400 BAD_REQUEST.

Endpoint

Request

Rests in the order book until filled or cancelled (GTC), or follows the IOC / ALO policy you choose. p is the resting price.

Action fields

string
required
Fixed value: "order".
array
required
Array of order objects. Maximum 10 per request; more returns BATCH_TOO_LARGE.
string
Compatibility field. The server does not validate it and it does not affect placement, but send the conventional value "na".

Order object fields

Each element of the orders array uses compact single-letter keys.
int32
required
asset — The integer contract ID identifying which perpetual to trade.
boolean
required
isBuytrue to buy/go long; false to sell/go short.
string
required
price — Order price as a raw integer string, required for every order type.
  • Limit order — the resting price.
  • Market order — the execution price you are willing to cross to, computed client-side as mark price ± slippage allowance.
  • Trigger order — the resting price after the trigger fires when isMarket is false, or the execution price when it is true.
Must be greater than zero and aligned to the contract’s tickSize. A missing, zero, or misaligned price is rejected.
string
required
size — Order quantity as a raw integer string. Must be positive.
boolean
reduceOnlytrue restricts the order to reducing an existing position. Omitting the field is equivalent to false.
object
required
orderType — Selects limit, market, or trigger behavior. See Order types.
string
clientOrderId — An int64 decimal string you assign for your own tracking (for example "1778572951477"). Use it later with cancelByCloid to cancel without storing the exchange-assigned oid.
string
builder — Optional builder-fee recipient address ("0x" + 40 hex). Omit for no builder. An unregistered address does not reject the order, but builderFee is silently zeroed.
int
builderFee — Builder fee rate in basis points. Ignored when builderAddress is omitted.
In a batched request only the first order’s builder fields take effect — the engine uses orders[0]’s builderAddress / builderFee as the single shared builder for the whole batch, the same one-per-request rule as vaultAddress.
You never send a position side. The server derives which position an order acts on from the contract, the direction b, and r — a reduce-only order closes the position opposite to its own direction.

Order types

Trigger orders

A trigger order consumes no book depth while it waits. When the mark price crosses triggerPx, the server places the order described by the remaining fields.
string
required
Trigger price as a raw integer string, greater than zero. Evaluated against the mark price.
boolean
required
true fires a market IOC order; false rests a GTC limit order. Both require a positive top-level p — the resting price when false, the execution price when true.
string
required
"tp" or "sl". Sets the direction of the trigger comparison, matching the convention used by tpSl.
Constraints and behavior:
  • Single order only. Trigger orders are valid when orders has exactly one element. A batch containing one is rejected with 400 BAD_REQUEST.
  • The trigger price is always evaluated against the mark price; no other price source can be selected.
  • A trigger order cannot also carry inline tp* / sl* fields.
  • The response differs from an ordinary order — see Trigger order response.
  • A resting trigger order appears in userOrders with isConditional: true, an orderType of TPM / TPL / SM / SL, and its triggerPrice. On the orderUpdates channel it carries the compact cond: true flag.
  • Cancel it with cancelConditional or cancelTpSl; there is no dedicated cancel action.

Inline take-profit and stop-loss

A limit or market entry order can arm its own exits. These fields are part of the signed payload, so include them when you compute the signature. The sl* fields mirror the tp* fields exactly.
string
Take-profit trigger price. "0" or omitted means no take-profit.
string
Execution price used once the take-profit triggers, greater than zero. With a limit tpOrderType this is the resting price; with a market tpOrderType it is the price to cross to. A market take-profit still requires this price.
string
Quantity to close on trigger. "0" closes the entire position.
int
Price source for the trigger: 0 for mark price, 1 for oracle price. No other value is accepted.
int
Order type placed when the take-profit triggers: 1 for limit, 2 for market. Required whenever tpPrice is set and must be omitted or 0 when it is not.
string
Stop-loss trigger price. Mirrors tpPrice.
string
Execution price once the stop-loss triggers. Mirrors tpLimitPrice.
string
Quantity to close on trigger. Mirrors tpSize.
int
Price source for the stop-loss trigger. Mirrors tpTriggerType.
int
Order type placed when the stop-loss triggers. Mirrors tpOrderType.
Inline TP/SL applies to single-order requests only. In a batch of two or more, every order’s tp* / sl* fields are ignored. A reduce-only order must not carry them — the whole order is rejected if it does.
Once the entry order is completely filled, the armed levels become conditional orders bound to the resulting position. They appear in userOrders with isConditional: true and isPositionTpsl: true, with tpslParentOrderId pointing at the entry order. A partial fill does not arm them.

Responses

Order submission returns either HTTP 200 with per-order results, or HTTP 202 acknowledging the batch for asynchronous processing. Clients must handle both — do not assume one or the other.
The batch was accepted for asynchronous processing. No order IDs or fill results are returned inline.
Read each order’s outcome from the orderUpdates channel, correlating by your c (client order ID). The same shape is used by the cancel actions.

Response fields

string
"ok" for a synchronous result, "accepted" when the batch was taken for asynchronous processing. Malformed, unauthenticated, or pre-validation failures instead return a top-level status: "error" with a machine code.
int
Present on an acknowledgement. Number of orders accepted for processing.
array
Present on a synchronous result. One entry per submitted order, in request order. Each entry is one of:
  • resting{ "oid": <int64> }, the order is in the book.
  • filled{ "oid": <int64>, "totalSz": "<string>", "avgPx": "<string>" }.
  • error — a string explaining why that order was rejected.
A top-level "status": "ok" does not mean every order succeeded. Inspect each element of statuses — a rejected order appears there as an error entry alongside successful siblings.

Trigger order response

A trigger order settles through the conditional-order path, so its 200 response uses a different shape. Parse the receipt according to whether the order was a trigger order; do not apply the statuses[] shape to it.
With tpsl: "tp" the new order’s ID is in tpOrderId and slOrderId is 0; with tpsl: "sl" the reverse. A 202 acknowledgement is identical to an ordinary order’s.

Retrieving order state

When you receive a 202, and whenever you need lifecycle transitions, read order state from:

Validation sequence

An order is checked in this order, and the first failure is the one reported. Every check runs on the raw integers you submit, so you can reproduce all of it locally before signing.
1

Price present and on tick

p must be greater than zero and an exact multiple of the contract’s tickSize. This applies to market orders too. → invalid price
2

Price within the book's tick range

p / tickSize must be below the contract’s maxTicks. → price exceeds tick range (maxTicks x tickSize)
3

Size present and on step

s must be greater than zero and an exact multiple of stepSize. → invalid size
4

Size within range

s must not exceed 2,147,483,647. → size exceeds Integer.MAX_VALUE
5

Notional above the floor

price_raw × size_raw × notionalScaleMultiplier must be at least minTradeNtl. → notional below minTradeNtl
6

Notional below the cap

The same notional must not exceed maxPositionNotional. → notional exceeds maxPositionNotional
7

Price band (limit orders only)

For a limit order, |p − mark| must not exceed mark × priceBandBps / 10000. Skipped when priceBandBps is 0 or no mark price exists. Market orders skip this check entirely.price exceeds priceBandBps
8

Margin pre-check

The account must have sufficient margin. For a market order the reserved amount is charged on the full difference between your submitted price and the mark price, without dividing by leverage.
All the parameters above — tickSize, stepSize, notionalScaleMultiplier, minTradeNtl, maxPositionNotional, priceBandBps — come from configs for that specific contract. See Notional, and the limits enforced on it for the arithmetic and a worked example.
A market order is executed as IOC regardless of any tif you supply.

Errors

Messages are fixed strings and do not interpolate your values — read the limit that was breached from configs.
For accounts in PORTFOLIO margin mode, margin is drawn from the shared group pool automatically whenever the contract belongs to a share group. You send no group-related fields — the system resolves it from your marginShareType and the contract’s group membership.