Private Data API (WebSocket · Private Channels)

Private Channels Overview

Private channels provide access to account-specific data and trading operations. All private channels require authentication via a valid JWT token.

Authentication Required All private channels require a valid signature token. Ensure you have completed the authentication flow before attempting to access these channels.
Available Private Channels
  • BALANCE - Real-time account balance updates
  • CLIENT_BALANCE_DISTRIBUTION - Per-exchange breakdown of where each asset is held
  • TRANSFER_FEE_QUOTE - What a transfer or withdrawal will deliver after fees
  • TRADE_PRIVATE - Private trades and order management
  • TRADE_POSITIONS - Current trading positions
  • YIELD_CONTRACT - Your Yield contracts as they change stage and earn
  • RFQ POST - Request for Quote functionality
Balance

Real-time balance updates for specified currencies. Provides both snapshot and incremental updates.

Subscribe Request
{
    "command": "SUBSCRIBE",
    "signature": "valid_signature",
    "channel": "BALANCE",
    "channelArgs": [
        {
            "name": "currency",
            "value": "[USD,ADA,ETH,BTC]"
        }
    ]
}
Acknowledgment
{
    "command": "SUBSCRIBE",
    "event": "ACK",
    "channel": "BALANCE"
}
Snapshot Response
{
    "command": "SUBSCRIBE",
    "event": "SNAPSHOT",
    "channel": "BALANCE",
    "data": [
        {
            "class": "Balance",
            "currencyCode": "ADA",
            "balance": 16140.3555,
            "available": 16040.3555,
            "locked": 100.0
        }
    ]
}
Update Response
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "BALANCE",
    "data": [
        {
            "class": "Balance",
            "currencyCode": "ADA",
            "balance": 16140.3555,
            "available": 16040.3555,
            "locked": 100.0
        }
    ]
}
GET Balance Distribution

Where your tokens actually sit — a per-venue breakdown of every asset you hold, with cost basis, valuation and PnL for each venue. One time request/response; there is no subscription on this channel.

Why this is not the same as Balance The BALANCE channel reports one aggregate figure per currency across all venues, but an order is routed to exactly one exchange and is checked against that venue's balance alone. Read this channel to decide where an order can actually be filled, and how much can be withdrawn or transferred off a given venue.
Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "CLIENT_BALANCE_DISTRIBUTION",
    "channelArgs": [],
    "data": []
}
No channel arguments channelArgs and data are ignored on this channel — send them empty. The client is taken from your token, so there is no clientId to supply and no way to request another account's distribution.
Response
{
    "command": "GET",
    "event": "GET",
    "channel": "CLIENT_BALANCE_DISTRIBUTION",
    "channelArgs": [],
    "data": [
        {
            "class": "ClientBalanceDistribution",
            "clientId": 1000123,
            "asset": "BTC",
            "exchange": "OKEX",
            "finalBalance": 0.35,
            "costBasisUsd": 30642.7595,
            "marketValueUsd": 30803.6502,
            "avgPriceUsd": 87550.7414,
            "lockedAmount": 0.05,
            "availableAmount": 0.3,
            "unrealizedPnl": 160.8907,
            "returnPercent": 0.525
        },
        {
            "class": "ClientBalanceDistribution",
            "clientId": 1000123,
            "asset": "BTC",
            "exchange": "BITGET",
            "finalBalance": 0.12,
            "costBasisUsd": 10866.089,
            "marketValueUsd": 10561.2515,
            "avgPriceUsd": 90550.7417,
            "lockedAmount": 0.0,
            "availableAmount": 0.12,
            "unrealizedPnl": -304.8375,
            "returnPercent": -2.8054
        }
    ]
}

Response Fields

Field Type Description
clientId Number Your Open Trade client identifier, taken from the token.
asset String Asset code, e.g. BTC, USDT, GALA.
exchange String Venue holding the asset: OKEX, HUOBI, BITGET, BITMART, BINANCE, DERIBIT, LMAX, GEMINI, BLOCKCHAIN, OPENTRADE.
finalBalance Number Total amount of the asset held on that venue.
availableAmount Number Amount free to trade, withdraw or transfer from that venue.
lockedAmount Number Amount reserved on that venue, typically against open orders or a pending transfer.
avgPriceUsd Number Average price paid for the quantity still open on that venue, in USD. Equal to costBasisUsd divided by finalBalance.
costBasisUsd Number USD paid for the quantity still open on that venue. Anything already closed is excluded.
marketValueUsd Number Current USD market value of the holding on that venue.
unrealizedPnl Number Unrealized PnL on the holding, in USD, measured as market value less cost basis. Negative when the position is under water, and zero when nothing was paid for the holding.
returnPercent Number Return on the holding, in percent, measured against the cost basis. Zero when nothing was paid for the holding.
One row per asset per venue An asset held on three exchanges comes back as three rows. Sum finalBalance over the rows sharing an asset to reconcile against the BALANCE channel, and never assume a single row carries the whole position.
Private Trades

Private trades subscription will provide a snapshot of currently open ACTIVE orders and then updates via WebSocket.

