Trade API#
POST /trade/noop - Invalidate a Specified Nonce#
Invalidates a specified nonce.
A cancelled action may be successfully submitted on-chain but fail during execution with error code 30004.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | Object | Yes | Noop action. |
| > type | String | Yes | Must be noop. |
| nonce | Number | Yes | Nonce to invalidate. |
| signature | Object | Yes | EIP-712 signature. |
| > Ecdsa | Object | Yes | ECDSA signature. |
| >> r | String | Yes | Signature r value, as a 0x-prefixed hexadecimal string. |
| >> s | String | Yes | Signature s value, as a 0x-prefixed hexadecimal string. |
| >> v | Number | Yes | Signature recovery value. |
Request Example
{
"action": {
"type": "noop"
},
"nonce": 1,
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
Successful Response
A successful response returns code="0", msg="", and data=[], indicating that the specified nonce has been invalidated and no business data is returned.
The successful API response confirms only that the nonce was invalidated. It does not guarantee that any pending action was cancelled, nor can it roll back an already executed action.
Response Example
{
"code": "0",
"msg": "",
"data": []
}
POST /trade/place-order - Place Orders#
Supports batch order placement, with a maximum of 30 orders per request.
- Ordering directly by quote-currency amount is not supported. Market orders are simulated with aggressive IOC limit orders.
- Decimal places in
sizemust not exceedinstruments.sizeDecimals. Orders exceeding the permitted precision fail on-chain validation. vaultAddressis an optional envelope field. Omit it when operating the main account; provide the subaccount address when operating a subaccount.userremains the main-account address, and the signer remains an Agent authorized by the main account.marginModerepresents the current margin mode for theassetId; it is not independently selectable for each order. All positions and orders for the same account andassetIduse the samemarginMode.crossandisolatedcannot coexist.- Complete the
/account/set-margin-modeflow before switching margin mode.
Leverage Validation Rules
- oneWay: Uses net leverage.
- hedge + cross: Long and short positions share leverage.
- hedge + isolated: Uses long or short leverage according to the order's
positionSide.
Request Query String Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| mode | String | No | Response mode: sync waits synchronously for the on-chain receipt; async returns txHash immediately after acceptance. Defaults to sync. This parameter affects only the response format; it is not signed, does not change on-chain behavior, and is excluded from the EIP-712 signature. |
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | Object | Yes | Business action object. This field and all of its child fields are included in the EIP-712 signature. Field names are on-chain canonical names and are fixed after release. |
| > type | String | Yes | Must be placeOrder. |
| > grouping | String | No; defaults to na | na: standalone or Trigger order; orderTpsl: Order-Attached TPSL; positionTpsl: Position-Attached TPSL. |
| > orders | Array | Yes | Non-empty order list. |
| >> assetId | String | Yes | Composite asset ID that includes market type. |
| >> side | String | Yes | buy or sell. |
| >> marketType | String or Object | No | Market type. spot is a string; perp is an object containing marginMode and positionSide. |
| >>> marginMode | String | No; perp only | cross or isolated. When omitted, uses the current mode for the assetId; new positions default to cross. |
| >>> positionSide | String | No; defaults to net | oneWay uses net; hedge uses long or short. perp only. |
| >> clientOrderId | String | Required for standard orders; optional for Trigger or TPSL orders | 34-character format: 0x{region}{env}{30hex}. Reusable; deduplication uses oid + block_height. |
| >> price | String | Yes | Trigger Market must use "0"; other order types must be greater than 0. When isTpLimit=true, this is the take-profit limit price. After triggering or conversion, the system places a Reduce-Only GTC Limit order at this price. |
| >> size | String | Yes | Greater than 0, in base token units. Order-Attached TPSL child orders must use "0" and are resolved from the parent order's filled size. Entire Position TPSL uses "0". |
| >> sizeType | String | No; defaults to base | base places orders by token quantity. quote places orders by quote-currency amount; quote is not currently supported by OpenAPI. |
| >> priceAmendType | String | No; defaults to noAmend | Handling strategy when price exceeds the permitted price band. OpenAPI currently supports only noAmend; out-of-band orders are rejected. clampToLimit is a reserved underlying capability and is not currently available. |
| >> reduceOnly | Boolean | No; defaults to false | Whether the order is Reduce-Only. Attached TPSL child orders always use true. |
| >> orderType | Object | Yes | Order-type object containing exactly one key: limit or trigger. They cannot coexist. Child fields exist only in their corresponding object. Placing tif, isMarket, triggerPx, tpsl, triggerPriceType, parentOrderId, or isTpLimit at the order level is rejected. |
| >>> tif | String or Object | Required for Limit orders | gtc, ioc, fok, or alo. |
| >>> isMarket | Boolean | Required for Trigger orders | true: execute at market after triggering, simulated by an aggressive IOC limit order. false: execute as a limit order after triggering; price is the resting limit price. |
| >>> triggerPx | String | Required for Trigger orders | Trigger price must be greater than 0. When isTpLimit=true, must be "0". This is a sentinel value, not a zero trigger price; TP Limit uses the order-level price. |
| >>> tpsl | String | Required for Trigger orders | Values depend on grouping: na uses up or down; orderTpsl and positionTpsl use tp or sl. |
| >>> triggerPriceType | String | Required for Trigger orders | mark or index. Supported by all Trigger and TPSL orders; use mark when isTpLimit=true. |
| >>> parentOrderId | String | No | Exists only in orderType.trigger. When omitted, the parent order and TPSL child order are submitted in the same orders[] array; the chain automatically fills the parent oid from orders[0] into the child order. When an oid is provided, it appends TPSL to an existing, resting parent order. The request then includes only TPSL child orders and uses grouping="orderTpsl". |
| >>> isTpLimit | Boolean | No; defaults to false | TP Limit child-order flag. When true, tpsl must be tp and isMarket must be false. |
| nonce | Number | Yes | Current timestamp in milliseconds. Included in the signature hash and used by the server for replay prevention. |
| expiresAfter | Long | No | Action expiration time, Unix timestamp in milliseconds. Requests after this time are rejected. This is unrelated to an order's GTD expiration. |
| user | String | No | Principal account address. The gateway resolves the principal from the signer-to-main-account binding and this field may be omitted. When explicitly provided, it must match the binding. |
| vaultAddress | String | No | Omit when operating the main account; provide the subaccount address when operating a subaccount. |
| signature | Object | Yes | Agent EIP-712 ECDSA signature for the complete action. r and s are 0x-prefixed hexadecimal strings; v is 0 or 1. |
marketType
prediction and spot are strings. perp is an object.
{
"marketType": "spot"
}
{
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
}
}
perp marketType Child Fields
| Child Field | Type | Required | Values | Description |
|---|---|---|---|---|
| marginMode | String | No; perp only | cross / isolated | Margin mode. When omitted, uses the current mode for the assetId; new positions default to cross. |
| positionSide | String | No | net / long / short / null | Position side. oneWay mode uses net; hedge mode uses long or short. perp only. |
Order Type Definitions
- Trigger Order: An independent strategy order that is not bound to a parent order or position. Once the trigger condition is met, an order is placed on the order book using the user-configured parameters.
- Order-Attached TPSL: A TPSL child order bound to a parent order. Whether it becomes active depends on the parent order status. A Reduce-Only parent order cannot include TPSL.
- Position-Attached TPSL: A TPSL child order bound to an associated position. Its status depends on the associated position status.
Order Placement Forms
| Form | grouping | orderType | reduceOnly | side | size |
|---|---|---|---|---|---|
| Standard Limit Order | na | limit, including tif | Optional | User-specified | User-specified and greater than 0. |
| Market Order, simulated with IOC/FOK | na | limit, with tif set to ioc or fok | Optional | User-specified | User-specified and greater than 0. |
| Standalone Trigger Order | na | trigger | Optional | User-specified buy or sell | User-specified and greater than 0. |
| Partial Position TPSL | positionTpsl | trigger | Automatically true | Automatically set opposite to the position side | User-specified and greater than 0. |
| Order-Attached TPSL | orderTpsl | trigger; TP may use TP Limit | Automatically true | Automatically set opposite to the parent order side | "0"; resolved from the parent order's filled size. |
| Entire Position TPSL | positionTpsl | trigger; SL supports market execution only; TP supports market execution or TP Limit | Automatically true | Automatically set opposite to the position side | "0"; resolved from the current position size. |
Trigger and TPSL Business Rules
- The trigger price of a standalone Trigger order must not equal the reference price. Otherwise, the order would trigger immediately after submission and be rejected.
- Order-Attached TPSL applies only to non-Reduce-Only market, limit, and Trigger parent orders.
- TPSL trigger-price direction:
- Position-Attached TPSL is evaluated against the reference price.
- Order-Attached TPSL is evaluated against the parent order price.
- For sell orders, TP must be above the reference price and SL must be below it.
- For buy orders, TP must be below the reference price and SL must be above it.
- SL cannot be placed directly as a limit order.
- TP may use Trigger or Limit.
- An SL Trigger order may execute at market or as a limit order after triggering.
- Each parent order may include at most one TP and one SL, and TPSL may be attached only to non-Reduce-Only Limit or Market parent orders.
- Position-Attached TPSL has two forms: Entire Position and Partial Position.
- Entire Position: Each position supports at most one TP and one SL. Both TP and SL support Trigger Market only.
size="0"and follows the position size. - Partial Position: The user specifies the size.
size>0and each order must not exceed the position size. Multiple TP and SL orders are allowed. - Partial Position TP supports Trigger Market, Trigger Limit, or TP Limit.
- Partial Position SL supports Trigger Market or Trigger Limit.
- Entire Position: Each position supports at most one TP and one SL. Both TP and SL support Trigger Market only.
- Unactivated or untriggered Trigger orders and attached TPSL orders count toward the maximum order count for each address.
- Related orders have different
oidvalues.parentOrderIdpoints to the direct parent order:- Parent order A ← TPSL child order B, where
B.parentOrderId=A. - TPSL child order B ← triggered execution order C, where
C.parentOrderId=B. - Automatically generated execution order C does not contain
clientOrderId. - User-submitted TPSL child order B may include
clientOrderId.
- Parent order A ← TPSL child order B, where
- A Position-Attached TP Limit is immediately converted into a Reduce-Only GTC Limit resting order; it does not wait for a price trigger.
- Use the live resting order's
oidfor queries, cancellation, and amendments.
- Use the live resting order's
- How to obtain a resting order
oid:mode=sync, the default mode: the placement response directly returns the resting order ID instatuses[].resting.oid.mode=async: query through the privateuser-order-statuschannel orGET /trade/transaction.
Request Example: Limit Order and Standalone Trigger Order
grouping="na".
{
"action": {
"type": "placeOrder",
"grouping": "na",
"orders": [
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "buy",
"price": "95000",
"size": "0.1",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": false,
"clientOrderId": "0x030000277b000001a02462e725000101",
"orderType": {
"limit": {
"tif": "gtc"
}
}
},
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "sell",
"price": "0",
"size": "0.1",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": false,
"orderType": {
"trigger": {
"isMarket": true,
"triggerPx": "49000",
"triggerPriceType": "mark",
"tpsl": "down"
}
}
}
]
},
"nonce": 1704067200000,
"expiresAfter": 1704067260000,
"user": "0x742d35cc...",
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
**Request Example: Order-Attached TPSL Order Group**
`grouping="orderTpsl"`, submitted in the same batch.
TPSL child orders are independent elements in `orders[]` and may each include an optional `clientOrderId`. A child order's `size` is fixed at `"0"` and is resolved from the parent order's filled size after the parent order is filled.
```json
{
"action": {
"type": "placeOrder",
"grouping": "orderTpsl",
"orders": [
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "buy",
"price": "95000",
"size": "0.1",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": false,
"clientOrderId": "0x030000277b000001a02462e725000201",
"orderType": {
"limit": {
"tif": "gtc"
}
}
},
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "sell",
"price": "0",
"size": "0",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": true,
"clientOrderId": "0x030000277b000001a02462e725000202",
"orderType": {
"trigger": {
"isMarket": true,
"triggerPx": "99000",
"triggerPriceType": "mark",
"tpsl": "tp"
}
}
},
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "sell",
"price": "0",
"size": "0",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": true,
"clientOrderId": "0x030000277b000001a02462e725000203",
"orderType": {
"trigger": {
"isMarket": true,
"triggerPx": "90000",
"triggerPriceType": "mark",
"tpsl": "sl"
}
}
}
]
},
"nonce": 1704067200000,
"user": "0x742d35cc...",
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
**Request Example: Order-Attached TPSL Order Group with TP Limit**
`grouping="orderTpsl"`.
For a TP Limit child order, `price` is the take-profit limit price. After the parent order is filled, the system places a Reduce-Only limit order at this price.
- `triggerPx` must be `"0"` and serves only as a sentinel; it does not mean that the trigger price is zero.
- `isMarket` must be `false`.
```json
{
"action": {
"type": "placeOrder",
"grouping": "orderTpsl",
"orders": [
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "buy",
"price": "95000",
"size": "0.1",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": false,
"clientOrderId": "0x030000277b000001a02462e725000301",
"orderType": {
"limit": {
"tif": "gtc"
}
}
},
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "sell",
"price": "105000",
"size": "0",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": true,
"orderType": {
"trigger": {
"isMarket": false,
"triggerPx": "0",
"triggerPriceType": "mark",
"tpsl": "tp",
"isTpLimit": true
}
}
},
{
"assetId": "102",
"marketType": {
"perp": {
"marginMode": "cross",
"positionSide": "long"
}
},
"side": "sell",
"price": "0",
"size": "0",
"sizeType": "base",
"priceAmendType": "noAmend",
"reduceOnly": true,
"orderType": {
"trigger": {
"isMarket": true,
"triggerPx": "90000",
"triggerPriceType": "mark",
"tpsl": "sl"
}
}
}
]
},
"nonce": 1704067200000,
"user": "0x742d35cc...",
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
POST /trade/cancel-order - Cancel Orders (Batch)#
Supports batch cancellation with a maximum of 30 orders per request.
- Each cancellation must provide either
oidorclientOrderId. assetIdandmarketTypemust match the target order.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | Object | Yes | Cancellation action. |
| > type | String | Yes | Must be cancel. |
| > cancels | Array | Yes | Orders to cancel. |
| >> assetId | String | Yes | Instrument ID. |
| >> marketType | String or Object | Yes | Market type; must match the target order. |
| >> oid | String | Conditionally | Order ID. Provide this or clientOrderId. |
| >> clientOrderId | String | Conditionally | Client Order ID. Provide this or oid. |
| nonce | Number | Yes | Current nonce. |
| user | String | No | Main-account address. |
| signature | Object | Yes | EIP-712 signature. |
{
"action": {
"type": "cancel",
"cancels": [
{
"assetId": "102",
"marketType": "perp",
"clientOrderId": "0xdeadbeef00000000deadbeef00000001"
},
{
"assetId": "102",
"marketType": "perp",
"oid": "77738308"
}
]
},
"nonce": 1704067200000,
"user": "0x742d35cc...",
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
POST /trade/modify-order - Modify Orders(Batch)#
Amends the price, size, trigger parameters, or supported order-type variant of existing orders. The unified modify action supports both single and batch amendments.
- A maximum of 30 amendments is supported per request.
- Each item is identified by
oidorclientOrderId. - Price amendments and size increases lose existing queue priority and enter the end of the relevant price-level queue.
- Size decreases retain existing queue priority.
- If the new
sizeis below the filled quantity, the system clamps the amended size to the filled quantity.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | Object | Yes | Amendment action. |
| > type | String | Yes | Must be modify. |
| > modifies | Array | Yes | Amendment list. |
| >> oid | String | Conditionally | Order ID. Provide this or clientOrderId. |
| >> clientOrderId | String | Conditionally | Client Order ID. Provide this or oid. |
| >> assetId | String | Yes | Instrument ID. |
| >> price | String | No | Amended order price. |
| >> size | String | No | Amended total order size. |
| >> orderType | Object | No | Required when amending order type or trigger parameters; provide the complete corresponding substructure. |
| nonce | Number | Yes | Current nonce. |
| user | String | No | Main-account address. |
| signature | Object | Yes | EIP-712 signature. |
Request Example
{
"action": {
"type": "modify",
"modifies": [
{
"clientOrderId": "0xdeadbeef00000000deadbeef00000001",
"assetId": "102",
"price": "50100",
"size": "0.2",
"orderType": {
"limit": {
"tif": "gtc"
}
}
}
]
},
"nonce": 1704067200000,
"user": "0x742d35cc...",
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
GET /trade/order - Get a Single Order#
Queries a single order by oid or clientOrderId. Provide exactly one of these parameters.
This endpoint only queries orders that have an on-chain order record. A rejected placement that did not produce an oid cannot be queried here; use GET /trade/transaction to retrieve the transaction receipt.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| oid | String | One of | On-chain order ID. Provide this or clientOrderId, but not both. |
| clientOrderId | String | One of | User-defined order ID. Provide this or oid, but not both. |
| vaultAddress | String | No | Omit for the main account; provide the subaccount address when operating a subaccount. |
Request Examples
GET /api/v5/exchangeos/trade/order?oid=77738308
GET /api/v5/exchangeos/trade/order?clientOrderId=0xdeadbeef00000000deadbeef00000001Response Fields
| Field | Type | Description |
|---|---|---|
| oid | String | On-chain order ID. |
| clientOrderId | String | User-defined order ID. |
| assetId | String | Instrument ID. |
| side | String | buy or sell. |
| marginMode | String | cross or isolated; applicable to perp only. spot and prediction return null. |
| reduceOnly | Boolean | Whether the order is Reduce-Only. |
| orderType | String | limit or trigger. |
| tif | String | gtc, ioc, fok, or alo. Trigger orders return null. |
| price | String | Order price. |
| size | String | Order size in base token units. |
| accFillSz | String | Cumulative filled size in base token units. |
| avgPx | String | Weighted average fill price; null when unfilled. |
| state | String | Order state. |
| triggerPx | String | Trigger price; null for non-Trigger orders. |
| triggerPriceType | String | mark or index; null for non-Trigger orders. |
| isMarket | Boolean | Whether execution after triggering is at market; null for non-Trigger orders. |
| tpsl | String | up, down, tp, or sl; null for non-Trigger orders. |
| grouping | String | na, orderTpsl, or positionTpsl. |
| parentOrderId | String | Direct parent order ID; null when no parent exists. |
| cancelReason | String | Cancellation reason; null when not cancelled. |
| cTime | String | Order creation time, Unix timestamp in milliseconds. |
| block_timestamp | String | Most recent status-update time, Unix timestamp in milliseconds. |
| block_height | String | Block height for the most recent status update. |
| txHash | String | On-chain transaction hash. |
GET /trade/orders-pending - Get Pending Orders#
Queries active standard resting orders, standalone Trigger orders, Position TPSL orders, and TP/SL orders attached to standard orders for the main account or a specified subaccount.
Only spot and perp are supported. Prediction Market and CeDeFi Swap are excluded.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| pointBoard | Boolean | No | true for points trading; false for live trading. |
| assetId | String | No | Filters by instrument ID. |
| vaultAddress | String | No | Omit for the main account; provide the subaccount address when operating a subaccount. |
Request Examples
GET /api/v5/exchangeos/trade/orders-pending
GET /api/v5/exchangeos/trade/orders-pending?assetId=102
GET /api/v5/exchangeos/trade/orders-pending?vaultAddress=0x6d1a19e1e03b83163fb38d7336b58875e71c50c2Response Fields
| Field | Type | Description |
|---|---|---|
| block_height | String | Block height corresponding to the query. |
| block_timestamp | String | Block timestamp corresponding to the query, in milliseconds. |
| data | Array | Pending-order list; returns an empty array when no orders exist. |
| > oid | String | On-chain order ID. |
| > clientOrderId | String | User-defined order ID; automatically generated execution children return an empty string. |
| > assetId | String | Instrument ID. |
| > assetStatus | String | Instrument status. |
| > side | String | buy or sell. |
| > positionSide | String | net, long, or short; Spot returns an empty string. |
| > marginMode | String | cross or isolated; Spot returns an empty string. |
| > leverage | String | Leverage multiplier; Spot or Equity equal to 0 returns an empty string. |
| > orderType | String | limit or trigger. |
| > tif | String | gtc, ioc, fok, alo, or gtd; Trigger orders return an empty string. |
| > price | String | Order price; Trigger Market returns an empty string. |
| > size | String | Order size in base token units. |
| > accFillSz | String | Cumulative filled size. |
| > state | String | open or partially_filled. |
| > reduceOnly | Boolean | Whether the order is Reduce-Only. |
| > parentOrderId | String | Direct parent order ID; an empty string when no parent exists. |
| > attachAlgoOrds | Array | Attached TP/SL child orders; at most two. |
| > triggerPx | String | Trigger price; an empty string when not applicable. |
| > triggerPriceType | String | mark or index; an empty string when not applicable. |
| > triggerCond | String | Gte or Lte; an empty string when not applicable. |
| > isMarket | Boolean | Whether execution after triggering is at market. |
| > tpsl | String | up, down, tp, or sl; an empty string when not applicable. |
| > tpLimit | Boolean | Whether the order is a TP Limit. |
Attached TPSL Fields
attachAlgoOrds child orders use the same order fields. isActive indicates whether the child order is active, and parentOrderId identifies the parent order.
Response Example
{
"code": "0",
"msg": "",
"data": [
{
"block_height": "11892975",
"block_timestamp": "1785062091486",
"data": [
{
"oid": "39933954",
"clientOrderId": "0x01a3f09c7e12b84d6590ef31ca762b4d",
"assetId": "1502",
"assetStatus": "normal",
"side": "buy",
"positionSide": "long",
"marginMode": "isolated",
"orderType": "limit",
"tif": "gtc",
"price": "96.0500",
"size": "1.00",
"accFillSz": "0.50",
"state": "partially_filled",
"reduceOnly": false,
"parentOrderId": "",
"attachAlgoOrds": [
{
"oid": "39933955",
"assetId": "1502",
"side": "sell",
"positionSide": "long",
"marginMode": "isolated",
"price": "200.0000",
"size": "1.00",
"reduceOnly": true,
"triggerPx": "200.0000",
"triggerPriceType": "mark",
"triggerCond": "Gte",
"isMarket": false,
"tpsl": "tp",
"parentOrderId": "39933954",
"isActive": false,
"tpLimit": true
}
],
"triggerPx": "",
"triggerPriceType": "",
"triggerCond": "",
"isMarket": false,
"tpsl": "",
"tpLimit": false
}
]
}
]
}
Get Order History GET /trade/orders-history#
Queries order-status transition history for the main account or a specified subaccount. Each state transition from creation through final state is returned as a separate snapshot.
Pagination Rules
- Records are returned in
data[0].data, ordered byblock_timestampfrom newest to oldest. - Use
nextCursoras the continuation token andhasMoreto determine whether another page exists. - Do not use a returned row count lower than
limitto determine the end of pagination. beginandendare time-window filters only. When sent withcursor, the cursor determines the starting point.- Records for the same
oidmay span pages. Aggregate event rows usingoid,state, andblock_timestamp. - Rejected placements without an
oidare excluded. QueryGET /trade/transactionbytxHashinstead.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| pointBoard | Boolean | No | true for points trading; false for live trading. |
| assetId | String | No | Filters by instrument ID. |
| state | String | No | Filters by order state. |
| begin | String | No | Start of the time window, in milliseconds. |
| end | String | No | End of the time window, in milliseconds. |
| cursor | String | No | Continuation token. Omit for the first page. |
| limit | String | No | Number of records to return; default and maximum are 100. |
| vaultAddress | String | No | Omit for the main account; provide the subaccount address for a subaccount. |
state Values
| Value | Description |
|---|---|
| open | Created successfully or entered the order book, including untriggered Trigger and TPSL orders. |
| partially_filled | Partially filled. |
| modified | Modified in place, such as a same-price size reduction; oid is unchanged. |
| filled | Fully filled. |
| triggered | Triggered successfully; the generated execution order is linked through children. |
| triggered_and_failed | Triggered successfully, but the execution order was not created. |
| failed | The execution order was created but placement failed. |
| canceled | Cancelled. |
| part_filled_canceled | Partially filled and remaining quantity cancelled. |
Parent-Child Order Relationships
parentOrderIdpoints only to the direct parent;childrenlists only direct children.- An Order-Attached TPSL chain is: parent order A → TPSL child B → triggered execution order C.
- User-submitted Trigger and TPSL orders may include
clientOrderId; automatically generated execution orders do not. - A Position TPSL has no parent order and returns
parentOrderId="". Its generated execution order points to that Position TPSL.
Response Example
Open a long position → set an Entire Position SL → trigger position close, plus one Spot fill, resulting in five records:
- Block 12092400: Order 88001 opens a long position and is fully filled immediately (taker; one
filledrecord; tradeId 776), resulting in a 602 long position of 1.5@3000. - Block 12092405: Entire Position SL 32733862 is placed (triggers when mark ≤ 2900 and closes the long position at market), producing an
openrecord. - Block 12092410: Spot sell order 88004 is filled immediately (one
filledrecord; tradeId 779). - Block 12092417: The price falls below 2900. Order 32733862 changes from
opentotriggered, withchildren=["90005"]; the chain automatically creates execution order 90005, which sells 1.5 at market to close the position and isfilled(tradeId 780, noclientOrderId, andparentOrderIdpoints to the SL order).
{
"code": "0",
"msg": "",
"data": [
{
"nextCursor": "",
"hasMore": false,
"data": [
{
"oid": "90005",
"clientOrderId": "",
"assetId": "602",
"side": "sell",
"positionSide": "long",
"marginMode": "isolated",
"orderType": "limit",
"tif": "ioc",
"price": "",
"size": "1.500",
"accFillSz": "1.500",
"avgPx": "2895.000",
"state": "filled",
"reduceOnly": true,
"parentOrderId": "32733862",
"children": [],
"triggerPx": "",
"triggerPriceType": "",
"triggerCond": "",
"isMarket": false,
"tpsl": "",
"tpLimit": false,
"cancelReason": "",
"block_height": "12092417",
"block_timestamp": "1785218400074"
},
{
"oid": "32733862",
"clientOrderId": "0x01a2b3c4d5e6f7089a0b1c2d3e4f5060",
"assetId": "602",
"side": "sell",
"positionSide": "long",
"marginMode": "isolated",
"orderType": "trigger",
"tif": "",
"price": "",
"size": "0",
"accFillSz": "0",
"avgPx": "",
"state": "triggered",
"reduceOnly": true,
"parentOrderId": "",
"children": [
"90005"
],
"triggerPx": "2900.000",
"triggerPriceType": "mark",
"triggerCond": "Lte",
"isMarket": true,
"tpsl": "sl",
"tpLimit": false,
"cancelReason": "",
"block_height": "12092417",
"block_timestamp": "1785218400074"
},
{
"oid": "88004",
"clientOrderId": "0x01eac095b61842df730259ec48a3fb7d",
"assetId": "301",
"side": "sell",
"positionSide": "",
"marginMode": "",
"orderType": "limit",
"tif": "gtc",
"price": "80000.000000",
"size": "0.050000",
"accFillSz": "0.050000",
"avgPx": "80000.000000",
"state": "filled",
"reduceOnly": false,
"parentOrderId": "",
"children": [],
"triggerPx": "",
"triggerPriceType": "",
"triggerCond": "",
"isMarket": false,
"tpsl": "",
"tpLimit": false,
"cancelReason": "",
"block_height": "12092410",
"block_timestamp": "1785218399800"
},
{
"oid": "32733862",
"clientOrderId": "0x01a2b3c4d5e6f7089a0b1c2d3e4f5060",
"assetId": "602",
"side": "sell",
"positionSide": "long",
"marginMode": "isolated",
"orderType": "trigger",
"tif": "",
"price": "",
"size": "0",
"accFillSz": "0",
"avgPx": "",
"state": "open",
"reduceOnly": true,
"parentOrderId": "",
"children": [],
"triggerPx": "2900.000",
"triggerPriceType": "mark",
"triggerCond": "Lte",
"isMarket": true,
"tpsl": "sl",
"tpLimit": false,
"cancelReason": "",
"block_height": "12092405",
"block_timestamp": "1785218399500"
},
{
"oid": "88001",
"clientOrderId": "0x01b7c8d9e0f1a2b3c4d5e6f708192021",
"assetId": "602",
"side": "buy",
"positionSide": "long",
"marginMode": "isolated",
"orderType": "limit",
"tif": "gtc",
"price": "3000.000",
"size": "1.500",
"accFillSz": "1.500",
"avgPx": "3000.000",
"state": "filled",
"reduceOnly": false,
"parentOrderId": "",
"children": [],
"triggerPx": "",
"triggerPriceType": "",
"triggerCond": "",
"isMarket": false,
"tpsl": "",
"tpLimit": false,
"cancelReason": "",
"block_height": "12092400",
"block_timestamp": "1785218399000"
}
]
}
]
}
Pagination response format when additional records are available. The content of data[0].data is the same as above:
{
"code": "0",
"msg": "",
"data": [
{
"nextCursor": "1"
}
]
}
GET /trade/fills - Get Fills#
Queries fill details for the main account or a specified subaccount.
Pagination Rules
- Fill records are returned in
data[0].data[]. - Pagination fields are
data[0].hasMoreanddata[0].nextCursor. - Records are ordered by
block_timestampfrom newest to oldest. - Omit
cursoron the first request. For later pages, return the preceding page'snextCursorunchanged. nextCursoris opaque; do not parse, compare, or construct it.hasMore=falseandnextCursor=""indicate the final page.- Multiple fills may share a millisecond timestamp. Do not use the returned row count to determine pagination completion.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| pointBoard | Boolean | No | true for points trading; false for live trading. |
| assetId | String | No | Filters by instrument ID. |
| begin | String | No | Start of the time window, in milliseconds. |
| end | String | No | End of the time window, in milliseconds. |
| cursor | String | No | Continuation token. |
| limit | String | No | Number of records to return; default and maximum are 100. |
| vaultAddress | String | No | Omit for the main account; provide the subaccount address for a subaccount. |
Response Fields
| Field | Type | Description |
|---|---|---|
| tradeId | String | Trade ID. |
| oid | String | Order ID. |
| clientOrderId | String | Client Order ID. |
| assetId | String | Instrument ID. |
| side | String | Order side. |
| execType | String | Execution role, such as maker or taker. |
| price | String | Fill price. |
| size | String | Fill size. |
| fee | String | Trading fee. |
| feeTokenId | String | Fee token ID. |
| rebate | String | Rebate amount. |
| rebateTokenId | String | Rebate token ID. |
| closedPnl | String | Realized PnL. |
| fillDir | String | Fill direction or business type. |
| startPosition | String | Position size before the fill. |
| block_timestamp | String | Block timestamp in milliseconds. |
| block_height | String | Block height. |
fillDir Values
| Value | Description |
|---|---|
| Buy | Buyer-side fill. |
| Sell | Seller-side fill. |
| BuySplit | Implicit split when both parties are buyers. |
| SellMerge | Implicit merge when both parties are sellers. |
| BackstopLiquidation | Insurance fund takes over a losing position in liquidation. |
| BackstopLiquidator | Insurance fund acts as liquidity provider in liquidation. |
| Adl | Auto-deleveraging fill. |
| AdlOpponent | Auto-deleveraging counterparty fill. |
| AdlPreviousPrice | Auto-deleveraging fill at a previous price. |
| AdlOpponentPreviousPrice | Auto-deleveraging counterparty fill at a previous price. |
| NetLiquidation | Net liquidation fill. |
| NetAdl | Net auto-deleveraging fill. |
| Settlement | Settlement fill. |
| Open | Perpetual position opening or increase in the same direction. |
| Close | Perpetual position close. |
| ReverseOpen | Closes an existing position and opens one in the opposite direction. |
| DecimalAdjustSettle | Decimal-adjustment settlement fill; not emitted in the current version. |
| DecimalAdjustTakeover | Decimal-adjustment takeover fill; not emitted in the current version. |
POST /account/account-transfer - Transfer Between Main and Subaccounts#
Transfers assets between a main account and its subaccounts.
- Supported directions are main account to subaccount and subaccount to main account.
- Direct transfers between subaccounts are not supported.
isDepositdetermines transfer direction; direction is not inferred from address order.- The request must be signed by an authorized, active, and unexpired OpenAPI Agent of the main account.
useris the main-account address;subAccountUseris the subaccount address.- Only available assets of the source account can be transferred. Rejected requests do not change balances.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| action | Object | Yes | Transfer action. |
| > type | String | Yes | Must be subAccountTransfer. |
| > subAccountUser | String | Yes | Subaccount address. |
| > isDeposit | Boolean | Yes | true: main account to subaccount; false: subaccount to main account. |
| > tokenId | String | Yes | Token ID. |
| > amount | String | Yes | Transfer amount. |
| nonce | Number | Yes | Current nonce. |
| expiresAfter | Number | No | Request expiry time, Unix timestamp in milliseconds. |
| user | String | Yes | Main-account address. |
| signature | Object | Yes | EIP-712 signature. |
Request Example: Main Account to Subaccount
{
"action": {
"type": "subAccountTransfer",
"subAccountUser": "0x1111111111111111111111111111111111111111",
"isDeposit": true,
"tokenId": "0",
"amount": "0.5"
},
"nonce": 1704067200000,
"expiresAfter": 1704067260000,
"user": "0x2222222222222222222222222222222222222222",
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
Request Example: Subaccount to Main Account
{
"action": {
"type": "subAccountTransfer",
"subAccountUser": "0x1111111111111111111111111111111111111111",
"isDeposit": false,
"tokenId": "0",
"amount": "0.5"
},
"nonce": 1704067200000,
"expiresAfter": 1704067260000,
"user": "0x2222222222222222222222222222222222222222",
"signature": {
"Ecdsa": {
"r": "0x...",
"s": "0x...",
"v": 1
}
}
}
GET /trade/transaction - On-Chain Transaction Receipt#
Retrieves the on-chain confirmation result and standardized execution receipt for a submitted transaction.
GET /api/v5/exchangeos/trade/transaction
Request Parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
| txHash | Query | String | Yes | Transaction hash in the format of 0x followed by 64 hexadecimal characters. |
Request Example
GET /api/v5/exchangeos/trade/transaction?txHash=0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
OK-ACCESS-KEY: {{apiKey}}
OK-ACCESS-SIGN: {{sign}}
OK-ACCESS-TIMESTAMP: {{timestamp}}
OK-ACCESS-PASSPHRASE: {{passphrase}}Standard Response Structure
{
"code": "0",
"msg": "",
"data": [
{
"txHash": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"blockHeight": "3588863",
"blockHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"txIndex": "12",
"status": "ok",
"response": {
"type": "order",
"data": {
"statuses": []
}
}
}
]
}
Envelope Response Fields
| Field | Type | Description |
|---|---|---|
| code | String | OpenAPI query result. "0" indicates that the on-chain receipt was retrieved successfully. |
| msg | String | Description of the OpenAPI query result. Empty on success. |
| data | Array | Contains one transaction receipt on success; an empty array is returned for API-level errors. |
Transaction Receipt Fields
| Field | Type | Always Present | Description |
|---|---|---|---|
| txHash | String | Yes | Transaction hash. |
| blockHeight | String | Yes | Confirmed block height. Returned as a string to avoid JavaScript u64 precision loss. |
| blockHash | String | Yes | Confirmed block hash. |
| txIndex | String | Yes | Transaction index in the block. Returned as a string. |
| status | String | Yes | Status of the entire on-chain transaction: ok or err. |
| response | Object | No | On-chain execution result. Omitted for successful Empty responses. |
Status Semantics
Clients must evaluate the following three status levels independently. A result at an upper level must not be used to bypass evaluation at a lower level:
code: Whether the OpenAPI query itself succeeded.data[0].status: Whether the entire on-chain transaction executed successfully.data[0].response.data.statuses[]: The execution result of each item in a batch place, cancel, or modify operation.
For example, envelope-level code="0" only means that the receipt was successfully retrieved. The on-chain transaction has still failed if status="err".
For batch order placement, when status="ok", individual orders may still be resting, filled, or error. Even if every entry in statuses[] is error, the transaction is still considered successfully executed; all orders were simply rejected by business rules. Order results must always be determined item by item from statuses[], not inferred from status.
A resting result may represent an unfilled or partially filled resting order.
Standard response Union Types
Entire Transaction Failure: status="err"
In this case, response is always an error object and does not include type or data:
{
"code": "0",
"msg": "",
"data": [
{
"txHash": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"blockHeight": "3588863",
"blockHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"txIndex": "12",
"status": "err",
"response": {
"code": "30004",
"message": "Nonce validation failed"
}
}
]
}
| Field | Type | Description |
|---|---|---|
| response.code | String | On-chain error code. |
| response.message | String | On-chain error reason. |
Successful Response Without Data: status="ok" + Empty
Some Actions return no additional data after succeeding. The receipt remains valid, and the response field is omitted:
{
"code": "0",
"msg": "",
"data": [
{
"txHash": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"blockHeight": "3588863",
"blockHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"txIndex": "12",
"status": "ok"
}
]
}
Clients must not treat a missing response as an error. Use status="ok" to determine that the transaction succeeded.
Successful Response With Data: status="ok" + {type,data}
{
"type": "order",
"data": {}
}
The following response.type values may appear for ExchangeOS OpenAPI user-trading and account-configuration operations:
| type | Meaning of data | Source Action |
|---|---|---|
| order | Batch order placement result. | placeOrder |
| cancel | Batch cancellation result. | cancel, cancelAll |
| modify | Batch order modification result. | modify |
| createSubAccount | Address of the successfully created sub-account. | createSubAccount |
Scope Summary
The current public scope includes 16 OpenAPI ActionTypes, corresponding to 14 distinct on-chain type values:
- Actions with a structured
response:placeOrder,cancel,cancelAll,modify, andcreateSubAccount. - Actions that return Empty after succeeding:
reserveRequestWeight,subAccountTransfer,updateLeverage,updateMarginMode,updatePositionMode, andupdateIsolatedMargin.
The standardized examples for each type follow this structure:
{
"status": "ok",
"response": {
"type": "<type>",
"data": {}
}
}
order
data.statuses maps one-to-one to the original batch placement array by index. Each item contains exactly one branch: resting, filled, or error.
Complete example:
{
"code": "0",
"msg": "",
"data": [
{
"txHash": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"blockHeight": "3588863",
"blockHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"txIndex": "12",
"status": "ok",
"response": {
"type": "order",
"data": {
"statuses": [
{
"resting": {
"oid": "3588863",
"clientOrderId": "0x030000277b0000019fd9e97db9000000"
}
},
{
"filled": {
"oid": "3588864",
"clientOrderId": "0x030000277b0000019fd9e97db9000001",
"avgPx": "0.65",
"totalSz": "100"
}
},
{
"error": {
"code": "30043",
"message": "order price is outside the permitted band [0.9813, 1.0375]"
}
}
]
}
}
}
]
}
resting` Fields
The order was successfully placed on the order book but has not been filled.
| Field | Type | Always Present | Description |
|---|---|---|---|
| oid | String | Yes | On-chain order ID. |
| clientOrderId | String | No | Client order ID. |
| adjustedSz | String | No | Order size adjusted by the chain. |
filled` Fields
The order has executions, including partial fills.
| Field | Type | Always Present | Description |
|---|---|---|---|
| oid | String | Yes | On-chain order ID. |
| clientOrderId | String | No | Client order ID. |
| avgPx | String | Yes | Average execution price. |
| totalSz | String | Yes | Total filled size. |
| adjustedSz | String | No | Order size adjusted by the chain. |
error` Fields
| Field | Type | Description |
|---|---|---|
| code | String | Per-order placement error code. |
| message | String | Per-order placement error reason. |
cancel
data.statuses maps one-to-one to the original batch cancellation array by index. A successful item is the string "success"; a failed item is an error object.
{
"type": "cancel",
"data": {
"statuses": [
"success",
{
"error": {
"code": "30010",
"message": "order not found"
}
}
]
}
}
"success" is a valid member of the on-chain standard union type; it does not indicate missing structured data. Clients should parse items by element type: a string indicates success, while an object indicates failure.
modify
data.statuses maps one-to-one to the original batch modification array by index. Each item can be one of the following:
"success"{"successWithAdjustment":{"adjustedSz":"..."}}{"error":{"code":"...","message":"..."}}
{
"type": "modify",
"data": {
"statuses": [
"success",
{
"successWithAdjustment": {
"adjustedSz": "60"
}
},
{
"error": {
"code": "30000",
"message": "invalid transaction"
}
}
]
}
}
Parsing Recommendations
if envelope.code != "0":
if envelope.code == "80106":
retry_later()
else:
handle_query_error(envelope.code, envelope.msg)
return
receipt = envelope.data[0]
if receipt.status == "err":
handle_transaction_error(receipt.response.code, receipt.response.message)
return
if receipt.response is absent:
handle_empty_success()
return
switch receipt.response.type:
case "order":
case "cancel":
case "modify":
for status in receipt.response.data.statuses:
handle_positional_item(status)
case "createSubAccount":
handle_created_sub_account(receipt.response.data)Notes
statuses[n]always corresponds to itemnin the request batch. Do not filter successful or failed items before associating them with the original request.- In union types, inactive fields are omitted. For example, a
restingitem does not also includefilled: nullorerror: null. - Optional fields are omitted when absent; they are not returned as empty strings.
- IDs, prices, sizes, block heights, indices, and error codes must all be handled as strings.
- Do not determine on-chain transaction success solely from envelope-level
code="0".
- POST /trade/noop - Invalidate a Specified NoncePOST /trade/place-order - Place OrdersPOST /trade/cancel-order - Cancel Orders (Batch)POST /trade/modify-order - Modify Orders(Batch)GET /trade/order - Get a Single OrderGET /trade/orders-pending - Get Pending OrdersGet Order History GET /trade/orders-historyGET /trade/fills - Get FillsPOST /account/account-transfer - Transfer Between Main and SubaccountsGET /trade/transaction - On-Chain Transaction Receipt
