Topics Reference
Complete WebSocket topic documentation with message formats
WebSocket Topics Reference
This document provides complete documentation for all WebSocket topics, including message structures and field descriptions.
Topic Overview
| Topic | Pattern | Auth | Description |
|---|---|---|---|
| Trades | {pair}@trades | No | Public trade stream |
| Depth | {pair}@depth@{speed} | No | Order book updates (speed: 100ms, 1000ms) |
| Prices | *@prices@{category} | No | Price feed |
| Market Schedules | {pair}@market-schedules | No | Trading hours |
| Sub-Account Orders | {id}@subaccount-orders | Yes | Order updates |
| Sub-Account OTC Orders | {id}@subaccount-otc-orders | Yes | OTC order updates |
| Balances | {id}@balances | Yes | Balance updates |
| Balance Aggregate | {id}@balance-agg@{quote} | Yes | Aggregate balance |
| Exposures | {id}@exposures | Yes | Exposure updates |
| OTC Trades | {pair}@otc-trades | No | OTC trade stream |
| OTC Depth Snapshots | {pair}@otc-depth-snapshots | No | OTC depth |
| OTC Pair Listings | {pair}@otc-listings | No | OTC availability |
Public Topics
Trades
Real-time trade stream for a trading pair.
Topic: {pair}@trades
Example: BTC/CHF@trades
Authentication: Not required
Subscribe
{
"e": "tdx:subscribe",
"t": "BTC/CHF@trades"
}Confirmation
{
"e": "tdx:subscription_received",
"t": "BTC/CHF@trades"
}Trade Event
{
"e": "trade",
"t": "BTC/CHF@trades",
"d": {
"d": 1705667200000,
"p": "45000.50",
"q": "1.5",
"i": "trade-uuid",
"a": "BUY"
}
}| Field | Type | Description |
|---|---|---|
d | integer | Timestamp (Unix milliseconds) |
p | string | Price |
q | string | Quantity |
i | string | Trade ID |
a | string | Aggressor side: BUY or SELL |
Depth (Order Book)
Order book depth updates for a trading pair.
Topic: {pair}@depth@{speed}
Speed Values: 100ms, 1000ms
Example: BTC/CHF@depth@1000ms
Authentication: Not required
Note: The speed parameter is required. It determines how frequently updates are sent (e.g.,
100msfor 10 updates/second,1000msfor 1 update/second).
Subscribe
{
"e": "tdx:subscribe",
"t": "BTC/CHF@depth@1000ms"
}Full Snapshot Event
Sent on initial subscription and periodically.
{
"e": "orderbook",
"t": "BTC/CHF@depth@1000ms",
"d": {
"u": 12345,
"b": [
["44999.00", "1.0"],
["44998.00", "2.5"]
],
"a": [
["45001.00", "0.5"],
["45002.00", "1.2"]
]
}
}| Field | Type | Description |
|---|---|---|
u | integer | Update ID (always present) |
b | array | Bids (buy orders) as [[price, quantity], ...], sorted by price descending. Omitted if no bids. |
a | array | Asks (sell orders) as [[price, quantity], ...], sorted by price ascending. Omitted if no asks. |
Note: When the orderbook is completely empty, only
uis present:{"u": 12345}
Incremental Update Event
Partial updates between snapshots.
{
"e": "update",
"t": "BTC/CHF@depth@1000ms",
"d": {
"u": 12340,
"U": 12345,
"b": [["44999.00", "1.5"]],
"a": [["45001.00", "0.0"]]
}
}| Field | Type | Description |
|---|---|---|
u | integer | First update ID in this batch |
U | integer | Last update ID in this batch |
b | array | Changed bids as [[price, quantity], ...] (quantity "0.0" = removed) |
a | array | Changed asks as [[price, quantity], ...] (quantity "0.0" = removed) |
Prices
Real-time price feed. Supports multiple price categories.
Topic: *@prices@{category}
Categories: platform, mid, auction, market
Example: *@prices@auction
Authentication: Not required
Debouncing: Yes (500ms)
Subscribe
{
"e": "tdx:subscribe",
"t": "*@prices@auction"
}Price Event
{
"e": "price",
"t": "BTC/CHF@prices@auction",
"d": {
"v": "45000.50",
"c": "-500.00",
"C": "-1.10"
}
}| Field | Type | Description |
|---|---|---|
v | string | Current price value |
c | string (optional) | 24h change (absolute) |
C | string (optional) | 24h change (percentage) |
Note: The topic in the response includes the actual pair symbol, not the wildcard.
Market Schedules
Trading schedule updates for a pair.
Topic: {pair}@market-schedules
Example: BTC/CHF@market-schedules
Authentication: Not required
Subscribe
{
"e": "tdx:subscribe",
"t": "BTC/CHF@market-schedules"
}Schedule Event
{
"e": "market_schedule",
"t": "BTC/CHF@market-schedules",
"d": {
"c": {
"state": "OPEN",
"start": "2025-01-19T09:00:00Z",
"end": "2025-01-19T17:00:00Z"
},
"n": {
"state": "CLOSED",
"start": "2025-01-19T17:00:00Z",
"end": "2025-01-20T09:00:00Z"
},
"t": "2025-01-19T17:00:00Z"
}
}| Field | Type | Description |
|---|---|---|
c | object | Current period |
c.state | string | Current state: OPEN, CLOSED, AUCTION, etc. |
c.start | timestamp | Period start time |
c.end | timestamp | Period end time |
n | object (optional) | Next period |
t | timestamp (optional) | Time of next period change |
Authenticated Topics
Sub-Account Orders
Order updates for a specific sub-account. Used for both subscribing to updates and placing/canceling orders.
Topic: {subAccountId}@subaccount-orders
Authentication: Required
Subscribe
{
"e": "tdx:subscribe",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@subaccount-orders",
"a": "jwt_token"
}Order Event
Sent when an order status changes.
{
"e": "order",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@subaccount-orders",
"d": {
"requestId": "req-123",
"orderId": "order-456",
"clientOrderId": "client-123",
"status": "NEW",
"type": "LIMIT",
"side": "BUY",
"quantity": "1.5",
"cumulativeQuantity": "0.0",
"price": "45000.50",
"symbol": "BTC/CHF"
}
}| Field | Type | Description |
|---|---|---|
requestId | string | Request ID (for correlation) |
orderId | string | Order ID |
clientOrderId | string | Client-provided order ID |
status | string | Order status (see below) |
type | string | LIMIT or MARKET |
side | string | BUY or SELL |
quantity | string | Order quantity |
cumulativeQuantity | string | Filled quantity |
price | string | Limit price |
symbol | string | Pair symbol |
Order Status Values: NEW, PARTIALLY_FILLED, FILLED, CANCELED, REJECTED, EXPIRED
Order Cancel Rejection Event
Sent when a cancel request fails.
{
"e": "order_cancel_reject",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@subaccount-orders",
"d": {
"orderId": "order-456",
"clientOrderId": "client-123",
"reason": "Order not found",
"text": "Unable to cancel"
}
}Create Order
{
"e": "tdx:order_create",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@subaccount-orders",
"a": "jwt_token",
"d": {
"dry": false,
"order": {
"subAccountId": "7376524e-6b6b-4137-9719-7e07a7709804",
"symbol": "BTC/CHF",
"side": "BUY",
"type": "LIMIT",
"quantity": "1.5",
"price": "45000.50",
"timeInForce": "GTC",
"clientOrderId": "client-123"
}
}
}| Field | Type | Required | Description |
|---|---|---|---|
dry | boolean | No | If true, validates without creating |
order.subAccountId | string | Yes | Sub-account ID |
order.symbol | string | Yes | Pair symbol |
order.side | string | Yes | BUY or SELL |
order.type | string | Yes | LIMIT or MARKET |
order.quantity | string | Yes | Order quantity |
order.price | string | For LIMIT | Limit price |
order.timeInForce | string | No | GTC, IOC, FOK |
order.clientOrderId | string | No | Client-provided ID |
order.minQuantity | string | No | Minimum fill quantity |
Response:
{"e": "tdx:order_create_received", "t": "...@subaccount-orders"}{
"e": "tdx:order_create_submitted",
"t": "...@subaccount-orders",
"d": {"clientOrderId": "client-123", "orderId": "order-789"}
}Cancel Order
Order cancellation is asynchronous. The server responds in stages:
- Acknowledgment (
tdx:order_cancel_received) - Request received - Submission (
tdx:order_cancel_submitted) - Cancel submitted to exchange - Result (async) - Either
orderevent (status changed) ororder_cancel_rejectif failed
{
"e": "tdx:order_cancel",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@subaccount-orders",
"a": "jwt_token",
"d": {
"orderId": "order-789",
"subAccountId": "7376524e-6b6b-4137-9719-7e07a7709804"
}
}Response Flow:
// Step 1: Acknowledgment (immediate)
{"e": "tdx:order_cancel_received", "t": "...@subaccount-orders"}
// Step 2: Submission
{
"e": "tdx:order_cancel_submitted",
"t": "...@subaccount-orders",
"d": {"requestId": "req-789", "orderId": "order-789"}
}
// Step 3: Result (async - may arrive later)
// Success: order event with updated status
// Failure: order_cancel_reject eventNote: The
order_cancel_rejectevent arrives asynchronously and may not be immediate. Applications should handle timeouts and check order status separately if confirmation is critical.
Sub-Account OTC Orders
OTC order updates for a specific sub-account.
Topic: {subAccountId}@subaccount-otc-orders
Authentication: Required
Subscribe
{
"e": "tdx:subscribe",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@subaccount-otc-orders",
"a": "jwt_token"
}OTC Order Update Event
{
"e": "otc_order_update",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@subaccount-otc-orders",
"d": {
"id": "otc-order-123",
"subAccountId": "7376524e-6b6b-4137-9719-7e07a7709804",
"clientOrderId": "client-456",
"pairId": "pair-789",
"status": "PENDING",
"type": "MARKET",
"side": "BUY",
"clientAmount": "50000.00",
"quantity": "1.0",
"cumulativeQuantity": "0.0",
"price": "50000.00",
"timeInForce": "GTC",
"comment": "optional comment",
"createdAt": "2025-01-19T10:00:00Z",
"updatedAt": "2025-01-19T10:00:00Z",
"triggeredAt": null
}
}| Field | Type | Description |
|---|---|---|
id | string | OTC order ID |
subAccountId | string | Sub-account ID |
clientOrderId | string | Client-provided ID |
pairId | string | Pair ID |
status | string | Status (see OTC order status values) |
type | string | Order type |
side | string | BUY or SELL |
clientAmount | string | Amount charged to client |
quantity | string | Order quantity |
cumulativeQuantity | string | Filled quantity |
price | string | Execution price |
timeInForce | string | GTC, etc. |
comment | string | Optional comment |
createdAt | timestamp | Creation time |
updatedAt | timestamp | Last update time |
triggeredAt | timestamp | Trigger time (for scheduled orders) |
OTC Order Status Values: TENTATIVE, PENDING, OPEN, FILLED, CANCELED, REJECTED, PENDING_CANCEL
Balances
Balance updates for a sub-account. Updates are debounced by instrument.
Topic: {subAccountId}@balances
Authentication: Required
Debouncing: Yes (500ms, by instrument)
Subscribe
{
"e": "tdx:subscribe",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@balances",
"a": "jwt_token"
}Balance Event
{
"e": "balance",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@balances",
"d": {
"i": "btc-instrument-uuid",
"a": "2.50000000",
"o": "0.50000000",
"w": "0.10000000",
"c": "0.00000000"
}
}| Field | Type | Description |
|---|---|---|
i | string | Instrument ID |
a | string | Available balance |
o | string | Orders reserved |
w | string | Withdrawals reserved |
c | string | Settlement line used |
Balance Aggregate
Aggregate portfolio value in a quote currency. Updates are debounced.
Topic: {subAccountId}@balance-agg@{quoteCurrency}
Example: 7376524e-6b6b-4137-9719-7e07a7709804@balance-agg@CHF
Authentication: Required
Debouncing: Yes (500ms, by quote currency)
Subscribe
{
"e": "tdx:subscribe",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@balance-agg@CHF",
"a": "jwt_token"
}Balance Aggregate Event
{
"e": "balance-agg",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@balance-agg@CHF",
"d": {
"q": "CHF",
"v": "500000.00"
}
}| Field | Type | Description |
|---|---|---|
q | string | Quote currency |
v | string | Total value in quote currency |
Exposures
Exposure and overdraft updates for a sub-account.
Topic: {subAccountId}@exposures
Authentication: Required
Subscribe
{
"e": "tdx:subscribe",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@exposures",
"a": "jwt_token"
}Exposure Event
{
"e": "exposure",
"t": "7376524e-6b6b-4137-9719-7e07a7709804@exposures",
"d": {
"i": "quotation-instrument-uuid",
"o": "100000.00",
"u": "50000.00"
}
}| Field | Type | Description |
|---|---|---|
i | string | Quotation instrument ID |
o | string | Overdraft amount |
u | string | Utilized amount |
OTC Topics
OTC Trades
Public OTC trade stream for a pair.
Topic: {pair}@otc-trades
Example: BTC/USD@otc-trades
Authentication: Not required
Subscribe
{
"e": "tdx:subscribe",
"t": "BTC/USD@otc-trades"
}OTC Trade Event
{
"e": "otc-trade",
"t": "BTC/USD@otc-trades",
"d": {
"i": "otc-trade-uuid",
"p": "50000.00",
"q": "1.0",
"s": "Buy",
"d": 1705667200000
}
}| Field | Type | Description |
|---|---|---|
i | string | Trade ID |
p | string | Price |
q | string | Quantity |
s | string | Side: Buy or Sell |
d | integer | Timestamp (Unix milliseconds) |
OTC Depth Snapshots
OTC liquidity depth snapshots.
Topic: {pair}@otc-depth-snapshots
Example: BTC/USD@otc-depth-snapshots
Authentication: Not required
Subscribe
{
"e": "tdx:subscribe",
"t": "BTC/USD@otc-depth-snapshots"
}OTC Depth Snapshot Event
{
"e": "otc-depth-snapshot",
"t": "BTC/USD@otc-depth-snapshots",
"d": {
"symbol": "BTC/USD",
"bids": [
{"price": "49999.00", "quantity": "0.5"},
{"price": "49998.00", "quantity": "1.0"}
],
"asks": [
{"price": "50001.00", "quantity": "0.5"},
{"price": "50002.00", "quantity": "1.0"}
],
"timestamp": "2025-01-19T10:00:00Z"
}
}| Field | Type | Description |
|---|---|---|
symbol | string | Pair symbol |
bids | array | Bid levels |
asks | array | Ask levels |
bids[].price | string | Bid price |
bids[].quantity | string | Bid quantity |
asks[].price | string | Ask price |
asks[].quantity | string | Ask quantity |
timestamp | timestamp | Snapshot time |
OTC Pair Listings
OTC pair listing availability updates.
Topic: {pair}@otc-listings
Example: BTC/USD@otc-listings
Authentication: Not required
Subscribe
{
"e": "tdx:subscribe",
"t": "BTC/USD@otc-listings"
}OTC Listing Update Event
{
"e": "otc_listing_update",
"t": "BTC/USD@otc-listings",
"d": {
"pairId": "pair-123",
"symbol": "BTC/USD",
"live": true,
"updatedAt": "2025-01-19T10:00:00Z"
}
}| Field | Type | Description |
|---|---|---|
pairId | string | Pair ID |
symbol | string | Pair symbol |
live | boolean | Whether OTC trading is available |
updatedAt | timestamp | Last update time |
RFQ (Request for Quote)
RFQ is the primary workflow for OTC trading. For complete documentation, see the RFQ documentation in the trading domain.
Topics:
{subAccountId}@quotes- Start quoting, receive streaming quotes{subAccountId}@accept- Accept a quote{subAccountId}@stop- Cancel an RFQ session
Session Management
Cancel on Disconnect
Enable automatic cancellation of all orders when the connection drops.
Topic: Not required Authentication: Required
{
"e": "tdx:cancel_on_disconnect",
"a": "jwt_token"
}Response
{
"e": "tdx:cancel_on_disconnect_succeeded"
}Notes:
- Only one cancel-on-disconnect session per client account is allowed
- If a second connection attempts to enable this, it will fail
- Orders are canceled when the WebSocket connection closes
Unsubscribe
Unsubscribe from any topic.
{
"e": "tdx:unsubscribe",
"t": "BTC/CHF@trades"
}Response
{
"e": "tdx:unsubscription_succeeded",
"t": "BTC/CHF@trades"
}Error Handling
All errors are returned with the tdx:error event:
{
"e": "tdx:error",
"t": "invalid@topic",
"d": {
"message": "Invalid topic format"
}
}Common Error Scenarios
| Error | Description |
|---|---|
| Invalid topic format | Topic doesn't match {target}@{category} pattern |
| Authentication required | Token missing for authenticated topic |
| Permission denied | User lacks access to sub-account |
| Rate limit exceeded | Too many messages (anonymous: 1 per 500ms) |
| Invalid event type | Unknown event in e field |
| Order validation failed | Order parameters invalid |
| Subscription conflict | Cancel-on-disconnect already active for account |
Updated 5 days ago