Important! Must be subscribed to valid pairs in order to get WS updates for those pairs! May subscribe to multiple pairs if desired.
Subscribe Request
{
    "command": "SUBSCRIBE",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "channelArgs": [
        {
            "name": "instrument",
            "value": "[BTC/USD,ETH/BTC]"
        }
    ]
}
Current Active Orders Response
{
    "command": "GET",
    "event": "GET",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "orderId": "567567567",
            "exchOrderId": "1668662119644",
            "direction": "BUY",
            "orderType": "LIMIT",
            "orderStatus": "ACTIVE",
            "price": 12000.0,
            "filledPrice": 0.0,
            "amount": 0.001,
            "orderDateTime": "2022-11-09T18:19:29.644164Z",
            "globalInstrumentCd": "BTC/USD",
            "message": null
        }
    ]
}
Real-time Order Update
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "globalInstrumentCd": "BTC/USD",
            "orderId": "0989876565",
            "exchOrderId": "1652424613543121",
            "direction": "SELL",
            "orderType": "LIMIT",
            "orderStatus": "NEW",
            "price": "0.215",
            "amount": "1.0",
            "orderDateTime": "1652424613543121"
        }
    ]
}
GET Get Active Private Trades

Get current list of open orders. One time request/response.

Note: Either channel argument 'instrument' or the 'data' section must be provided. If both are present, the server will return no data.
Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "channelArgs": [
        {
            "name": "category",
            "value": "ACTIVE_ORDERS"
        },
        {
            "name": "instrument",
            "value": "[USD/ADA,ETH/BTC,BTC/USD,BTC/EUR]"
        }
    ]
}
Alternative Request (using data section)
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "channelArgs": [
        {
            "name": "category",
            "value": "ACTIVE_ORDERS"
        }
    ],
    "data": [
        {
            "class": "Order",
            "globalInstrumentCd": "BTC/USD",
            "clientOrderId": "123456789",
            "exchangeOrderId": "5464564"
        }
    ]
}
CREATE Send New Order

User may post New LIMIT, MARKET, POST_ONLY, BUY_STOP, SELL_STOP, STOP_LOSS, TAKE_PROFIT orders via CREATE action. A LIMIT, MARKET, BUY_STOP or SELL_STOP entry may carry a take profit and a stop loss that work as one-cancels-other once it fills.

Critical! Before sending the new order, user must first be subscribed to desired pair, otherwise order will be rejected!!

Order Parameters

Field Type Required Description
action String Yes Create, Cancel, Modify
amount Number Yes Quantity of the order
clientOrderId String Optional Id of the order (must be unique, recommend Unix timestamp)
exchange String Optional Name of exchange to send order to, such as BITFINEX, LMAX, OKX. If not provided, order will be set as SMART
globalInstrumentCd String Yes Pair (BTC/USD, ...)
orderType String Yes MARKET, LIMIT, POST_ONLY, BUY_STOP, SELL_STOP, STOP_LOSS, TAKE_PROFIT
price Number Yes The limit price for LIMIT and POST_ONLY, and the trigger for BUY_STOP and SELL_STOP. For MARKET, STOP_LOSS and TAKE_PROFIT send the current price as a reference
sl Number Optional Stop loss trigger. Required for STOP_LOSS. On a LIMIT, MARKET, BUY_STOP or SELL_STOP entry it attaches a stop loss, and on a TAKE_PROFIT it links one to it (see Take profit and stop loss)
tp Number Optional Take profit trigger. Required for TAKE_PROFIT. On a LIMIT, MARKET, BUY_STOP or SELL_STOP entry it attaches a take profit, and on a STOP_LOSS it links one to it (see Take profit and stop loss)
timeInForce String Optional GTC, GTD, GTT, FOK, IOC
direction String Yes BUY or SELL

Time In Force Options

  • GTC - Good Till Cancelled (default; orders rest in the book for 90 days)
  • GTD - Good Till Day (terminates at end of day, 4:59 PM NY time)
  • GTT - Good Till Time (alive until a specific date; cannot exceed 90 days)
  • FOK - Fill or Kill (fill the full amount immediately or nothing)
  • IOC - Immediate or Cancel (fill any amount immediately, cancel the rest)

Order types

  • MARKET - Buy or sell immediately at the best available price. No price guarantee.
  • LIMIT - Buy or sell only at your specified price or better. Rests in the book until matched or cancelled. Price guaranteed; fill is not.
  • POST_ONLY - Limit order that is rejected if it would match immediately. Guarantees you add liquidity (maker).
  • BUY_STOP - Triggers a buy when price rises to or above the stop price. Used to enter long on a breakout, or to cover a short position when the market moves against you.
  • SELL_STOP - Triggers a sell when price falls to or below the stop price. Used to enter short on a breakdown, or to exit a long position when the market falls.
  • STOP_LOSS - Protective exit order. Closes an existing position at market once the trigger in sl is hit, capping the loss on the trade.
  • TAKE_PROFIT - Protective exit order. Closes an existing position at market once the trigger in tp is reached, locking in the gain.

Take profit and stop loss

