Skip to main content
Version: 1.0

WebSocket Streams

WebSocket connections provide real-time market data and account updates without polling the REST API.

Connection

Base URLs

EnvironmentWebSocket URL
Productionws://119.8.50.236:8088/ws
Testnetws://119.8.50.236:8088/ws

Connection Example

const ws = new WebSocket('ws://119.8.50.236:8088/ws');

ws.onopen = () => {
console.log('Connected');
};

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Received:', data);
};

ws.onerror = (error) => {
console.error('Error:', error);
};

ws.onclose = () => {
console.log('Disconnected');
};

Subscribing to Streams

Subscribe

ws.send(JSON.stringify({
method: 'SUBSCRIBE',
params: ['btcusdt@ticker', 'ethusdt@ticker'],
id: 1
}));

Unsubscribe

ws.send(JSON.stringify({
method: 'UNSUBSCRIBE',
params: ['btcusdt@ticker'],
id: 2
}));

List Subscriptions

ws.send(JSON.stringify({
method: 'LIST_SUBSCRIPTIONS',
id: 3
}));

Market Streams

Ticker Stream

24-hour rolling window statistics for a symbol.

Stream Name: <symbol>@ticker

ws.send(JSON.stringify({
method: 'SUBSCRIBE',
params: ['btcusdt@ticker'],
id: 1
}));

Payload:

{
"e": "24hrTicker",
"E": 1672515782136,
"s": "BTCUSDT",
"p": "500.00",
"P": "1.02",
"w": "49500.00",
"c": "50000.00",
"Q": "0.500",
"o": "49500.00",
"h": "51000.00",
"l": "49000.00",
"v": "10000.000",
"q": "495000000.00",
"O": 1672429382136,
"C": 1672515782136,
"F": 100,
"L": 200,
"n": 101
}
FieldDescription
eEvent type
EEvent time (ms)
sSymbol
pPrice change
PPrice change percent
wWeighted average price
cLast price
QLast quantity
oOpen price
hHigh price
lLow price
vTotal traded base asset volume
qTotal traded quote asset volume
nNumber of trades

Mini Ticker Stream

Simplified ticker with key fields only.

Stream Name: <symbol>@miniTicker

{
"e": "24hrMiniTicker",
"E": 1672515782136,
"s": "BTCUSDT",
"c": "50000.00",
"o": "49500.00",
"h": "51000.00",
"l": "49000.00",
"v": "10000.000",
"q": "495000000.00"
}

All Market Tickers

Stream Name: !ticker@arr

Receives ticker updates for all symbols.

Order Book Depth

Stream Name: <symbol>@depth<levels> or <symbol>@depth<levels>@<speed>

ParameterOptions
levels5, 10, 20
speed100ms, 250ms, 500ms
// Top 10 levels, 100ms updates
ws.send(JSON.stringify({
method: 'SUBSCRIBE',
params: ['btcusdt@depth10@100ms'],
id: 1
}));

Payload:

{
"e": "depthUpdate",
"E": 1672515782136,
"s": "BTCUSDT",
"U": 157,
"u": 160,
"b": [
["49990.00", "1.500"],
["49980.00", "2.300"]
],
"a": [
["50000.00", "0.800"],
["50010.00", "1.200"]
]
}
FieldDescription
bBids [price, quantity]
aAsks [price, quantity]
UFirst update ID
uFinal update ID

Kline/Candlestick Stream

Stream Name: <symbol>@kline_<interval>

IntervalDescription
1m1 minute
3m3 minutes
5m5 minutes
15m15 minutes
30m30 minutes
1h1 hour
2h2 hours
4h4 hours
6h6 hours
8h8 hours
12h12 hours
1d1 day
3d3 days
1w1 week
1M1 month
ws.send(JSON.stringify({
method: 'SUBSCRIBE',
params: ['btcusdt@kline_1h'],
id: 1
}));

Payload:

{
"e": "kline",
"E": 1672515782136,
"s": "BTCUSDT",
"k": {
"t": 1672512000000,
"T": 1672515599999,
"s": "BTCUSDT",
"i": "1h",
"o": "49500.00",
"c": "50000.00",
"h": "50100.00",
"l": "49400.00",
"v": "1000.000",
"n": 500,
"x": false,
"q": "49750000.00"
}
}
FieldDescription
tKline start time
TKline close time
iInterval
oOpen price
cClose price
hHigh price
lLow price
vVolume
xIs kline closed

Trade Stream

Real-time trade execution data.

Stream Name: <symbol>@trade

{
"e": "trade",
"E": 1672515782136,
"s": "BTCUSDT",
"t": 12345,
"p": "50000.00",
"q": "0.100",
"T": 1672515782100,
"m": true
}
FieldDescription
tTrade ID
pPrice
qQuantity
TTrade time
mIs buyer market maker

Aggregated Trade Stream

Stream Name: <symbol>@aggTrade

Aggregates trades that fill at the same time, price, and side.

Mark Price Stream

Stream Name: <symbol>@markPrice or <symbol>@markPrice@1s

{
"e": "markPriceUpdate",
"E": 1672515782136,
"s": "BTCUSDT",
"p": "50000.00",
"i": "50010.00",
"r": "0.00010000",
"T": 1672531200000
}
FieldDescription
pMark price
iIndex price
rFunding rate
TNext funding time

User Data Streams

User data streams provide real-time updates for your account. These require authentication.

