Skip to main content

Real-time Data (WebSocket)

Use the WebSocket at wss://<your-api-domain>/stream instead of polling REST endpoints. You get updates as they happen, and you stay well clear of the REST rate limits.

Channels​

ChannelAuthYou receive
orderbookPublicOrder book snapshots and updates. Use orderbook:btc-usdt for one pair.
tradePublicPublic trades. Use trade:btc-usdt for one pair.
pricePublicAsset prices, as a full snapshot followed by per-asset updates.
orderUser keyYour orders being created, filled or cancelled.
usertradeUser keyYour fills.
walletUser keyBalance changes.
depositUser keyYour incoming deposits.
withdrawalUser keyYour withdrawals.
stakeUser keyYour staking updates.
adminAdmin keyDeposits, withdrawals and stakes for all users. Use this to drive back-office automation.

Each message has a topic, an action (partial for the first snapshot, then insert, update or delete) and data. For full payload examples, see the WebSocket reference.

With hollaex-node-lib​

The library signs the connection, sends keep-alive pings and reconnects automatically.

const hollaex = require('hollaex-node-lib');

const client = new hollaex({
apiURL: process.env.HOLLAEX_API_URL,
wsURL: process.env.HOLLAEX_WS_URL, // wss://<your-api-domain>/stream
apiKey: process.env.HOLLAEX_API_KEY,
apiSecret: process.env.HOLLAEX_API_SECRET,
});

client.connect(['orderbook:btc-usdt', 'order', 'wallet']);

client.ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.topic === 'order') console.log('Order update:', msg.action, msg.data);
if (msg.topic === 'wallet') console.log('Balances:', msg.data);
});

// Later:
// client.subscribe(['trade:btc-usdt']);
// client.unsubscribe(['orderbook:btc-usdt']);
// client.disconnect();

With a plain WebSocket client​

const WebSocket = require('ws');

const ws = new WebSocket('wss://<your-api-domain>/stream'); // add signed query params for private channels

ws.on('open', () => {
ws.send(JSON.stringify({ op: 'subscribe', args: ['orderbook:btc-usdt', 'trade:btc-usdt'] }));
// The server closes idle connections after about 1 minute, so ping every 30 s
setInterval(() => ws.send(JSON.stringify({ op: 'ping' })), 30000);
});

ws.on('message', (raw) => console.log(JSON.parse(raw)));

For private channels, sign the connection URL. See WebSocket authentication.

Production tips​

  • Reconnect with backoff. Connections can drop. After reconnecting, resubscribe, and treat the next partial message as the new source of truth.
  • Keep a local order book. Apply update messages on top of the last partial. If you think you've missed messages, resubscribe to get a fresh snapshot.
  • Reconcile with REST. After downtime, call the matching REST endpoint (for example deposits or orders) to fill any gaps before you trust the stream again.
  • Make processing idempotent. Key deposits and withdrawals on their transaction_id so a repeated message can't credit something twice.