Send tp, sl or both on a LIMIT, MARKET, BUY_STOP or SELL_STOP entry to protect it as it fills. With both, the two exits are one-cancels-other: when one fires, the other is cancelled.

  • Smart routing only - leave exchange out. An entry that names an exchange and carries tp or sl is rejected.
  • Side - for a BUY entry set sl below and tp above the entry price; for a SELL entry set tp below and sl above. The entry price is the limit price for LIMIT, the best ask (BUY) or best bid (SELL) for MARKET, and the stop price for BUY_STOP and SELL_STOP. A trigger on the wrong side is rejected.
  • Stop entries - a BUY_STOP or SELL_STOP places no exit while it waits. Once its stop price is reached it enters at market and the exits arm on what fills. Cancelling it before then cancels the whole order. While it waits, price, sl and tp can be modified, the amount cannot.
  • Size - the exits arm as soon as the entry starts to fill, sized to the quantity you received, and grow with each further fill.
  • Trigger - a sell exit watches the best bid and a buy exit the best ask. A triggered exit executes at market.
  • Cancel - cancelling while the entry is still working cancels only its unfilled part; the exits stay on what filled. Cancel the order again once the entry has completed to remove both exits.

Take profit and stop loss on a position you already hold

Send one STOP_LOSS or TAKE_PROFIT order carrying both sl and tp. The two exits are one-cancels-other: when one fires, the other is cancelled, and the quantity is reserved once for the pair.

  • Smart routing only - leave exchange out.
  • Side and size - set direction to the side that closes the position (SELL for a long) and amount to the quantity to protect. An order for more than you can hold is rejected.
  • Triggers - for a SELL set sl below and tp above the current price; for a BUY set tp below and sl above. A trigger on the wrong side is rejected.
  • Status - the order you get back owns the pair. It is FILLED once an exit has closed the quantity, CANCELLED when you cancel it or it expires, and FAILED with the reason when it could not be funded or could no longer protect the rest. The fills are reported on the two exit orders.
  • Cancel and amend - cancelling the order cancels both exits. The triggers can be amended; to change the quantity, cancel the order and send it again.
Linked STOP_LOSS and TAKE_PROFIT Request
{
    "command": "CREATE",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "globalInstrumentCd": "BTC/USD",
            "clientOrderId": "0989876566",
            "direction": "SELL",
            "orderType": "STOP_LOSS",
            "timeInForce": "GTC",
            "price": "64210",
            "sl": "63000",
            "tp": "66000",
            "amount": "0.5"
        }
    ]
}
LIMIT Order Request
{
    "command": "CREATE",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "globalInstrumentCd": "BTC/USD",
            "clientOrderId": "0989876565",
            "direction": "SELL",
            "orderType": "LIMIT",
            "timeInForce": "GTC",
            "price": "0.215",
            "amount": "1.0"
        }
    ]
}
LIMIT Order with Take Profit and Stop Loss
{
    "command": "CREATE",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "globalInstrumentCd": "BTC/USD",
            "clientOrderId": "1790600000000",
            "direction": "BUY",
            "orderType": "LIMIT",
            "timeInForce": "GTC",
            "price": "64000",
            "amount": "0.01",
            "tp": "66000",
            "sl": "63000"
        }
    ]
}
ACK Response
{
    "command": "CREATE",
    "event": "ACK",
    "channel": "TRADE_PRIVATE"
}
Accepted Response
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "OrderUpdate",
            "clientId": 100141,
            "requestType": "SMART",
            "tradeSide": "BUY",
            "instrumentCd": "BTC/USD",
            "exchangeOrderId": null,
            "clientOrderId": "2222223333",
            "transactionId": 1668897424879,
            "orderRequestStatus": "ACCEPTED",
            "message": "",
            "key": "100141:BTC/USD:1275564715"
        }
    ]
}
Rejection Response
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "OrderUpdate",
            "clientId": 100000,
            "requestType": "SMART",
            "instrumentCd": "BTC/USD",
            "timeInForce": "GTC",
            "exchangeOrderId": null,
            "clientOrderId": "1234567896",
            "transactionId": 0,
            "orderRequestStatus": "REJECTED",
            "message": "Request amount less than minimum order size",
            "key": "100000:BTC/USD:1243828326"
        }
    ]
}
Filled Order Response
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "ExecutionReport",
            "clientId": 100141,
            "transactionId": 1668127315108,
            "instrumentCd": "BTC/USD",
            "requestType": null,
            "tradeSide": "BUY",
            "orderType": "LIMIT",
            "timeInForce": "GTC",
            "exchangeOrderId": null,
            "clientOrderId": "65656775333",
            "requestedPrice": 19000.0,
            "requestedAmount": 0.001,
            "amountSent": 0.001,
            "amountFilled": 0.001,
            "orderRequestStatus": "COMPLETED",
            "message": "",
            "key": "100141:BTC/USD:1668127315108:-1088378359"
        }
    ]
}
CANCEL Cancel Order

User may cancel existing orders; client may cancel one order by either including clientOrderId or exchangeOrderId if clientOrderId is not known. exchange and requestType: "DIRECT" are also required so the gateway knows which venue to route the cancel to.