Get Listen Key

curl -X POST "http://119.8.50.236:8088/api/v1/listenKey" \
-H "Authorization: Bearer YOUR_TOKEN"

Response:

{
"code": 0,
"data": {
"listenKey": "pqia91ma19a5s61cv6a81va65sdf19v8a65a1a5s61cv6a81va65sdf19v8a65a1"
}
}

Connect to User Data Stream

const listenKey = 'pqia91ma19a5s61cv6a81va65sdf19v8a65a1a5s61cv6a81va65sdf19v8a65a1';
const ws = new WebSocket(`ws://119.8.50.236:8088/ws/${listenKey}`);

Keep Listen Key Alive

Listen keys expire after 60 minutes. Send a keepalive every 30 minutes:

curl -X PUT "http://119.8.50.236:8088/api/v1/listenKey" \
-H "Authorization: Bearer YOUR_TOKEN"

Account Update Event

Triggered when account balance changes.

{
"e": "ACCOUNT_UPDATE",
"E": 1672515782136,
"T": 1672515782100,
"a": {
"m": "ORDER",
"B": [
{
"a": "USDT",
"wb": "10000.00",
"cw": "9500.00"
}
],
"P": [
{
"s": "BTCUSDT",
"pa": "0.100",
"ep": "50000.00",
"up": "50.00"
}
]
}
}
FieldDescription
mEvent reason (DEPOSIT, WITHDRAW, ORDER, FUNDING_FEE, etc.)
BBalance updates
PPosition updates
wbWallet balance
cwCross wallet balance
paPosition amount
epEntry price
upUnrealized profit

Order Update Event

Triggered when an order is created, filled, or cancelled.

{
"e": "ORDER_TRADE_UPDATE",
"E": 1672515782136,
"T": 1672515782100,
"o": {
"s": "BTCUSDT",
"c": "myOrder123",
"S": "BUY",
"o": "LIMIT",
"f": "GTC",
"q": "0.100",
"p": "50000.00",
"ap": "0",
"sp": "0",
"x": "NEW",
"X": "NEW",
"i": 123456789,
"l": "0",
"z": "0",
"L": "0",
"T": 1672515782100,
"t": 0,
"rp": "0"
}
}
FieldDescription
sSymbol
cClient order ID
SSide
oOrder type
qOriginal quantity
pOriginal price
apAverage price
xExecution type (NEW, TRADE, CANCELED, EXPIRED)
XOrder status
iOrder ID
lLast filled quantity
zCumulative filled quantity
LLast filled price
tTrade ID
rpRealized profit

Connection Management

Keep-Alive

Send a ping frame every 30 minutes to prevent disconnection:

setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
}
}, 30 * 60 * 1000);

Reconnection

Implement automatic reconnection with exponential backoff:

class WebSocketClient {
constructor(url) {
this.url = url;
this.reconnectDelay = 1000;
this.maxReconnectDelay = 30000;
this.connect();
}

connect() {
this.ws = new WebSocket(this.url);

this.ws.onopen = () => {
console.log('Connected');
this.reconnectDelay = 1000;
this.resubscribe();
};

this.ws.onclose = () => {
console.log('Disconnected, reconnecting...');
setTimeout(() => this.connect(), this.reconnectDelay);
this.reconnectDelay = Math.min(
this.reconnectDelay * 2,
this.maxReconnectDelay
);
};

this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
}

resubscribe() {
// Re-subscribe to previous streams
}
}

Rate Limits

LimitValue
Connections per IP5
Subscriptions per connection200
Messages per second10

Complete Example

import json
import websocket
import threading

class BitzoomWebSocket:
def __init__(self):
self.url = "ws://119.8.50.236:8088/ws"
self.ws = None
self.subscriptions = []

def on_message(self, ws, message):
data = json.loads(message)

if 'e' in data:
event_type = data['e']

if event_type == '24hrTicker':
self.handle_ticker(data)
elif event_type == 'trade':
self.handle_trade(data)
elif event_type == 'kline':
self.handle_kline(data)
elif event_type == 'depthUpdate':
self.handle_depth(data)

def handle_ticker(self, data):
print(f"Ticker {data['s']}: {data['c']} ({data['P']}%)")

def handle_trade(self, data):
print(f"Trade {data['s']}: {data['q']} @ {data['p']}")

def handle_kline(self, data):
k = data['k']
print(f"Kline {k['s']} {k['i']}: O={k['o']} H={k['h']} L={k['l']} C={k['c']}")

def handle_depth(self, data):
best_bid = data['b'][0] if data['b'] else None
best_ask = data['a'][0] if data['a'] else None
print(f"Depth {data['s']}: Bid={best_bid}, Ask={best_ask}")

def on_error(self, ws, error):
print(f"Error: {error}")

def on_close(self, ws, close_status_code, close_msg):
print("Connection closed")

def on_open(self, ws):
print("Connected")
self.subscribe(['btcusdt@ticker', 'btcusdt@trade', 'btcusdt@kline_1m'])

def subscribe(self, streams):
self.subscriptions.extend(streams)
self.ws.send(json.dumps({
"method": "SUBSCRIBE",
"params": streams,
"id": 1
}))

def run(self):
self.ws = websocket.WebSocketApp(
self.url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
on_open=self.on_open
)
self.ws.run_forever()

if __name__ == "__main__":
client = BitzoomWebSocket()
client.run()

Next Steps