Private WebSocket Subscription Guidelines
All private channels are subscribed to through the WebSocket subscribe operation. Unless stated otherwise, id is client-defined; use vaultAddress for a sub-account, pointBoard defaults to false, and marketTypes defaults to all markets.
Backend Connection Prewarming (connect_backends)
ExchangeOS private channels support establishing Backend connections before subscription to reduce latency for the first subscription and the first data push. The Backend for ExchangeOS private channels is okx-defi-tradezone-indexerpubsub-awstky-pro. connect_backends only prewarms the connection; it does not create a channel subscription or replace subscribe.
After login succeeds and before sending subscribe, clients may send:
A successful connect_backends request does not return a synchronous request-level success response. The Backend connection is established only after the following asynchronous event is received:
Recommended sequence: establish the WebSocket connection → complete private-channel login → send connect_backends → wait for event=backend with code=0 → send subscribe → receive event=subscribe → receive channel data.
connect_backends is an optional connection-prewarming mechanism. If the client does not send it, the first subscribe still triggers lazy connection establishment and the existing subscription flow continues to work. The event order is event=backend with code=0 → event=subscribe → channel data.
Backend Connection Status Event (event: backend)
event=backend is a server-initiated event that reports the connection status of a Backend. It is neither a response to a specific request nor channel data.
This event informs clients that the connection between the push service and a Backend has been interrupted, or that the connection and subscriptions have been restored. The push service automatically reconnects and restores subscriptions; clients do not need to resend connect_backends or subscribe.
Trigger Conditions
| Status | Trigger Scenario | code | msg |
|---|
| Backend connection established for the first time | Triggered by connect_backends, or by lazy connection establishment initiated through send/subscribe, and the Backend connection is successfully established. | 0 | Success |
| Backend connection disconnected unexpectedly | The push service receives a gRPC onError. The WebSocket remains active, while the push service starts automatic reconnection and subscription recovery. | 50011 | Backend stream disconnected |
| Backend connection closed by the server | The push service receives a gRPC onCompleted. The WebSocket remains active, while the push service starts automatic reconnection and subscription recovery. | 50012 | Backend stream completed by server |
| Backend connection and subscriptions restored | The push service completes reconnection and automatically restores active subscriptions for that Backend. | 0 | Success |
| Field | Description |
|---|
event | Always backend. |
code | 0: connection established; 50011: abnormal disconnection; 50012: server-side closure. |
msg | Status description. |
backend | Identifier of the Backend whose status changed. |
extraInfo | Reserved field; currently always an empty string. |
connId | Current WebSocket connection ID. |
Client Handling Guidelines
event=backend does not mean that the WebSocket connection has closed. The WebSocket remains active; only the connection between the push service and a Backend has changed.
- After receiving
code=50011 or code=50012, clients do not need to resend connect_backends or subscribe, and do not need to close or recreate the WebSocket connection. The push service automatically reconnects to the Backend and restores subscriptions.
- Clients without data-reconciliation requirements may simply recognize, log, or ignore
event=backend; no additional handling is required.
- Automatic recovery only ensures that messages continue after recovery. It cannot replay business messages missed while the Backend connection was unavailable.
- Clients that require data completeness for orders, fills, positions, assets, or similar data may record the timestamps of
code=50011/50012 and the subsequent code=0. After receiving the recovery event, they may query the latest state through the relevant REST APIs, reconcile data, or perform business-level recovery.
- If the WebSocket connection itself is closed, follow the existing WebSocket reconnection, login, and resubscription flow. A WebSocket disconnection and a Backend downstream connection interruption represented by
event=backend are different conditions.
exchangeos-balance-and-position - Scheduled Account and Position Snapshots
Pushes a complete account and position snapshot every 5 seconds. Periodic snapshots do not include Position tradeId.
The request id can be user-defined.
Subscribe
| Parameter | Type | Required | Description |
|---|
id | String | Yes | A user-defined request ID. |
op | String | Yes | Fixed value: subscribe. |
args | Array | Yes | Subscription argument list. |
> channel | String | Yes | Fixed value: exchangeos-balance-and-position. |
> vaultAddress | String | No | Sub-account address. Omit this field to subscribe to the master account. |
> pointBoard | String | No | true for the points board and false for the live board. Default: false. |
> marketTypes | String | No | Market type filter, for example ["spot", "perp"]. Defaults to all supported market types. |
type, curPage, lastPage, totalCount, and activeCount are located inside data.
data is an object. Do not expect the format data: [{ "orders": [] }].
- All pages in the same snapshot cycle have the same
block_height, block_timestamp, totalCount, and activeCount.
pTime represents the actual generation time of each page and can differ across pages.
- Clients should collect all pages and apply the snapshot atomically after receiving
lastPage=true.
- When there are no applicable records, the channel still returns empty arrays and corresponding zero counts.
Top-Level Push Fields
| Field | Type | Description |
|---|
arg | Object | Subscription information. |
> channel | String | Fixed value: exchangeos-balance-and-position. |
> vaultAddress | String | Sub-account address. Omitted when subscribing to the master account. |
> marketTypes | String | Market type filter used for the subscription. |
> pointBoard | String | Board type used for the subscription. |
backend | String | Backend identifier that serves the subscription. |
block_height | String | On-chain block height for this snapshot. |
block_timestamp | String | On-chain block timestamp for this snapshot, in Unix milliseconds. |
pTime | String | Actual WebSocket message generation time, in Unix milliseconds. |
user | String | Master-account or sub-account address associated with this snapshot. |
data | Object | Complete account and position snapshot. |
data Fields
| Field | Type | Description |
|---|
type | String | Fixed value: snapshot. |
curPage | String | Current snapshot page number. |
lastPage | Boolean | Whether this is the final page of the current snapshot cycle. |
assetsCnt | String | Total number of token records in the complete snapshot. |
positionsCnt | String | Total number of position records in the complete snapshot. |
totalEq | String | Total account equity. Includes all business lines; perp includes cross and isolated equity. |
notionalUsd | String | Total account-level position notional value in USD. |
positionMode | String | Position mode: oneWay or hedge. |
details | Array | Token balance details. Tokens with both cashBal and eq equal to 0 are omitted, except USDS. |
positions | Array | perpetual position details. |
details[] Fields
| Field | Type | Description |
|---|
tokenId | String | Token ID. |
collateralEnabled | Boolean | Whether the token can be used as collateral. |
cashBal | String | Token balance, including funds frozen by perp and spot orders. |
availBal | String | Available token balance. Only collateral tokens have a value. |
frozenMgn | String | Total frozen amount. For collateral tokens, includes spot, perp, and Prediction Market frozen amounts. For non-collateral tokens, includes only spot and Prediction Market frozen amounts. |
frozenMgnRatio | String | Frozen margin ratio. |
perpFrozen | String | Margin frozen by perp positions and open orders. |
spotFrozen | String | Amount frozen by spot open orders. |
predFrozen | String | Amount frozen by Prediction Market activity. |
lastPx | String | Latest trade price. Returns an empty string when unavailable. |
tokenPx | String | Token USD price. spot USD valuation uses tokenPx first, then lastPx if unavailable. |
marketType | String | Market type. |
accAvgPx | String | Average acquisition cost. |
spotUpl | String | spot unrealized profit and loss. |
entryCost | String | Total spot holding cost. |
spotUplRatio | String | spot unrealized profit and loss ratio. |
availEq | String | Available margin. |
upl | String | Cross-margin unrealized profit and loss. |
eq | String | Total cross-margin and isolated-margin equity. |
eqUsd | String | USD value of eq, calculated using eq * tokenPx. |
isoUpl | String | Isolated-margin unrealized profit and loss. |
isoEq | String | Total isolated-margin equity. |
totalLever | String | Position leverage calculated as coinPosValue / coinEquity. Returns an empty string when unavailable. |
mmr | String | Maintenance margin. It is the sum of position maintenance margins and liquidation fees, excluding isolated margin. |
mgnRatio | String | Maintenance margin ratio. Returns an empty string when unavailable. |
positions[] Fields
| Field | Type | Description |
|---|
assetId | String | Asset ID. |
positionSide | String | Position side: net, long, or short. net is used in one-way mode; long and short are used in hedge mode. |
marginMode | String | Margin mode: cross or isolated. |
pos | String | Position size. |
leverage | String | Leverage. Only integer leverage is supported. Returns an empty string when equity is 0. |
avgPx | String | Average position price. |
fundingFee | String | Cumulative funding fee since the position was opened. |
imr | String | Initial margin. For cross margin, calculated as notional value divided by leverage. Returns an empty string when the mark price is unavailable. |
mmr | String | Maintenance margin. |
mgnRatio | String | Maintenance margin ratio. For cross margin, it uses the token-level maintenance margin ratio; for isolated margin, it is calculated from the position. |
markPx | String | Mark price. |
lastPx | String | Latest trade price. |
idxPx | String | Latest index price for the underlying. Returns an empty string when unavailable. |
positionValue | String | Position value in USD. |
quoteUsdPx | String | USD price of the quote token. |
liqPx | String | Estimated liquidation price. |
upl | String | Unrealized profit and loss calculated using the mark price. |
uplRatio | String | Unrealized profit and loss ratio calculated using the mark price. |
uplLastPx | String | Unrealized profit and loss calculated using the latest trade price. |
uplRatioLastPx | String | Unrealized profit and loss ratio calculated using the latest trade price. |
margin | String | Isolated margin balance. Returns an empty string for cross-margin positions. |
pnl | String | Closed-position profit and loss. |
realizedPnl | String | Realized profit and loss. |
fee | String | Cumulative trading fee for the position. |
closeOrderAlgo | Array | Position TP/SL orders. |
tpLimitOrders | Array | Position TP Limit orders. |
assetStatus | String | Contract status: normal, scheduled, converging, or regressing. |
closeOrderAlgo[] Fields
| Field | Type | Description |
|---|
oid | String | On-chain order ID. |
assetId | String | Associated perp asset ID. |
assetStatus | String | Contract status. |
cTime | String | Order creation time, in Unix milliseconds. |
side | String | Closing-order side: buy or sell. |
positionSide | String | Associated position side: net, long, or short. |
marginMode | String | Associated margin mode: cross or isolated. |
leverage | String | Position leverage. |
size | String | Closing size, measured in base currency units. |
reduceOnly | Boolean | Whether the order is reduce-only. |
triggerPx | String | Trigger price. |
triggerPriceType | String | Trigger price type: mark or index. |
triggerCond | String | Trigger condition: gte or lte. |
isMarket | Boolean | Whether the order is executed at market after it is triggered. |
tpsl | String | TPSL type: tp or sl. |
tpLimit | Boolean | Whether this is a TP Limit order. |
isActive | Boolean | Whether the TP/SL order is active. |
tpLimitOrders[] Fields
| Field | Type | Description |
|---|
oid | String | On-chain order ID. |
assetId | String | Associated perp asset ID. |
assetStatus | String | Contract status. |
cTime | String | Order creation time, in Unix milliseconds. |
side | String | Closing-order side: buy or sell. |
positionSide | String | Associated position side. |
marginMode | String | Associated margin mode. |
leverage | String | Position leverage. |
price | String | TP Limit order price. |
size | String | Order size, measured in base currency units. |
accFillSz | String | Cumulative filled size. |
reduceOnly | Boolean | Whether the order is reduce-only. |
tpsl | String | Fixed value: tp. |
tpLimit | Boolean | Fixed value: true. |
Response Example
Account and Position Event Updates exchangeos-balance-and-position-updates
A private account and position update channel for Open API developers.
After a successful subscription, the channel pushes incremental data by event whenever balance, Position, or account data changes.
When a Position is fully closed, the incremental update still returns that Position with pos set to "0".
The subscription request id can be user-defined.
Subscribe to the Master Account
Subscribe to a Sub-account
Subscription Parameters
| Parameter | Type | Required | Description |
|---|
id | String | Yes | User-defined request ID. |
op | String | Yes | Fixed value: subscribe. |
args | Array | Yes | Subscription argument list. |
> channel | String | Yes | Fixed value: exchangeos-balance-and-position-updates. |
> vaultAddress | String | No | Sub-account address. Omit when subscribing to the master account. |
> pointBoard | String | No | true for the points board and false for the live board. Default: false. |
> marketTypes | String | No | Market types, for example ["spot", "perp"]. All market types are returned by default. |
Top-Level Push Fields
| Field | Type | Description |
|---|
arg | Object | Subscription information. |
> channel | String | Fixed value: exchangeos-balance-and-position-updates. |
> vaultAddress | String | Sub-account address. Omitted when subscribing to the master account. |
block_height | String | On-chain block height associated with this update. |
block_timestamp | String | On-chain block time associated with this update, in Unix milliseconds. It has the same semantics as uTime and is the data version for data.details[] and data.positions[]. |
pTime | String | Actual WebSocket message generation or push time, in Unix milliseconds. Not used for data deduplication. |
user | String | Master-account or sub-account address associated with this update. |
data | Object | The first message is a complete account snapshot. Subsequent messages contain account, Token, and Position updates involved in the event. type is located inside data. |
data Fields
| Field | Type | Description |
|---|
type | String | Data mode: snapshot or update. |
eventType | String | Business event type that caused this data update. |
totalEq | String | Total live-account equity in USD after the event is processed. Excludes points-board assets. |
notionalUsd | String | Sum of the absolute USD notional values of all perp positions after the event is processed. Includes cross and isolated positions. Hedge-mode long and short positions are not netted. Excludes open orders. |
positionMode | String | Account position mode: oneWay or hedge. |
details | Array | Latest state of Tokens involved in this event. |
positions | Array | Latest state of perp Positions involved in this event. |
trades | Array | Trade identifier list involved in this event. Returns [] for the initial snapshot or when there are no ordinary matching trades. |
type and eventType have different meanings:
data.type indicates the data mode: snapshot or update.
data.eventType indicates the business event that caused this incremental update.
- When
type="snapshot", eventType returns "". Do not use eventType to determine whether data is a full snapshot or an incremental update.
details[] Fields
| Field | Type | Description |
|---|
tokenId | String | Token ID. USDS is "0". |
marketType | String | Market type. |
collateralEnabled | Boolean | Whether the Token can be used as collateral. USDS and independent points-board Tokens can be true; standard spot Tokens are false. |
eq | String | Total Token equity in native Token units. For collateral Tokens, this is the sum of cross-margin and isolated-margin equity. |
eqUsd | String | Total Token equity valuation. Live-board Tokens are converted to USD; points-board Tokens use the display convention of 1 Point = 1 USD. |
isoEq | String | Isolated-margin equity in native collateral Token units. Returns "" for non-collateral Tokens. |
cashBal | String | Token balance in native Token units, including frozen amounts. |
availBal | String | Available Token balance in native Token units. |
availEq | String | Available cross-margin collateral. Returns "" for non-collateral Tokens. |
frozenMgn | String | Total Token amount in use, equal to spotFrozen + perpFrozen + predFrozen. |
spotFrozen | String | Amount reserved by spot open orders, in native Token units. |
perpFrozen | String | Amount used by perp cross-margin positions and open orders. Includes isolated-margin open-order usage but excludes isolated-position margin. Returns "" for non-collateral Tokens. |
predFrozen | String | Amount used by Prediction Market activity, in native Token units. |
mmr | String | Cross-margin maintenance margin. Excludes isolated margin. Returns "" for non-collateral Tokens. |
mgnRatio | String | Cross-margin maintenance margin ratio. Returns "" for non-collateral Tokens. |
frozenMgnRatio | String | Cross-margin funds utilization ratio. Returns "" for non-collateral Tokens. |
accAvgPx | String | spot cumulative average cost price. The Phase 1 real-time channel always returns "". |
spotUpl | String | spot unrealized profit and loss. The Phase 1 real-time channel always returns "". |
spotUplRatio | String | spot unrealized profit and loss ratio. The Phase 1 real-time channel always returns "". |
entryCost | String | Total spot cost. The Phase 1 real-time channel always returns "". |
upl | String | perp cross-margin unrealized profit and loss. Returns "" for non-collateral Tokens. |
isoUpl | String | perp isolated-margin unrealized profit and loss. Returns "" for non-collateral Tokens. |
lastPx | String | Latest spot trade price for this Token. Returns "" when no trade price is available. |
tokenPx | String | USD valuation price of this Token. Returns "" when no valuation price is available. |
totalLever | String | Total cross-margin leverage for this collateral Token. Returns "" for non-collateral Tokens, when not applicable, or when unavailable. |
positions[] Fields
| Field | Type | Description |
|---|
assetId | String | Perp product ID. |
assetStatus | String | Contract status: normal, scheduled, converging, or regressing. |
positionSide | String | Position side: net, long, or short. |
marginMode | String | Margin mode: cross or isolated. |
leverage | String | Position leverage. |
pos | String | Position size in base units. A fully closed Position in an incremental event returns "0". |
avgPx | String | Average entry price. |
markPx | String | Mark price. |
positionValue | String | Position notional value in USD. |
upl | String | Unrealized profit and loss. |
uplRatio | String | Unrealized profit and loss ratio. |
liqPx | String | Estimated liquidation price. Returns "" when unavailable. |
imr | String | Cross-margin initial margin. Returns "" for isolated margin. |
margin | String | Isolated-margin balance. Returns "" for cross margin. |
mmr | String | Maintenance margin. |
mgnRatio | String | Maintenance margin ratio. |
realizedPnl | String | Realized profit and loss. |
fee | String | Cumulative trading fees. |
fundingFee | String | Cumulative funding fees since the position was opened. |
lastPx | String | Latest trade price. Used for display only and not as a risk-control or deduplication reference. |
idxPx | String | Latest index price for the underlying. Returns "" when no index price is available. |
quoteUsdPx | String | USD price of the quote Token. |
pnl | String | Closed-position profit and loss. |
uplLastPx | String | Unrealized profit and loss calculated using the latest trade price. |
uplRatioLastPx | String | Unrealized profit and loss ratio calculated using the latest trade price. |
closeOrderAlgo | Array | Position TPSL orders associated with this Position. Returns [] when there are no associated orders. |
closeOrderAlgo[] Fields
| Field | Type | Description |
|---|
oid | String | On-chain order ID of the Position TPSL. |
assetId | String | perp product ID of the associated Position. |
assetStatus | String | Product status: normal, scheduled, converging, or regressing. |
side | String | Closing-order side: buy or sell. |
positionSide | String | Associated position side: net, long, or short. |
marginMode | String | Margin mode of the associated Position: cross or isolated. |
price | String | Order price after triggering. Trigger Market returns "0". |
size | String | Closing size after triggering, in base units. Entire Position TPSL can return "0" and is executed using the actual position size at the time of the on-chain trigger. |
reduceOnly | Boolean | Whether the order is reduce-only. Position TPSL is always true. |
triggerPx | String | Trigger price. |
triggerPriceType | String | Trigger price type: mark or index. |
triggerCond | String | Gte or Lte, indicating the comparison condition between the trigger reference price and triggerPx. |
isMarket | Boolean | Whether the order is executed at market after triggering. |
tpsl | String | Position TPSL type: tp or sl. |
parentOrderId | String | Position TPSL has no parent order and always returns "". |
isActive | Boolean | Whether the Position TPSL is active. |
tpLimit | Boolean | Whether this is a TP Limit order. |
trades[] Fields
| Field | Type | Description |
|---|
assetId | String | Product ID for the trade. Can be a perp or spot product. |
tradeId | String | Global ordinary matching trade ID, used for trade deduplication and association with account-state updates. Non-ordinary matching events do not generate a special value. |
eventType Enumeration
| Value | Description |
|---|
filled | Ordinary trade fill. |
liquidation | Liquidation. |
adl | Auto-deleveraging. |
settlement | Settlement. |
ctfOperation | CTF operation. |
fundingFee | Funding fee. |
setLeverage | Leverage update. |
transferred | Funds transfer. |
deposit | Deposit. |
withdraw | Withdrawal. |
adjustMargin | Margin adjustment. |
clawBack | Clawback. |
vaultOperation | Vault operation. |
tokenBurn | Token burn. |
purchaseFee | Purchase fee. |
orderUpdated | Order update. |
Ordinary Fill Event Example
Two perp fills and one spot fill occur at the same on-chain timestamp:
Partial Liquidation Event Example
Non-ordinary matching events, such as liquidation, ADL, funding fees, and settlement, do not generate new ordinary tradeId values. Therefore, trades=[]. Use eventType to identify the event cause.
Deduplication Rules
| Data Type | Identifier Key |
|---|
| Token | tokenId |
| Position | assetId + marginMode + positionSide |
| Trade | tradeId |
Event-Triggered Full Snapshot of Open Orders exchangeos-orders
After a successful subscription, the channel immediately pushes a complete snapshot of all open orders for the master account or specified sub-account.
This channel does not push on a fixed schedule. When an Order Event or Fill Event occurs, the system retrieves and pushes a complete snapshot of open orders after the event. It does not push only the orders that changed.
On the initial subscription, or after a subsequent order or fill event, if the account has no open orders, the channel still pushes:
orders=[]
totalCount="0"
activeCount="0"
curPage="0"
lastPage=true
Subscription Request
Subscription Parameters
| Parameter | Type | Required | Description |
|---|
id | String | No | User-defined request ID. |
op | String | Yes | Fixed value: subscribe. |
args | Array | Yes | Subscription argument list. |
> channel | String | Yes | Fixed value: exchangeos-orders. |
> vaultAddress | String | No | Sub-account address. Omit to subscribe to the master account. |
> pointBoard | String | No | true for the points board and false for the live board. Default: false. |
> marketTypes | String | No | Market scope. Supports spot, prediction, and perp. Omit for all markets. |
Top-Level Push Fields
| Field | Type | Description |
|---|
arg | Object | Echo of the subscription parameters. |
backend | String | Backend service that generated this push. |
block_height | String | On-chain block height associated with this snapshot cycle. |
block_timestamp | String | On-chain block time associated with this snapshot cycle, in Unix milliseconds. |
pTime | String | Generation time of this page's push message, in Unix milliseconds. |
user | String | Master-account or sub-account address to which the data belongs. |
data | Object | Open-order snapshot, pagination, and count data for this snapshot cycle. |
data Fields
| Field | Type | Description |
|---|
type | String | Fixed value: snapshot, indicating a complete event-triggered snapshot of open orders. |
curPage | String | Current page number of the snapshot cycle, starting from "0". |
lastPage | Boolean | Whether this is the last page of the snapshot cycle. |
totalCount | String | Total number of open orders in the snapshot cycle, including inactive Order-Attached TPSL orders. The value is identical on every page. |
activeCount | String | Total number of active orders in the snapshot cycle, excluding inactive Order-Attached TPSL orders. The value is identical on every page. |
orders | Array | Open orders on the current page. Elements can be Order or StopOrder. Returns [] when there are no open orders. |
type, curPage, lastPage, totalCount, and activeCount are all located inside data.
data is an Object. Do not expect the format data: [{ "orders": [] }].
- All pages in the same snapshot cycle share the same
block_height, block_timestamp, totalCount, and activeCount.
pTime is the actual generation time of each page. Therefore, pTime can differ across pages.
- Clients should collect all pages and atomically apply the complete snapshot after receiving
lastPage=true.
- If there are no open orders after an event, the channel still pushes
orders=[], totalCount="0", and activeCount="0".
orders[] Element Types
orders[] returns two flattened data structures:
Order: A standard limit order that has entered the order book, or a TP Limit order that has been converted into a standard resting order.
StopOrder: A standalone Trigger order, Order-Attached TPSL, or Position-Attached TPSL.
Order-Attached TPSL is not nested in the parent order's attachAlgoOrds[]. It is returned as an independent StopOrder element in the same orders[] array and is linked to its parent order through parentOrderId.
Order Fields
| Field | Type | Description |
|---|
oid | String | On-chain order ID. |
clientOrderId | String | User-defined order ID. |
assetId | String | Product ID. |
assetStatus | String | Product status: normal, scheduled, converging, or regressing. |
side | String | Order side: buy or sell. |
positionSide | String | Position side: net, long, or short. Returns "" for non-perp products. |
marginMode | String | Margin mode: cross or isolated. Returns "" for non-perp products. |
leverage | String | Leverage. Only integer leverage is supported. Returns "" when equity is 0 or for non-perp products. |
orderType | String | Order type. Fixed value: limit. |
tif | String | Time in force: gtc, ioc, fok, alo, or gtd. |
price | String | Order price. |
size | String | Order size, in base units. |
accFillSz | String | Cumulative filled size, in base units. |
state | String | Order state, for example open or partially_filled. |
reduceOnly | Boolean | Whether this is a reduce-only order. |
cTime | String | Order creation time, in Unix milliseconds. |
expiresAfter | String | Order expiration time. Returns "" when not applicable. |
isMarket | Boolean | Whether this is a market-execution order. |
outcomeReverse | Boolean | Whether the outcome is reversed. |
tpLimit | Boolean | Whether this is a TP Limit order. |
Order does not provide avgPx, parentOrderId, triggerPx, triggerPriceType, triggerCond, tpsl, or attachAlgoOrds.
Calculate the cumulative average fill price through REST GET /trade/fills or the private channel exchangeos-user-fills.
StopOrder Fields
| Field | Type | Description |
|---|
oid | String | Trigger or TPSL order ID. |
assetId | String | Product ID. |
assetStatus | String | Product status: normal, scheduled, converging, or regressing. |
side | String | Order side: buy or sell. |
positionSide | String | Position side: net, long, or short. Returns "" for non-perp products. |
marginMode | String | Margin mode: cross or isolated. Returns "" for non-perp products. |
leverage | String | Leverage. Only integer leverage is supported. Returns "" when equity is 0 or for non-perp products. |
size | String | Trigger or TPSL order size. |
price | String | Order price for Trigger Limit. Trigger Market returns "". |
isMarket | Boolean | Whether the order executes at market after triggering. true indicates Trigger Market; false indicates Trigger Limit. |
reduceOnly | Boolean | Whether this is a reduce-only order. |
cTime | String | Trigger or TPSL creation time, in Unix milliseconds. |
triggerPx | String | Trigger price. |
triggerPriceType | String | Trigger price source: mark or index. |
triggerCond | String | Trigger condition: Gte or Lte. |
tpsl | String | Order purpose: tp, sl, up, or down. |
parentOrderId | String | Parent order ID for Order-Attached TPSL. Standalone Trigger and Position-Attached TPSL return "". |
isActive | Boolean | Whether the order is active. Order-Attached TPSL is false before its parent order reaches a terminal state. |
tpLimit | Boolean | Whether this is a TP Limit order. |
StopOrder does not provide clientOrderId, state, accFillSz, or outcomeReverse.
Complete Push Example
The following example includes one standard perp limit parent order and inactive Order-Attached TP and SL orders. All three items are flattened into data.orders[]. totalCount="3"; only the parent order is active, so activeCount="1".
Empty Order Snapshot Example
When no open orders remain after an Order Event or Fill Event:
Setting Updates exchangeos-setting-updates
An event-triggered channel for account setting updates.
After a successful subscription, the channel does not push a snapshot of the current settings. It pushes an update only when positionMode, roleId, leverage, or marginMode actually changes.
No empty message is pushed when there is no setting change.
This channel does not provide an initial push. The subscription request id can be user-defined.
To subscribe to a sub-account, specify the sub-account address through vaultAddress.
Subscription Request
Subscription Parameters
| Parameter | Type | Required | Description |
|---|
id | String | No | User-defined request ID. |
op | String | Yes | Fixed value: subscribe. |
args | Array | Yes | Subscription argument list. |
> channel | String | Yes | Fixed value: exchangeos-setting-updates. |
> vaultAddress | String | No | Sub-account address. Omit to subscribe to the master account. |
> pointBoard | String | No | true for the points board and false for the live board. Default: false. |
> marketTypes | String | No | Market types, for example ["spot", "perp"]. All market types are used when omitted. |
Top-Level Push Fields
| Field | Type | Description |
|---|
arg | Object | Subscription information. |
> channel | String | Fixed value: exchangeos-setting-updates. |
> vaultAddress | String | Sub-account address. Omitted when subscribing to the master account. |
backend | String | Backend service that generated this push. |
block_height | String | On-chain block height associated with this setting change. |
block_timestamp | String | On-chain block time associated with this setting change, in Unix milliseconds. |
pTime | String | Actual WebSocket message generation or push time, in Unix milliseconds. |
user | String | Master-account or sub-account address to which this update belongs. |
data | Object | Account-level or product-level settings that actually changed. |
data Fields
| Field | Type | Description |
|---|
accSetting | Object | Account-level setting updates. This field is omitted when no account-level setting has changed. |
assetSetting | Array | Product-level setting updates. Returns [] when no product-level setting has changed. |
accSetting Fields
| Field | Type | Description |
|---|
roleId | String | Margin role ID. Used to apply custom margin rules for special users. |
positionMode | String | Position mode. oneWay is one-way mode; hedge is hedge mode. |
assetSetting[] Fields
| Field | Type | Description |
|---|
assetId | String | Contract ID. |
positionSide | String | Position side. oneWay mode uses net; hedge mode uses long or short. |
leverage | String | Leverage. Only integer leverage is supported. |
marginMode | String | Margin mode: cross for cross margin and isolated for isolated margin. |
Example: Updating roleId or positionMode
Example: Updating leverage or marginMode
User Order Status exchangeos-user-order-status
Pushes order-submission results and subsequent state changes. Historical orders are not pushed. A rejected order is pushed even if no oid was created; its oid is "".
The payload is directly data: OrderDetail[]. It does not use orderStatuses[] or an order wrapper. Results from batch requests are emitted in input order.
Subscription Parameters
| Parameter | Type | Required | Description |
|---|
channel | String | Yes | Must be exchangeos-user-order-status. |
vaultAddress | String | No | Subaccount address. Omit it to subscribe to the master account. |
pointBoard | String | No | "true" for point board and "false" for live trading. Defaults to "false". |
marketTypes | String | No | JSON Array string. May include spot, prediction, and perp. Omit it for all markets. |
data[]: OrderDetail Fields
| Field | Type | Description |
|---|
oid | String | Order ID; "" if a rejected order was never created. |
clientOrderId | String | Client order ID. |
assetId | String | Product ID. |
marketType | String | Market type, such as spot, prediction, or perp. |
state | String | Order state; see the table below. |
cancelReason | String | Cancellation or rejection reason; empty when absent. |
cTime | String | Order creation time in Unix epoch milliseconds. |
marginMode | String | cross or isolated. |
positionSide | String | net, long, or short. |
side | String | buy or sell. |
price | String | Order price. |
size | String | Order size. |
sizeType | String | Size unit, such as base or quote. |
accFillSz | String | Cumulative filled size. |
reduceOnly | Boolean | Whether the order is reduce-only. |
outcomeReverse | Boolean | Whether the order is outcome-reverse. |
parentOrderId | String | Parent order ID; empty if not applicable. |
tif | String | Time-in-force, such as gtc or ioc. |
triggerInfo | Object | Trigger-order or TPSL information; absent for ordinary orders. |
children | Array | Related child orders created after triggering; may be absent. |
side and positionSide
| Business Direction | side | positionSide |
|---|
| Buy / one-way mode | buy | net |
| Sell / one-way mode | sell | net |
| Open Long | buy | long |
| Close Long | sell | long |
| Open Short | sell | short |
| Close Short | buy | short |
state Enumeration
| Value | Meaning | Description |
|---|
open | Order opened | The order entered the order book or was successfully created. |
canceled | Order canceled | Check cancelReason for the specific reason. |
rejected | Order rejected | Placement or trigger execution failed; an oid may not have been created. |
filled | Order filled | The order was fully filled and reached a terminal state. |
modified | Order modified in place | The order retains its oid, typically for a same-price size reduction. |
triggered | Trigger order triggered | The trigger condition was met; created order IDs are returned through children. |
active | Conditional order activated | An Order-Attached TPSL child order became active after its parent order filled. |
cancelReason Enumeration
cancelReason | Meaning |
|---|
iocNoFill | An IOC order found no executable liquidity. |
fokNotFilled | An FOK order could not be fully filled. |
aloRejected | An ALO / post-only order would execute immediately and was rejected. |
userCancel | User-initiated cancellation. |
selfTradeCancel | Cancellation caused by self-trade prevention. |
expired | A GTD order expired. |
makerInsufficientBalance | Cancellation caused by insufficient maker balance. |
clearOrderBook | Cancellation caused by order-book clearing. |
userModify | Cancellation or re-posting caused by a user order modification. |
reduceOnlyTrim | Order quantity was reduced by a reduce-only constraint. |
marginInsufficient | Insufficient margin caused rejection or cancellation of the remaining quantity. |
assetHalted | The asset was halted or delisted. |
relatedPositionClosed | The related position was closed or reversed. |
parentOrderCanceled | A related child order was canceled because its parent order terminated unfilled. |
marginTierExceeded | The position-tier limit was exceeded. |
triggerShrunkToZero | The executable trigger quantity became zero after limit trimming. |
triggerPriceOutOfBand | The post-trigger limit price fell outside the price-protection band. |
tpLimitActivationInvariantViolated | Execution prerequisites, such as position mode, changed when TP Limit activation occurred. |
sizeDecimalsAdjust | A size-decimal adjustment truncated the order quantity. |
priceDecimalsAdjust | A price-decimal adjustment canceled the order. |
priceDecimalsAdjustModify | A price-decimal adjustment modified the surviving order in place. |
Push Example
User Fills exchangeos-user-fills
Pushes new fills after subscription only. It sends no initial historical snapshot.
- The channel does not paginate. Use
data.fills[] length for the number of fills in a push.
- Use REST
GET /trade/fills to recover historical or disconnected-period fills.
- Subscribe first and buffer events, then retrieve REST history and merge/deduplicate by
tradeId.
- Normal matching fills are uniquely identified by non-empty
tradeId.
- Liquidation, ADL, and settlement fills can return
tradeId: ""; empty trade IDs must not all be treated as the same fill.
- The outer
block_timestamp is the blockchain-data time for the batch. Multiple fills can share it and must not overwrite one another.
Fill Push Fields
| Field | Type | Description |
|---|
arg | Object | Echoed subscription conditions. |
backend | String | Backend service that generated the push. |
block_height | String | Batch blockchain block height. |
block_timestamp | String | Batch blockchain-data time. |
pTime | String | Push-generation time; not used for fill deduplication. |
user | String | Associated master-account or subaccount address. |
data.fills | Array of Object | Fill array; a batch can contain multiple fills. |
data.fills[] Fields
| Field | Type | Description |
|---|
tradeId | String | Normal matching fill ID; "" for applicable system fills. |
oid | String | On-chain order ID that produced the fill; "" when inapplicable. |
clientOrderId | String | Client order ID; "" when unset or inapplicable. |
assetId | String | Product ID. |
marketType | Object | Market and trading attributes. Perp contains marginMode and positionSide; spot and Prediction return their own market objects. |
side | String | buy or sell. |
execType | String | maker or taker. |
price | String | Fill price. |
size | String | Fill size. |
sizeType | String | base or quote. |
remainingSize | String | Remaining order size after the fill. |
fee | String | Non-negative fee amount; "0" if none. |
feeTokenId | String | Fee token ID; "" when inapplicable. |
rebate | String | Non-negative rebate amount; "0" if none. |
rebateToken | String | Rebate token ID; "" if none. |
oppositeOrderId | String | Counterparty order oid. |
oppositeUser | String | Counterparty address. |
pnl | String | Realized PnL for the fill; "" for spot or when inapplicable. |
fillDir | String | Detailed fill direction. |
startPosition | String | Pre-match position quantity or spot asset balance. |
twapId | String | Parent TWAP ID; "" for non-TWAP fills. |
FillDir Enumeration
| Value | Meaning |
|---|
Buy / Sell | Buyer or seller fill from ordinary matching or Prediction Market transfer settlement. |
BuySplit / SellMerge | Implicit Prediction Market split or merge. |
BackstopLiquidation / BackstopLiquidator | Insurance-fund liquidation takeover and fund-side view. |
Adl / AdlOpponent | ADL event and its counterparty view. |
AdlPreviousPrice / AdlOpponentPreviousPrice | ADL event valued using a prior price. |
NetLiquidation / NetAdl | Net liquidation or net ADL. |
Settlement | Settlement fill. |
Open / Close | Perpetual opening or reducing/closing fill. |
ReverseOpen | A single fill crosses zero: closes the original position, then opens the opposite position. |
DecimalAdjustSettle / DecimalAdjustTakeover | Pre-release decimal-adjustment values; not emitted by the current version. |
Push Example
User Fundings exchangeos-user-fundings
An incremental funding-fee event channel. It sends no initial snapshot, no empty snapshot, and no historical funding events. It pushes only when funding is actually charged or paid. Push frequency follows the product settlementInterval; it is not fixed hourly.
Recover historical or missed funding events through:
data.fundings[] Fields
| Field | Type | Description |
|---|
assetId | String | Contract ID. |
fundingFee | String | Negative means paid; positive means received. |
pos | String | Position quantity. |
fundingRate | String | Funding rate. |
marginMode | String | cross or isolated. |
positionSide | String | net, short, or long. |
Push Example
User Ledger Updates exchangeos-user-ledger-updates
Pushes non-funding ledger changes, including deposits, withdrawals, account transfers, subaccount transfers, liquidations, Vault operations, Prediction Market operations, isolated-margin transfers, and margin-mode changes.
Funding events are not pushed by this channel; use exchangeos-user-fundings.
Push Rules
- This is an event-only channel and does not send a historical initial snapshot.
- Each WebSocket message is a JSON object, not a
[{...}] array.
- The business payload is always
data: { "ledgerUpdates": [...] }.
- Every
ledgerUpdates[] item contains time, hash, and delta.
- Every
delta contains affected users[] and exactly one concrete event variant.
- Determine event type from the variant key; do not rely on field count or field order.
block_timestamp is the batch block time, ledgerUpdates[].time is the individual event time, and pTime is the push-generation time. Do not interchange them.
data.ledgerUpdates[] Fields
| Field | Type | Description |
|---|
time | String | Individual ledger-event time in Unix epoch milliseconds. |
hash | String | Related transaction or event hash. |
delta | Object | Ledger-change payload. |
delta.users | Array of String | Affected account addresses. |
delta.<variant> | Object | Exactly one concrete ledger-event object. |
delta Variants
| Variant | Description |
|---|
liquidationPenalityCompensationEvent | Liquidation penalty and compensation. Penality is the existing wire-key spelling and must be parsed exactly. |
transfer | Transfer across account or market ledgers. |
subAccountTransfer | Transfer between master account and subaccount. |
deposit | Deposit from X Layer. |
withdraw | Withdrawal to X Layer. |
vaultCreate | Vault creation. |
vaultDeposit | Deposit to a Vault. |
vaultWithdraw | Withdrawal from a Vault. |
vaultDistribution | Vault profit distribution. |
vaultLeaderCommission | Vault leader commission. |
predictionSplit | Prediction Market split. |
predictionMerge | Prediction Market merge. |
predictionRedeem | Prediction Market settlement redemption. |
predictionConvert | Prediction Market negRisk conversion. |
depositAndRedeem | Deposit and automatic redemption of a settled Prediction Market token. |
tokenBurn | User-balance change caused by a total token burn. |
actionPurchaseFee | Fee for purchasing Action Allowance. |
isolatedMarginTransfer | Margin transfer between cross account and isolated position. |
updateMarginMode | Cross / isolated mode change and related collateral movement. |
Documented Variant Fields
transfer
| Field | Type | Description |
|---|
user | String | Source account. |
destination | String | Destination account. |
sourceDex / destinationDex | String | Source and destination business lines, such as perp and spot. |
tokenId | String | Token ID. |
amount | String | Transfer amount. |
fee | String | Transfer fee. |
updateMarginMode
| Field | Type | Description |
|---|
user | String | Account address. |
assetId | String | Product ID. |
marginMode | String | Updated margin mode. |
moves | Array | Margin-movement entries. |
moves[].side | String | Position side. |
moves[].amount | String | Moved amount. |
liquidationPenalityCompensationEvent
| Field | Type | Description |
|---|
marginMode | String | Margin mode. |
fullTakeOver | Boolean | Whether the position was fully taken over. |
liquidatorItems | Object | Liquidation items keyed by liquidator address. |
chargeList | Array | Liquidation penalty and compensation entries. |
chargeList[].assetId | String | Product ID. |
chargeList[].positionSide | String | Position side. |
chargeList[].penality | String | Liquidation penalty; this is the existing wire-key spelling. |
chargeList[].fee | String | Fee. |
chargeList[].wearingCompensation | String | Compensation amount. |
chargeList[].isLongPosition | Boolean | Whether the position is long. |
chargeList[].takeoverSize | String | Takeover size. |
chargeList[].takeoverPrice | String | Takeover price. |
Push Example