Note: If no clientOrderId or exchangeOrderId are added in the message, all orders for selected pair/s will be cancelled.
Important! Must be subscribed to valid pair in order to cancel order in proper pair!
Exchange is required Unlike some other request types, CANCEL requests must include exchange and requestType: "DIRECT" alongside the order identifier. Without these, the gateway may not be able to resolve which venue holds the order.

Cancel Parameters

Field Type Required Description
action String Yes Cancel
globalInstrumentCd String Yes Pair [BTC/USD, ...]
clientOrderId String Conditional The clientOrderId from the original order. One of clientOrderId or exchangeOrderId must be provided.
exchangeOrderId String Conditional Order id assigned by the underlying exchange. Use when clientOrderId is not known.
exchange String Yes The exchange the order lives on (e.g. HUOBI, OKEX, BITFINEX), as returned in the order's exchange field from Active Orders. Required to route the cancel to the correct venue.
requestType String Yes DIRECT — pins the cancel to exchange above. Omitting this (or the exchange) can result in the request failing to resolve which venue to cancel on.
Cancel resolution rules
  • You must provide either clientOrderId or exchangeOrderId — at least one is required to identify the order.
  • exchange and requestType: "DIRECT" are required in addition to the order identifier.
  • If clientOrderId is provided, it is used (takes precedence over exchangeOrderId).
  • If only exchangeOrderId is provided, that order is cancelled.
  • If both are provided, clientOrderId wins; exchangeOrderId is ignored.
  • If neither is provided, the request is rejected and no orders are cancelled.
Cancel Request (using clientOrderId)
{
    "command": "CANCEL",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "globalInstrumentCd": "BTC/USD",
            "clientOrderId": "7777",
            "exchange": "HUOBI",
            "requestType": "DIRECT"
            // OR use exchangeOrderId instead of clientOrderId:
            // "exchangeOrderId": "1668553243505"
        }
    ]
}
ACK Response
{
    "command": "CANCEL_REQUEST",
    "event": "ACK",
    "channel": "TRADE_PRIVATE"
}
Success Response
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "OrderUpdate",
            "clientId": 100141,
            "requestType": "SMART",
            "tradeSide": "BUY",
            "instrumentCd": "BTC/USD",
            "exchangeOrderId": null,
            "clientOrderId": null,
            "transactionId": 1668897424879,
            "orderRequestStatus": "CANCELLED",
            "message": "",
            "key": "100141:BTC/USD:352908720"
        }
    ]
}
MODIFY Modify Order

Clients may update existing orders. Amount or Price can be modified. Client must use clientOrderId or exchangeOrderId. Only one parameter is needed and will be accepted.

Modify Parameters

Field Type Required Description
action String Yes Modify
clientOrderId String Yes Id of the order
globalInstrumentCd String Yes Pair (BTC/USD, ...)
exchangeOrderId String Yes* Exchange order ID (*or use clientOrderId)
price String No If price is not passed in, then it's not modified
amount String No If amount is not passed in, then it's not modified
Modify Request
{
    "command": "MODIFY",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "globalInstrumentCd": "BTC/USD",
            "orderId": "7777",
            "price": "0.215",
            "amount": "0.215"
        }
    ]
}
GET Private Trades History

Clients may request a list of PARTIALLY_FILLED, FILLED trades for a required time frame.

Note: Channel arguments 'date-from', 'date-to' are optional. If 'date-from' is not provided, it will be defaulted to 'now minus 24 hours'. If 'date-to' is not provided, it will be defaulted to 'now'.
Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "channelArgs": [
        {
            "name": "category",
            "value": "TRADES_HISTORY"
        },
        {
            "name": "instrument",
            "value": "[USD/ADA,ETH/BTC,BTC/USD,BTC/EUR]"
        },
        {
            "name": "date-from",
            "value": "2022-12-01T00:00:00"
        },
        {
            "name": "date-to",
            "value": "2022-12-14T22:30:00"
        }
    ]
}
Response
{
    "command": "GET",
    "event": "GET",
    "channel": "TRADE_PRIVATE",
    "data": [
        {
            "class": "Order",
            "clientOrderId": "4444444",
            "exchangeOrderId": "1668553243505",
            "direction": "BUY",
            "orderType": "LIMIT",
            "orderStatus": "FILLED",
            "price": 12700.0,
            "filledPrice": 12700.0,
            "amount": 0.001,
            "orderDateTime": "2022-11-10T02:36:52.505443Z",
            "globalInstrumentCd": "BTC/USD",
            "message": null
        },
        ...
    ]
}
GET Private Orders History

Clients may request a list of COMPLETED, REJECTED, PARTIALLY_FILLED, FILLED, EXPIRED order requests for a required time frame.

Note: Channel arguments 'date-from', 'date-to', 'status' are optional. If 'date-from' is not provided, it will be defaulted to 'now minus 24 hours'. If 'date-to' is not provided, it will be defaulted to 'now'. If 'status' is not provided then trades with any status will be selected.
Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "TRADE_PRIVATE",
    "channelArgs": [
        {
            "name": "category",
            "value": "ORDERS_HISTORY"
        },
        {
            "name": "instrument",
            "value": "[USD/ADA,ETH/BTC,BTC/USD,BTC/EUR]"
        },
        {
            "name": "date-from",
            "value": "2022-12-01T00:00:00"
        },
        {
            "name": "date-to",
            "value": "2022-12-14T22:30:00"
        },
        {
            "name": "status",
            "value": "[COMPLETED,REJECTED,PARTIALLY_FILLED,FILLED,EXPIRED]"
        }
    ]
}

