Place order
Place a single order.
address query parameter matching the master Ethereum address for X-API-Key (same as POST /createApiKey response).
Response behavior
Asynchronous. The endpoint returns either202 Accepted (the common case — the signed request was forwarded to the matching engine and the body does not carry terminal state) or 200 OK (the gateway already had definitive state for the order by the time it responded; status reflects that state). In both cases the body echoes the accepted orderId / clientId so subscribers can correlate WebSocket events with the request. To observe the full order lifecycle (OPEN, FILLED, CANCELED, REJECTED, fills, rejection reasons, etc.) clients must subscribe to the orders WebSocket channel (and userFills for trade-level events).Authorizations
Hex-encoded Ed25519 public key (64 chars). The public key IS the API key — register it via POST /createApiKey. Required on every authenticated request, both read-only and signed.
Unix time in nanoseconds as a decimal string (e.g. "1713825891591000000"). Millisecond or second epochs are rejected with 401 Unauthorized. Must be within ±30,000 ms (MaxTimestampDriftMs, the drift window stays configured in milliseconds) of server wall-clock, or the request is rejected with 401 Unauthorized. Required on all mutating / credential-creating endpoints. This same value must appear as the ct field in the ordersign typed canonical payload (single-order endpoints) or in each element's ct field (batch endpoints).
Lowercase hex-encoded Ed25519 signature (128 chars).
Single-order endpoints (placeOrder, cancelOrder, modifyOrder, and other non-batch mutating routes) sign over the ordersign typed canonical payload — a compact, key-sorted JSON object built from parsed request fields using engine-native integer values:
placeOrder: {"ad":"0x…","ai":N,[,"c":"…"],"ct":N,"g":N,"m":N,"op":1,"p":N,"q":N,"r":0|1,"s":N,"t":N,"v":1}
cancelOrder: {"ad":"0x…","ai":N,[,"c":"…"],"ct":N,[,"id":"…"],"m":N,"op":2,"v":1}
modifyOrder: {"ad":"0x…","ai":N,[,"c":"…"],"ct":N,[,"id":"…"],"m":N,"op":3,"p":N,"q":N,"v":1}ct must equal the X-Timestamp header value. Keys in brackets are conditional (omitted when empty). op values: 1=place, 2=cancel, 3=modify. See the ordersign package for field definitions and reference signing code.
Other signed routes (e.g. createApiKey, tokens, userPreferences) still use the legacy scheme: signing_message = X-Timestamp + ACTION + canonicalJSON(body), where ACTION is the camelCase final path segment.
Batch endpoints (batchPlaceOrders, batchCancelOrders) do NOT use this header. They authenticate with per-element typed ordersign signatures embedded in the request body (see the global auth description and the per-field signature descriptions on OrderRequest / CancelOrderRequest).
Read endpoints are authenticated by ?address= (and optionally X-API-Key) only — no signature is required. canonicalJSON(body) is the JSON body with object keys sorted lexicographically at every level and no whitespace; the server canonicalizes the received body before verifying, so only the bytes signed over must be canonical. Required on all mutating / credential-creating endpoints.
Query Parameters
Master Ethereum address for this API key (must match address from POST /createApiKey for the same key). Required on REST for account-scoped reads and for place/cancel. Invalid hex → 400; mismatch with key → 403.
20-byte EVM address as hex: optional 0x or 0X prefix and exactly 40 hexadecimal digits. API responses normalize to lowercase a–f after 0x.
^(0x|0X)?[0-9a-fA-F]{40}$Body
Master Ethereum address for this API key (must match POST /createApiKey for the same key). May be sent here and/or as the address query parameter; if both are set, they must match.
^(0x|0X)?[0-9a-fA-F]{40}$Perpetual market identifier (uint16). Map to display name via GET /markets. Used for orders, positions, funding, and market metadata.
0 <= x <= 65535Account index (account index, 0–9). Identifies the account for orders, positions, fills, and API keys.
0 <= x <= 9BUY, SELL Execution style of the order. Use tpslType to mark an order as stop-loss or take-profit.
LIMIT— rests at the specifiedpriceuntil matched or expired.MARKET— executes immediately at best available price. Apricefield is required and serves as a protective slippage bound. The price must be a positive decimal within 10% of the current mark price; deviations beyond that are rejected withMarketPriceSlippageToleranceTooHigh. TPSL MARKET legs must also supply aprice, but it is validated against thestopPrice(trigger price) rather than the live mark price — the price must be within 10% ofstopPrice, since at trigger time the mark price ≈ stopPrice.
LIMIT, MARKET Order size in human-readable base-asset units (e.g. "0.1" for 0.1 BTC). Must be a positive value divisible by the market's step size (see GET /markets). Set to "0" for positionTpsl grouping — the engine resizes to the full open position at trigger time.
1^(0|0\.[0-9]*[1-9][0-9]*|[1-9][0-9]*\.?[0-9]*)$"0.1"
Order price in human-readable USD (e.g. "50000.5"). Must be a positive decimal divisible by the market's tick size (see GET /markets).
- LIMIT — the resting limit price.
- MARKET — required protective slippage bound (see
orderType). Must be within 10% of the current mark price; deviations beyond that are rejected withMarketPriceSlippageToleranceTooHigh. - TPSL MARKET — also required. Must be within 10% of
stopPrice(trigger price), since at trigger time the mark price ≈ stopPrice.
1^(0|0\.[0-9]*[1-9][0-9]*|[1-9][0-9]*\.?[0-9]*)$"50000.5"
GTT = Good Till Time (rests until goodTilTime), IOC = Immediate or Cancel, FOK = Fill or Kill, ALO = Add Liquidity Only (post-only)
GTT, IOC, FOK, ALO Signature timestamp (epoch ms). Must be > 0.
1 <= x <= 9223372036854776000Good-till-time (GTT): the order's expiration as an epoch-MICROSECOND timestamp (string) — the API's user-facing timestamp resolution, matching createdAt/updatedAt. REQUIRED for resting time-in-forces (GTT, ALO) and must be at least one month ahead of the current system timestamp; a nearer value is rejected. It is ignored for IOC and FOK, which never rest. The engine cancels the order (cancel reason Expired) the first time it would fill at or after this instant.
^[0-9]+$"4102444800000000"
Minimum fill size in human-readable base-asset units.
Trigger price in human-readable USD. Required when tpslType is set; otherwise omit this field.
1Set to STOP_LOSS or TAKE_PROFIT to mark this as a trigger order. Requires stopPrice; for LIMIT execution, price is also required.
STOP_LOSS, TAKE_PROFIT When true, mark this TPSL as a position-level close: at trigger time the engine resizes the order to the user's full open position in marketId (and forces reduceOnly). If the position is zero, the TPSL is canceled instead of executed. Requires tpslType. At most one position-level TPSL of each trigger class (TP, SL) may be active per account+market — a second placement is rejected with POSITION_TPSL_ALREADY_EXISTS. Defaults to false (sized leg / partialTpsl behavior).
Entry order id this TPSL leg is bound to (entryTpsl bundles). Set on each child TPSL placed alongside an entry order so the engine cascade-cancels every leg pointing at the entry when the entry is canceled. Requires tpslType. Omit for standalone TPSLs (partialTpsl, positionTpsl) and for non-TPSL orders.
Optional client-assigned identifier for this order.
Charset — only ASCII letters, digits, hyphens, and underscores ([A-Za-z0-9_-]) are accepted. This restricted set ensures JSON serialization is byte-identical across all SDK languages (Go, TypeScript, Python), which is required for cross-language signature compatibility. Strings containing any other character (spaces, @, Unicode, etc.) are rejected with HTTP 400 InvalidRequest.
Length — 1–36 characters.
Uniqueness — must be unique among the account's currently live orders. Reusing a clientId while the prior order is still open returns DUPLICATE_CLIENT_ID. The id is freed once the prior order reaches a terminal state (FILLED, CANCELED, REJECTED). An account may hold at most 10,000 live clientIds (TOO_MANY_CLIENT_IDS).
When set, the order can later be canceled or modified by clientId instead of orderId.
36^[A-Za-z0-9_-]+$Client-side timestamp (epoch ms as string).
Fill mode.
If true, the order can only reduce an existing position. When reduceOnly is true, timeInForce must be IOC or FOK.
Per-order Ed25519 signature (128 hex). REQUIRED when this order is an element of a POST /batchPlaceOrders orders array; omitted for single POST /placeOrder (which uses X-Signature in the HTTP header instead).
Covers the ordersign typed canonical payload for this order:
- Plain orders (no
tpsl_type):op=1{"ad":"0x…","ai":N,[,"c":"…"],"ct":N,"g":N,"m":N,"op":1,"p":N,"q":N,"r":0|1,"s":N,"t":N,"v":1} - TPSL / conditional orders (with
tpsl_type):op=4(OpPlaceUntriggered) Same field set asop=1but"op":4. Using a distinct op prevents cross-replay between TPSL and plain placeOrder signatures.
In both cases ct must equal the shared X-Timestamp header value.
Response
Order processed and the gateway already has definitive state for it. status reflects that state (OPEN / FILLED / CANCELED / REJECTED). Treat this as best-effort enrichment of the 202 path; the orders WebSocket channel is still the source of truth for the full lifecycle.
Place-order response. The HTTP call is asynchronous and may return either:
202 Accepted— common case.statusisACKand the body carries no terminal state; theordersWebSocket channel delivers the order's lifecycle.200 OK— the gateway already had definitive state for the order by the time it responded.statusreflects that state (OPEN/FILLED/CANCELED/REJECTED) and enrichment fields (updatedAt,remainingSize,filledSize,rejectionReason) may be populated. Clients should treat this as best-effort and not rely on it.
In both cases the body echoes the accepted orderId and clientId for correlation. To observe the full lifecycle (fills, rejection reasons, etc.) clients must subscribe to the orders WebSocket channel (and userFills for trade-level events).
Master Ethereum address of the account that placed the order.
"0x1234567890abcdef1234567890abcdef12345678"
Account index (subaccount) that placed the order.
0 <= x <= 9Server-generated order ID (hex string).
"a1b2c3d4e5f67890"
Perpetual market identifier (uint16). Map to display name via GET /markets. Used for orders, positions, funding, and market metadata.
0 <= x <= 65535Market symbol (e.g. BTC-USD).
"BTC-USD"
Order side.
BUY, SELL Order size in human-readable base-asset units.
Order price in human-readable USD.
ACK on the 202 path. On the 200 path, the definitive go-core state (OPEN / FILLED / CANCELED / REJECTED). Subscribe to the orders WebSocket channel for the full lifecycle.
PENDING, OPEN, PARTIALLY_FILLED, FILLED, CANCELED, MARGIN_CANCELED, REJECTED, UNTRIGGERED, TPSL_PLACED, TPSL_TRIGGERED, TPSL_CANCELED, LIQUIDATED, ADL, ACK, CANCEL_ACKNOWLEDGED, CANCEL_ALL_ACKNOWLEDGED, CANCEL_PENDING, ERROR "ACK"
Creation timestamp (epoch microseconds).
Echo of the clientId, if provided.
Order type (e.g. LIMIT, MARKET).
LIMIT, MARKET Echo of the time-in-force from the request.
GTT, IOC, FOK, ALO Expiration timestamp in epoch microseconds (as string), echoed from the request. Present for GTD/ALO orders that carry a good-till-time expiry; absent for GTC/IOC/FOK orders (which never expire). Matches the goodTilTime field on the Order shape.
Echo of the reduce-only flag from the request.
Epoch microseconds of the definitive go-core state when the gateway returned it on the 200 path. Omitted on the 202 path — definitive timestamps are delivered via the orders WebSocket channel.
Unfilled size at updatedAt, in human-readable base-asset units. Populated only on the 200 path; otherwise see the orders WebSocket channel.
Cumulative filled size at updatedAt, in human-readable base-asset units. Populated only on the 200 path; otherwise see the orders WebSocket channel.
Machine-readable reason when status is REJECTED on the 200 path. Otherwise rejection reasons are delivered via the orders WebSocket channel.
POST_ONLY_WOULD_CROSS, SELF_TRADE, UNDERCOLLATERALIZED, COULD_NOT_FILL, IOC_CANCELED, FOK_FAILED, REDUCE_ONLY_WOULD_INCREASE, TOO_MANY_CLIENT_IDS, DUPLICATE_CLIENT_ID, POSITION_TPSL_ALREADY_EXISTS, ENTRY_TPSL_CANNOT_BE_POSITION_TPSL, ORDER_WILL_TAKE_LIQUIDITY_DURING_MARKET_HALT, ORDER_NOT_FOUND_FOR_MODIFY, MODIFY_CHANGED_IMMUTABLE_FIELD, MODIFY_ZERO_SIZE, PRICE_WILL_EXCEED_MAXIMUM_OUTSIDE_RTH_TRADING_BOUND, MODIFY_WOULD_CROSS_OUTSIDE_RTH_TRADING_BOUNDARY Present when status is ERROR (e.g. batch item validation failure).
Per-subaccount order-pool rate-limit snapshot after this placement. Omitted when rate limiting is not configured.