WebSocket Endpoints
The Nord API provides WebSocket connections for real-time data streaming.
Base URLs
| Environment | URL |
|---|---|
| Mainnet | wss://zo-mainnet.n1.xyz |
| Devnet | wss://zo-devnet.n1.xyz |
Available Streams
| Stream | Endpoint | Description |
|---|---|---|
| Candles | candle@{symbol}:{resolution} | OHLCV candlestick data |
| Trades | trades@{symbol} | Real-time trade executions |
| Orderbook | deltas@{symbol} | Orderbook updates (bids/asks) |
| Account | account@{account_id} | Account updates (fills, orders, balances) |
You can subscribe to multiple streams in a single connection:
wss://{host}/ws/trades@BTCUSD&deltas@BTCUSD&account@42Candle Data Stream
Stream real-time candlestick (OHLCV) data for charting.
Endpoint
wss://{host}/ws/candle@{symbol}:{resolution}| Parameter | Type | Description |
|---|---|---|
symbol | string | Trading pair (e.g., “BTCUSD”) |
resolution | string | Timeframe: “1”, “5”, “15”, “30”, “60”, “240”, “1D”, “1W”, “1M” |
Message Format
{
"res": "1",
"mid": 0,
"t": 1705312800,
"o": 97500.0,
"h": 97550.0,
"l": 97480.0,
"c": 97520.0,
"v": 125.5
}| Field | Type | Description |
|---|---|---|
res | string | Resolution/timeframe |
mid | number | Market ID |
t | number | Timestamp (Unix seconds) |
o, h, l, c | number | Open, High, Low, Close prices |
v | number | Volume (optional) |
Trades Stream
Stream real-time trade executions for a market.
Endpoint
wss://{host}/ws/trades@{symbol}| Parameter | Type | Description |
|---|---|---|
symbol | string | Trading pair (e.g., “BTCUSD”) |
Message Format
{
"trades": {
"market_symbol": "BTCUSD",
"trade_id": 12345,
"price": 97500.0,
"base_size": 0.5,
"taker_side": "bid",
"time": "2024-01-15T10:30:00Z"
}
}| Field | Type | Description |
|---|---|---|
market_symbol | string | Trading pair symbol |
trade_id | number | Unique trade identifier |
price | number | Execution price |
base_size | number | Trade size in base currency |
taker_side | string | "bid" (buy) or "ask" (sell) |
time | string | ISO 8601 timestamp |
Example: JavaScript
const ws = new WebSocket("wss://zo-mainnet.n1.xyz/ws/trades@BTCUSD");
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
const trade = data.trades;
console.log(`${trade.taker_side.toUpperCase()} ${trade.base_size} @ $${trade.price}`);
};Orderbook Deltas Stream
Stream real-time orderbook updates (bid/ask changes).
Endpoint
wss://{host}/ws/deltas@{symbol}| Parameter | Type | Description |
|---|---|---|
symbol | string | Trading pair (e.g., “BTCUSD”) |
Message Format
{
"delta": {
"market_symbol": "BTCUSD",
"update_id": 98765,
"bids": [[97500.0, 1.5], [97490.0, 2.0]],
"asks": [[97510.0, 0.8], [97520.0, 1.2]]
}
}| Field | Type | Description |
|---|---|---|
market_symbol | string | Trading pair symbol |
update_id | number | Sequence number for ordering |
bids | array | Bid updates as [price, size] pairs |
asks | array | Ask updates as [price, size] pairs |
[!NOTE] A size of
0indicates the price level should be removed from the orderbook.
Example: JavaScript
const ws = new WebSocket("wss://zo-mainnet.n1.xyz/ws/deltas@BTCUSD");
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
const delta = data.delta;
// Apply delta updates to your local orderbook
delta.bids.forEach(([price, size]) => {
if (size === 0) {
// Remove price level
} else {
// Update price level with new size
}
});
};Account Stream
Stream real-time account updates including order fills, placements, cancellations, and balance changes.
Endpoint
wss://{host}/ws/account@{account_id}| Parameter | Type | Description |
|---|---|---|
account_id | number | Your Nord account ID |
Message Format
{
"account": {
"account_id": 42,
"update_id": 123456,
"fills": {
"order_123": {
"order_id": 123,
"market_id": 0,
"maker_id": 42,
"quantity": 0.5,
"price": 97500.0
}
},
"places": {
"order_124": {
"market_id": 0,
"side": "bid",
"price": 97000.0,
"current_size": 1.0
}
},
"cancels": {},
"balances": {
"0": { "token_id": 0, "amount": 1000.0 }
}
}
}| Field | Type | Description |
|---|---|---|
account_id | number | Account identifier |
update_id | number | Sequence number for ordering |
fills | object | Filled orders (keyed by order ID) |
places | object | Newly placed orders |
cancels | object | Cancelled orders |
balances | object | Updated token balances |
Example: JavaScript
const accountId = 42; // Your account ID
const ws = new WebSocket(`wss://zo-mainnet.n1.xyz/ws/account@${accountId}`);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
const account = data.account;
// Handle fills
Object.values(account.fills || {}).forEach(fill => {
console.log(`Order ${fill.order_id} filled: ${fill.quantity} @ $${fill.price}`);
});
// Handle new orders
Object.entries(account.places || {}).forEach(([orderId, order]) => {
console.log(`Order ${orderId} placed: ${order.side} ${order.current_size} @ $${order.price}`);
});
// Handle cancellations
Object.keys(account.cancels || {}).forEach(orderId => {
console.log(`Order ${orderId} cancelled`);
});
};Connection Best Practices
- Reconnection: Implement automatic reconnection with exponential backoff
- Heartbeat: Respond to server pings to keep the connection alive
- Sequence tracking: Use
update_idto detect missed messages - Resource cleanup: Close connections when no longer needed
Reconnecting Client Example
import asyncio
import websockets
import json
async def resilient_stream(symbol: str):
uri = f"wss://zo-mainnet.n1.xyz/ws/trades@{symbol}"
retry_delay = 1
while True:
try:
async with websockets.connect(uri) as ws:
retry_delay = 1
async for message in ws:
yield json.loads(message)
except websockets.ConnectionClosed:
await asyncio.sleep(retry_delay)
retry_delay = min(retry_delay * 2, 30)
asyncio.run(resilient_stream("BTCUSD"))Last updated on