Available Status Values

  • COMPLETED - Order fully executed
  • REJECTED - Order rejected by exchange
  • PARTIALLY_FILLED - Order partially executed
  • FILLED - Order completely filled
  • EXPIRED - Order expired based on time in force
GET Trade Positions

Get current trade positions with entry prices, volumes, and stop loss/take profit levels.

Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "TRADE_POSITIONS"
}
Response
{
    "command": "GET",
    "event": "GET",
    "channel": "TRADE_POSITIONS",
    "data": [
        {
            "class": "TradePosition",
            "direction": "BUY",
            "date": "2022-11-10",
            "globalInstrumentCd": "BTC/USD",
            "openPrice": 12700.0,
            "entryPrice": 12700.0,
            "posVolume": 0.001
        },
        ...
    ]
}
GET Deposit Wallets

Returns the client's deposit wallet addresses, one per supported asset. Use these addresses to fund your account via on-chain deposit.

Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "DEPOSIT_WALLET",
    "channelArgs": [],
    "data": []
}
Response
{
    "command": "GET",
    "event": "GET",
    "channel": "DEPOSIT_WALLET",
    "data": [
        {
            "class": "DepositWallet",
            "id": 1000003606,
            "clientId": 100882,
            "symbol": "XRP",
            "walletAddress": "rnSffMjADGXG9apHR6gjKz8THc1FtZGCov",
            "status": "ACTIVE",
            "comment": "tag: 1000003606",
            "exchange": "OPENTRADE"
        },
        {
            "class": "DepositWallet",
            "id": 1000003615,
            "clientId": 100882,
            "symbol": "AAVE",
            "walletAddress": "0x649590c78f702ed0cdeab07daf722673d2510afe",
            "status": "ACTIVE",
            "comment": null,
            "exchange": "OPENTRADE"
        },
        ...
    ]
}
Field Notes
  • id – internal wallet identifier for this client/asset pair
  • symbol – asset code the wallet accepts deposits for
  • comment – carries the destination tag/memo when the asset requires one (e.g. XRP), otherwise null
  • status – wallet status, e.g. ACTIVE
GET Deposit Workflow

Tracks the lifecycle of incoming on-chain deposits as they are detected, confirmed, and credited to your account. Query either currently running processes or a history of completed ones.

Note: Channel argument 'category' is required and must be either ACTIVE_PROCESSES or COMPLETED_PROCESSES. For COMPLETED_PROCESSES, 'removeFailed', 'date-from', 'date-to', 'page', and 'pageSize' are optional filters/pagination controls; 'removeFailed' excludes failed/errored processes from the result set when set to true.

Active Processes

Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "DEPOSIT_WORKFLOW",
    "channelArgs": [
        {
            "name": "category",
            "value": "ACTIVE_PROCESSES"
        }
    ]
}

Completed Processes

Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "DEPOSIT_WORKFLOW",
    "channelArgs": [
        {
            "name": "category",
            "value": "COMPLETED_PROCESSES"
        },
        {
            "name": "removeFailed",
            "value": "true"
        },
        {
            "name": "date-from",
            "value": "2026-01-01"
        },
        {
            "name": "date-to",
            "value": "2026-07-14"
        },
        {
            "name": "page",
            "value": "0"
        },
        {
            "name": "pageSize",
            "value": "50"
        }
    ]
}
Response
{
    "channel": "DEPOSIT_WORKFLOW",
    "channelArgs": [ ... ],
    "command": "GET",
    "data": [
        {
            "class": "DepositWorkflow",
            "walletAddress": "0x649590c78f702ed0cdeab07daf722673d2510afe",
            "cryptoAssetCode": "USDT",
            "transferAmount": 20.0002,
            "feeAmount": 0.00001613542206867,
            "feeAssetCode": "ETH",
            "walletTransferId": "a31a5f77-1826-4e20-a416-ba282c4fd864",
            "tag": null,
            "processInstanceId": "96ece4ff-463e-11f1-af10-22add62dcf14",
            "state": "Update Transfer Status - Complete",
            "message": null,
            "startTime": "2026-05-02T15:50:05.922Z",
            "endTime": "2026-05-02T15:53:27.104Z",
            "suspended": false,
            "tokenPriceUsd": 0.9997792134,
            "errorMessage": null
        },
        {
            "class": "DepositWorkflow",
            "walletAddress": "0x649590c78f702ed0cdeab07daf722673d2510afe",
            "cryptoAssetCode": "ETH",
            "transferAmount": 0.000811907277365572,
            "feeAmount": null,
            "feeAssetCode": null,
            "walletTransferId": null,
            "tag": null,
            "processInstanceId": "b6a8edc5-44f0-11f1-bce8-7a2b3ca44423",
            "state": "Check Deposit Amount",
            "message": null,
            "startTime": "2026-05-01T00:00:07.255Z",
            "endTime": "2026-05-01T00:00:08.580Z",
            "suspended": false,
            "tokenPriceUsd": 2255.9838392777,
            "errorMessage": null
        },
        ...
    ]
}
Field Notes
  • state – current step in the deposit pipeline (e.g. Check Deposit Amount, Update Transfer Status - Complete); a state ending in Complete indicates the deposit has been credited
  • feeAmount / feeAssetCode / walletTransferId – populated once the deposit has been processed on-chain; null while still pending
  • tokenPriceUsd – USD reference price for the asset at the time of processing
  • suspended – true if the workflow is paused awaiting manual review
