WebSocket Streaming
Receive indicator values pushed to you as candles close, over a persistent connection.
The streaming service pushes indicator updates over a WebSocket connection. Instead of polling the REST API, you subscribe to indicators and receive values the moment each candle closes (or on every tick, depending on your configuration).
wss://v2.taapi.io/streaming
Connection flow
- Open a WebSocket connection to
wss://v2.taapi.io/streaming. - Send an auth message with your API key. You must authenticate before subscribing.
- Send subscribe messages for the indicators you want.
- Receive update messages as indicator values are computed.
- Send unsubscribe messages when you no longer need an indicator, or list to see active subscriptions.
Authentication
Send this message immediately after connecting. All subsequent messages are ignored until authentication succeeds.
{ "type": "auth", "token": "Bearer YOUR_API_KEY" }
{ "type": "auth_ok" }
{ "type": "auth_error", "error": "Invalid or missing API key." }
Connections that fail authentication are closed by the server.
Subscribe
After authenticating, send a subscribe message for each indicator you want.
{
"type": "subscribe",
"exchange": "binance",
"symbol": "BTCUSDT",
"interval": "1m",
"indicator": "rsi",
"params": { "period": 14 },
"candleClose": true
}
| Field | Required | Description |
|---|---|---|
type | Yes | Must be "subscribe". |
exchange | Yes | Exchange identifier, e.g. binance. |
symbol | Yes | Trading pair, e.g. BTCUSDT. |
interval | Yes | Candle interval: 1m, 5m, 15m, 1h, 4h, 1d, 1w. |
indicator | Yes | Indicator name, e.g. rsi, ema, macd. |
params | No | Indicator-specific parameters, e.g. { "period": 14 }. |
candleClose | No | When true, only send updates when a candle closes (not on every tick). Default: false. |
Receiving updates
After subscribing, the server sends update messages as values are computed.
{
"type": "update",
"subscription": "BINANCE:BTC/USDT:1m",
"data": { "rsi": 45.2 }
}
Note: the subscription key uses uppercase exchange and symbol. This is intentional — the format is EXCHANGE:SYMBOL:INTERVAL in uppercase regardless of how you sent the subscribe message.
Subscribe bulk
Subscribe to many indicators, symbols, and timeframes in one message using a subscribe_bulk message. This mirrors the structure of POST /bulk.
{
"type": "subscribe_bulk",
"constructs": [
{
"exchange": "binance",
"symbol": "BTCUSDT",
"interval": "1m",
"indicators": [
{ "indicator": "rsi", "params": { "period": 14 } },
{ "indicator": "ema", "params": { "period": 9 } }
]
},
{
"exchange": "binance",
"symbol": "ETHUSDT",
"interval": "5m",
"indicators": [
{ "indicator": "rsi", "params": { "period": 14 } }
]
}
]
}
candleClose applies per-construct.
Unsubscribe
{
"type": "unsubscribe",
"exchange": "binance",
"symbol": "BTCUSDT",
"interval": "1m",
"indicator": "rsi",
"params": {}
}
List subscriptions
{ "type": "list" }
{ "type": "subscriptions", "data": [...] }
Throttle limits
Error messages
The server sends error messages for invalid subscribe/unsubscribe requests without closing the connection:
{
"type": "error",
"error": "Human-readable description of the problem"
}
Reconnection and heartbeat
WebSocket connections can drop due to network issues or server restarts. Build your client to handle disconnects gracefully:
- Reconnect with exponential backoff. Start with a 1-second delay and double it on each failed attempt, up to a maximum (e.g. 30 seconds). Reset the counter on a successful reconnect.
- Re-authenticate and re-subscribe after reconnecting. The server does not restore subscriptions automatically — you must repeat the
authmessage and allsubscribemessages after each reconnect. - Ping/pong. Send a WebSocket ping frame periodically (every 30 seconds is common) to keep the connection alive through proxies and firewalls. The server will respond with a pong frame.
const WebSocket = require('ws');
let ws;
let delay = 1000;
function connect() {
ws = new WebSocket('wss://v2.taapi.io/streaming');
ws.on('open', () => {
delay = 1000; // reset backoff
ws.send(JSON.stringify({ type: 'auth', token: 'Bearer YOUR_API_KEY' }));
});
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'auth_ok') {
// re-subscribe after connect/reconnect
ws.send(JSON.stringify({
type: 'subscribe', exchange: 'binance',
symbol: 'BTCUSDT', interval: '1m',
indicator: 'rsi', params: { period: 14 },
candleClose: true,
}));
}
if (msg.type === 'update') {
console.log(msg.subscription, msg.data);
}
});
ws.on('close', () => {
console.log(`Disconnected. Reconnecting in ${delay}ms…`);
setTimeout(connect, delay);
delay = Math.min(delay * 2, 30000);
});
ws.on('error', (err) => {
console.error('WS error:', err.message);
ws.close();
});
// keepalive ping every 30 s
setInterval(() => { if (ws.readyState === WebSocket.OPEN) ws.ping(); }, 30000);
}
connect();
Health check
GET https://v2.taapi.io/streaming/health