WebSocket Integration
This guide explains how to integrate with the TradeX Market Data WebSocket API for real-time market data: trades, order books, tickers, candles, mark prices, index prices, and funding rates.
Connection
Section titled “Connection”ws://localhost:8080/ws # localwss://marketdata.dokploy.samarpit.dev/ws # productionOne connection is multiplexed across all channels. You subscribe per
(channel, symbol). Rate limit: 100 messages/second per client.
Client messages
Section titled “Client messages”Subscribe
Section titled “Subscribe”One channel + one symbol per message:
{ "op": "subscribe", "channel": "book", "symbol": "BTCUSDT-PERP" }Channels: book, ticker, trades, mark, index, funding,
candle:<interval> (intervals 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w).
Send one subscribe per channel/symbol you want.
Unsubscribe
Section titled “Unsubscribe”{ "op": "unsubscribe", "channel": "book", "symbol": "BTCUSDT-PERP" }Configure order-book rounding
Section titled “Configure order-book rounding”Set arbitrary decimal price rounding for book (applies to your connection):
{ "op": "config", "prec": 0.5 }{ "op": "ping" }Server messages
Section titled “Server messages”Every server frame has a type and (for channel data) channel, symbol, data,
and an optional stale flag:
{ "type": "snapshot", "channel": "book", "symbol": "BTCUSDT-PERP", "data": { "bids": [], "asks": [], "seq": 0 } }{ "type": "delta", "channel": "trades", "symbol": "BTCUSDT-PERP", "data": { }, "stale": false }type is one of:
snapshot— full current state for a channel (sent on subscribe, and for book on rounding changes).delta— an incremental update.pong— reply toping.ack— reply toconfig(data: { "prec": 0.5 }).error—data: { "message": "..." }.
Candle frames use the channel name candle:<interval>:
{ "type": "delta", "channel": "candle:1m", "symbol": "BTCUSDT-PERP", "data": { } }Example — browser
Section titled “Example — browser”const ws = new WebSocket('wss://marketdata.dokploy.samarpit.dev/ws');
ws.onopen = () => { ws.send(JSON.stringify({ op: 'subscribe', channel: 'trades', symbol: 'BTCUSDT-PERP' })); ws.send(JSON.stringify({ op: 'subscribe', channel: 'book', symbol: 'BTCUSDT-PERP' })); ws.send(JSON.stringify({ op: 'config', prec: 0.5 }));};
ws.onmessage = (event) => { const frame = JSON.parse(event.data); switch (frame.type) { case 'snapshot': case 'delta': handleUpdate(frame.channel, frame.symbol, frame.data, frame.stale); break; case 'pong': break; case 'ack': break; case 'error': console.error('WS error:', frame.data?.message); break; }};Example — Python
Section titled “Example — Python”import asyncio, json, websockets
async def subscribe(): uri = "wss://marketdata.dokploy.samarpit.dev/ws" async with websockets.connect(uri) as ws: await ws.send(json.dumps({"op": "subscribe", "channel": "trades", "symbol": "BTCUSDT-PERP"})) async for raw in ws: frame = json.loads(raw) if frame.get("type") in ("snapshot", "delta"): print(frame["channel"], frame["symbol"], frame["data"])
asyncio.run(subscribe())Reconnection
Section titled “Reconnection”On reconnect, re-send a subscribe for every (channel, symbol) you had, then
re-send config if you use non-default rounding. Use exponential backoff.
Best practices
Section titled “Best practices”- Subscribe only to the channels/symbols you need (one message each).
- Re-subscribe on reconnect; the server does not remember prior subscriptions.
- Honour the
staleflag — surface stale feeds in the UI rather than treating them as live. - Respect the 100 msg/s/client rate limit.