GET Transfer Fee Quote

Prices a transfer or withdrawal before it is created: the venue and network fees it will be charged, and what will reach the destination. Show it to the client, then pass its 'feeAmount' as 'confirmedFee' on Create Transfer.

Note: Channel arguments 'cryptoAssetCode', 'amount', 'fromExchange' and 'toExchange' (BLOCKCHAIN for a withdrawal) are required; 'amount' is the whole amount to be debited. 'walletToAddress' is the destination of a withdrawal.
Request
{
    "command": "GET",
    "channel": "TRANSFER_FEE_QUOTE",
    "signature": "valid signature",
    "channelArgs": [
        { "name": "cryptoAssetCode", "value": "USDT" },
        { "name": "amount", "value": "15" },
        { "name": "fromExchange", "value": "OKEX" },
        { "name": "toExchange", "value": "BLOCKCHAIN" },
        { "name": "walletToAddress", "value": "0x1c93969dce56d7eeeb00679dcfe89d7e0f719979" }
    ]
}
Response
{
    "command": "GET",
    "channel": "TRANSFER_FEE_QUOTE",
    "event": "GET",
    "data": [
        {
            "class": "TransferFeeQuote",
            "cryptoAssetCode": "USDT",
            "amount": 15,
            "fromExchange": "OKEX",
            "toExchange": "BLOCKCHAIN",
            "quoted": true,
            "sendable": true,
            "feeAssetCode": "USDT",
            "feeAmount": 1.35,
            "venueFee": 1,
            "networkFee": 0.35,
            "receiveAmount": 13.65,
            "minimumAmount": 2,
            "refusal": null,
            "reason": null
        }
    ]
}

Quote Fields

FieldTypeDescription
quotedbooleanfalse when the venue or network could not price the fee right now; reason says why
sendablebooleanfalse when the transfer would be refused, for example because the amount does not cover the fee and the venue's minimum; refusal says why
feeAssetCodestringAsset the fee is charged in — the transferred asset
feeAmountnumberTotal fee, venueFee plus networkFee. Send it back as confirmedFee when you create the transfer
venueFeenumberWithdrawal fee of the source venue, null when the transfer does not leave a venue
networkFeenumberNetwork fee of the on-chain send from the platform wallet, null when there is none
receiveAmountnumberWhat reaches the destination: amount less feeAmount, rounded down to what the venue can send
minimumAmountnumberSmallest amount the source venue will send
refusalstringWhy the transfer is not sendable, null when it is
reasonstringWhy the fee could not be quoted, null when it was
CREATE Create Transfer

Initiates a transfer of an asset either between two connected exchanges/venues, or from an exchange out to an external blockchain wallet address.

Note: For exchange-to-exchange transfers, omit 'walletToAddress' and provide 'fromExchange'/'toExchange' venue codes. For exchange-to-wallet transfers, set 'toExchange' to BLOCKCHAIN and supply the destination 'walletToAddress'.
Fees come out of the amount 'transferAmount' is the whole amount debited from your balance. The venue's withdrawal fee and the network fee are taken out of it and the destination receives the rest. Quote it first with Transfer Fee Quote and pass its 'feeAmount' as 'confirmedFee': the transfer is then never charged more than the client confirmed, and is refused rather than sent if the fee has risen. Without 'confirmedFee' the fee is priced again as the funds are sent and charged at that price, which may be higher than the quote, and when no fee can be quoted it is sent in full and the venue may charge its fees afterwards.

Exchange to Exchange

Request
{
    "command": "CREATE",
    "channel": "TRANSFER_WORKFLOW",
    "signature": "valid signature",
    "data": [
        {
            "class": "TransferWorkflow",
            "fromExchange": "OPENTRADE",
            "toExchange": "BITMART",
            "cryptoAssetCode": "USDT",
            "transferAmount": 4
        }
    ]
}

Exchange to Blockchain Wallet (Withdrawal)

This is the same TRANSFER_WORKFLOW CREATE command used above — a withdrawal is simply a transfer where 'toExchange' is set to BLOCKCHAIN and 'walletToAddress' is the external destination address.

Withdraw Request
{
    "command": "CREATE",
    "channel": "TRANSFER_WORKFLOW",
    "signature": "valid signature",
    "data": [
        {
            "class": "TransferWorkflow",
            "fromExchange": "OKEX",
            "toExchange": "BLOCKCHAIN",
            "walletToAddress": "0x1c93969dce56d7eeeb00679dcfe89d7e0f719979",
            "cryptoAssetCode": "USDT",
            "transferAmount": 15,
            "confirmedFee": 1.35
        }
    ]
}
Critical! Withdrawals to blockchain wallet addresses cannot be reversed. Double-check 'walletToAddress' and 'cryptoAssetCode' before submitting.
Track a withdrawal Once submitted, poll Transfer Workflow with 'category' ACTIVE_PROCESSES (in flight) or COMPLETED_PROCESSES (finished) to follow the withdrawal's progress. The response's 'txId' is populated once the withdrawal is broadcast on-chain.

Fee Refusals

CodeDescription
FEE_CHANGEDThe fee has risen above 'confirmedFee'. Quote again and ask the client to confirm the new fee
FEE_UNAVAILABLE'confirmedFee' was sent but the fee cannot be quoted right now. Retry later
FEE_REFUSEDThe amount does not cover the fee and the venue's minimum

A refused transfer starts nothing and locks nothing. Each fee is priced again just before its leg is sent. If the venue's fee has risen above the one quoted at start (above 'confirmedFee' itself when the quote has no 'networkFee'), or the network fee above what 'confirmedFee' leaves for it before anything has left the venue, the transfer ends without sending, your balance is released, and it appears among the completed transfers with its 'errorMessage'. Once the funds have left the venue, a network fee over that is charged at the limit and the platform bears the rest.

Refusal Response
{
    "command": "CREATE",
    "channel": "TRANSFER_WORKFLOW",
    "event": "ERROR",
    "data": [
        { "class": "Error", "desc": "FEE_CHANGED" },
        { "class": "Error", "desc": "The fee on this transfer is now 1.6 USDT, above the 1.35 USDT confirmed" }
    ]
}
GET Transfer Workflow

Tracks the lifecycle of transfers created via the TRANSFER_WORKFLOW CREATE command, whether between exchanges or out to a blockchain wallet.

Note: Channel argument 'category' is required and must be either ACTIVE_PROCESSES or COMPLETED_PROCESSES. For COMPLETED_PROCESSES, 'removeFailed', 'date-from', 'date-to', 'page', 'pageSize', and 'transferSubType' are optional filters/pagination controls. 'transferSubType' accepts ALL or a more specific subtype to narrow results.

Active Processes

Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "TRANSFER_WORKFLOW",
    "channelArgs": [
        {
            "name": "category",
            "value": "ACTIVE_PROCESSES"
        }
    ]
}

Completed Processes

Request
{
    "command": "GET",
    "signature": "valid signature",
    "channel": "TRANSFER_WORKFLOW",
    "channelArgs": [
        {
            "name": "category",
            "value": "COMPLETED_PROCESSES"
        },
        {
            "name": "removeFailed",
            "value": "true"
        },
        {
            "name": "date-from",
            "value": "2026-07-01"
        },
        {
            "name": "date-to",
            "value": "2026-07-14"
        },
        {
            "name": "page",
            "value": "0"
        },
        {
            "name": "pageSize",
            "value": "500"
        },
        {
            "name": "transferSubType",
            "value": "ALL"
        }
    ]
}
Response
{
    "channel": "TRANSFER_WORKFLOW",
    "channelArgs": [ ... ],
    "command": "GET",
    "data": [
        {
            "class": "TransferWorkflow",
            "fromExchange": "OPENTRADE",
            "toExchange": "OKEX",
            "cryptoAssetCode": "USDT",
            "transferAmount": 5,
            "walletTransferId": "ffa280b4-3c95-4741-bb25-d154193b6510",
            "tag": null,
            "processInstanceId": "b0d4b1a1-78ec-11f1-86a3-b6505867aca1",
            "state": "Completed",
            "message": null,
            "startTime": "2026-07-06T03:42:19.954Z",
            "endTime": "2026-07-15T18:36:19.707Z",
            "suspended": false,
            "walletFromAddress": "0x375b9d792d38105bee4b87f72941a6af071d9218",
            "feeAmount": 0.00001031880686044,
            "feeAssetCode": "ETH",
            "txId": "0x205cce2e2077c709a2c9f2b8fffe8861b30c2421bce308bdc87e662d8f90edfb",
            "exchangeTxId": null,
            "exchangeTransferId": null,
            "errorMessage": null,
            "tasks": null
        },
        {
            "class": "TransferWorkflow",
            "fromExchange": "OKEX",
            "toExchange": "OPENTRADE",
            "cryptoAssetCode": "USDT",
            "transferAmount": 5,
            "walletTransferId": "916e31ee-700b-4e60-b6c2-9d14ad651fe9",
            "tag": null,
            "processInstanceId": "fe8858c3-78dd-11f1-86a3-b6505867aca1",
            "state": "Completed",
            "message": null,
            "startTime": "2026-07-06T01:57:07.865Z",
            "endTime": "2026-07-06T01:59:28.529Z",
            "suspended": false,
            "walletFromAddress": "OKEX",
            "feeAmount": 0.097,
            "feeAssetCode": "USDT",
            "txId": null,
            "exchangeTxId": "413425468",
            "exchangeTransferId": "413425468",
            "errorMessage": null,
            "tasks": null
        },
        ...
    ]
}
Field Notes
  • walletFromAddress – the source wallet address for on-chain transfers, or the source exchange name for exchange-internal transfers
  • txId – on-chain transaction hash, populated only for blockchain transfers; null for exchange-to-exchange transfers
  • exchangeTxId / exchangeTransferId – venue-assigned transfer reference, populated only for exchange-to-exchange transfers
  • state – reaches Completed once funds have arrived at the destination
Yield Contracts

Follows your Yield contracts as they work. Subscribing sends every open contract as a snapshot; after that, a contract is pushed as an update whenever its stage changes, income is credited to it, or funding accrues to it. Each contract is the same object Get Contract returns over REST, with the same fields. Subscribing, redeeming and cancelling are done over REST.

Note: The channel takes no arguments and needs the Trade permission. A contract that settles is pushed once more with its final status (CLOSED, CANCELLED or FAILED) and is not in later snapshots. The first update after subscribing may repeat what the snapshot already showed; every message carries the whole contract, so keep the latest one per contractId. Updates are not replayed: after a reconnect, subscribe again, or read GET /yield/contracts/open, to pick up anything that changed while you were away.
Subscribe Request
{
    "command": "SUBSCRIBE",
    "signature": "valid_signature",
    "channel": "YIELD_CONTRACT"
}
Acknowledgment
{
    "command": "SUBSCRIBE",
    "event": "ACK",
    "channel": "YIELD_CONTRACT"
}
Snapshot Response
{
    "command": "SUBSCRIBE",
    "event": "SNAPSHOT",
    "channel": "YIELD_CONTRACT",
    "data": [
        {
            "class": "YieldContract",
            "contractId": "7c1d5e2a-5b8e-11f1-9a51-0242ac120004",
            "baseAsset": "DOGE",
            "quoteAsset": "USDT",
            "status": "ACTIVE",
            "statusLabel": "Active",
            "step": "Active — earning",
            "redeemable": true,
            "principal": 1000,
            "cumulativeYieldNet": 8,
            "pendingYieldNet": 0.527,
            "credits": [ ... ]
        }
    ]
}
Update Response
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "YIELD_CONTRACT",
    "data": [
        {
            "class": "YieldContract",
            "contractId": "7c1d5e2a-5b8e-11f1-9a51-0242ac120004",
            "status": "REDEEMING",
            "statusLabel": "Redeeming",
            "redeemable": false,
            "redemptionRequested": true,
            "redemptionReason": "CLOSE",
            ...
        }
    ]
}

The examples are shortened; every message carries the whole contract. The fields are described under Contract Fields.

Request for Quote (RFQ)

Clients may request an RFQ stream for any symbol that is available on Open Trade.

Subscribe Request
{
    "command": "SUBSCRIBE",
    "channel": "RFQ POST",
    "channelArgs": [
        {
            "name": "instrument",
            "value": "[USD/ADA,ETH/BTC]"
        }
    ],
    "entries": [
        {
            "currency": "BTC",
            "orderQuantity": 1,
            "symbol": "BTC/USD"
        }
    ],
    "requestId": "test_001"
}
Acknowledgment
{
    "command": "SUBSCRIBE",
    "event": "ACK",
    "channel": "RFQPOST"
}
Data Response
{
    "command": "SUBSCRIBE",
    "event": "UPDATE",
    "channel": "RFQPOST",
    "data": [
        {
            "class": "OrderBook",
            "exchange": "CROSSTOWER",
            "symbol": "BTC/USD",
            "bids": [
                [19292.21]
            ],
            "asks": [
                [85100.0]
            ]
        }
    ]
}

Order Types Reference

Order Types

  • MARKET - Market order, executes immediately at best available price
  • LIMIT - Limit order, executes at specified price or better

Order Sub-Types

  • POST_ONLY - Only required if client wishes to submit a passive order which does not immediately fill. In case of immediate fill, order will be rejected.

Time In Force Options

Available Time In Force Values
  • GTC (Good Till Cancelled) - Default option. Orders remain in the order book for up to 90 days
  • GTD (Good Till Day) - Order will terminate at end of trading day (4:59 PM NY Time)
  • GTT (Good Till Time) - Order remains alive until specific date/time (cannot exceed 90 days)
  • FOK (Fill or Kill) - Order must be filled in full immediately or cancelled entirely
  • IOC (Immediate or Cancel) - Order fills any available amount immediately and cancels the rest

Order Status Values

Possible Order Status
  • NEW - Order has been accepted but not yet processed
  • ACTIVE - Order is active in the order book
  • PARTIALLY_FILLED - Order has been partially executed
  • FILLED - Order has been completely executed
  • CANCELLED - Order has been cancelled
  • REJECTED - Order was rejected by the exchange
  • EXPIRED - Order expired based on time in force settings
  • COMPLETED - Order processing is complete

Request Types

  • SMART - Default routing, automatically selects best exchange
  • DIRECT - Routes directly to specified exchange (requires exchangeName parameter)

Important Notes

Critical Requirements
  • Must be subscribed to a trading pair before placing orders on that pair
  • clientOrderId must be unique - recommended to use Unix timestamp
  • Price precision: up to 7 significant digits, 8 decimal places
  • Amount precision: up to 8 decimal places
  • Orders in the book for more than 90 days will be automatically cancelled