WebSocket Streaming
Receive calculated indicator values pushed to your client in real time as each candle closes — no polling, no repeated HTTP calls. Establish one persistent connection and subscribe to as many streams as your plan allows.
WebSocket URL:
wss://v2.taapi.io/streaming
Timeframe throttles
Streaming is optimised for intraday intervals. Supported timeframes and their minimum push intervals:
| Timeframe | Min push interval |
|---|---|
1m |
2 seconds |
5m |
5 seconds |
15m |
8 seconds |
1h |
15 seconds |
For macro intervals (
4h,1d,1w) use REST polling instead — push frequency would offer no meaningful advantage over a scheduled GET.
Connection flow
1. Connect & authenticate
Open a WebSocket connection to wss://v2.taapi.io/streaming. Send the auth message immediately — the server drops unauthenticated connections after a short timeout.
{ "type": "auth", "token": "Bearer YOUR_API_KEY" }
Server response on success:
{
"type": "auth_ok",
"userId": "6a1b2c3d4e5f6a1b2c3d4e5f",
"plan": {
"socketSubscriptionsAllowed": 50,
"streamThrottleMs": 5000
}
}
Server response on failure:
{ "type": "auth_error", "error": "Unauthorized" }
2. Subscribe to an indicator
Each subscription requires a unique id that you define. This becomes your routing key — the server echoes it back prefixed with EXCHANGE_SYMBOL_interval_ in all update messages.
{
"type": "subscribe",
"id": "my_ema_stream",
"exchange": "bybit",
"symbol": "BTCUSDT",
"interval": "1m",
"indicator": "ema",
"params": { "period": 20 }
}
| Field | Required | Description |
|---|---|---|
type |
✅ | Always "subscribe" |
id |
✅ | Your unique routing key for this stream |
exchange |
✅ | Exchange identifier, e.g. binance, bybit |
symbol |
✅ | Trading pair, e.g. BTCUSDT, ETHUSDT |
interval |
✅ | Candle interval: 1m 5m 15m 1h |
indicator |
✅ | Indicator name, e.g. rsi, macd, ema |
params |
— | Indicator-specific parameters, e.g. { "period": 20 } |
candleClose |
— | Set to true to only receive updates when a candle closes (no intra-candle ticks) |
Immediate confirmation from the server:
{
"type": "subscribed",
"id": "BYBIT_BTCUSDT_1m_my_ema_stream",
"subscription": "BYBIT:BTCUSDT:1m",
"indicator": "ema"
}
3. Receive updates
The server pushes an update message each time new data is computed. All streams sharing the same exchange + symbol + interval are bundled into a single payload:
{
"type": "update",
"subscription": "BYBIT:BTCUSDT:1m",
"data": {
"BYBIT_BTCUSDT_1m_my_ema_stream": {
"value": [76597.71],
"timestamp": [1777374240]
}
}
}
Multi-output indicators deliver all output fields inside the same key:
{
"BYBIT_BTCUSDT_1m_my_macd_stream": {
"valueMACD": [-18.63],
"valueMACDSignal": [-6.47],
"valueMACDHist": [-12.15],
"timestamp": [1777374480]
}
}
Bulk subscribe
For high-throughput setups, multiplex multiple indicators, symbols, and intervals into a single command:
{
"type": "subscribe_bulk",
"exchange": "bybit",
"symbols": ["BTCUSDT", "ETHUSDT"],
"intervals": ["1m", "5m"],
"indicators": [
{ "name": "rsi", "id": "bulk_rsi", "params": { "period": 14 } },
{ "name": "macd", "id": "bulk_macd", "params": { "fast": 12, "slow": 26, "signal": 9 } },
{ "name": "ema", "id": "bulk_ema", "params": { "period": 20 } }
]
}
The server responds in three stages:
// 1. Processing acknowledgement
{
"type": "subscribe_bulk_ack",
"status": "processing",
"totalConsumed": 12,
"message": "Bulk subscription accepted. Processing 12 indicator subscriptions."
}
// 2. All streams registered
{
"type": "subscribe_bulk_complete",
"subKeys": ["BYBIT:BTCUSDT:1m", "BYBIT:BTCUSDT:5m", "BYBIT:ETHUSDT:1m", "BYBIT:ETHUSDT:5m"],
"count": 12,
"message": "Successfully registered 12 indicator subscription(s) across 4 slot(s)."
}
// 3. Ongoing update pushes (same format as single subscribe)
{
"type": "update",
"subscription": "BYBIT:BTCUSDT:1m",
"data": {
"BYBIT_BTCUSDT_1m_bulk_ema": { "value": [76572.61], "timestamp": [1777374480] },
"BYBIT_BTCUSDT_1m_bulk_rsi": { "value": [32.78], "timestamp": [1777374480] }
}
}
Lifecycle commands
Unsubscribe a specific stream
{ "type": "unsubscribe", "id": "my_ema_stream" }
Unsubscribe all streams
{ "type": "unsubscribe_all" }
List active subscriptions
{ "type": "list", "unpack": true }
Complete example (JavaScript)
const ws = new WebSocket('wss://v2.taapi.io/streaming');
ws.onopen = () => {
// 1. Authenticate immediately
ws.send(JSON.stringify({
type: 'auth',
token: 'Bearer YOUR_API_KEY'
}));
};
ws.onmessage = ({ data }) => {
const msg = JSON.parse(data);
if (msg.type === 'auth_ok') {
// 2. Subscribe once authenticated
ws.send(JSON.stringify({
type: 'subscribe',
id: 'my_rsi',
exchange: 'bybit',
symbol: 'BTCUSDT',
interval: '1m',
indicator: 'rsi',
params: { period: 14 }
}));
}
if (msg.type === 'update') {
// 3. Route incoming data by your custom ID
const rsi = msg.data['BYBIT_BTCUSDT_1m_my_rsi'];
if (rsi) console.log('RSI:', rsi.value[0]);
}
if (msg.type === 'error') {
console.error('Server error:', msg.message);
}
};
ws.onerror = (err) => console.error('WebSocket error:', err);
ws.onclose = () => console.log('Connection closed');
Multiple subscriptions
Subscribe to as many streams as your plan allows on a single connection. Route incoming updates using the prefixed key pattern (EXCHANGE_SYMBOL_interval_yourId):
// After auth_ok — subscribe to several streams
const streams = [
{ id: 'rsi_btc', exchange: 'bybit', symbol: 'BTCUSDT', interval: '1m', indicator: 'rsi' },
{ id: 'ema_eth', exchange: 'bybit', symbol: 'ETHUSDT', interval: '5m', indicator: 'ema', params: { period: 20 } },
{ id: 'macd_sol', exchange: 'binance', symbol: 'SOLUSDT', interval: '15m', indicator: 'macd' },
];
streams.forEach(s => ws.send(JSON.stringify({ type: 'subscribe', ...s })));
// Route updates
ws.onmessage = ({ data }) => {
const { type, subscription, data: values } = JSON.parse(data);
if (type !== 'update') return;
const [exchange, symbol, interval] = subscription.split(':');
console.log(`[${exchange} ${symbol} ${interval}]`, values);
};
Reconnection
WebSocket connections can drop due to network interruptions. Implement exponential backoff:
function connect() {
const ws = new WebSocket('wss://v2.taapi.io/streaming');
let delay = 1000;
ws.onopen = () => {
delay = 1000; // reset on success
authenticate(ws);
};
ws.onclose = () => {
console.log(`Reconnecting in ${delay}ms…`);
setTimeout(() => {
delay = Math.min(delay * 2, 30000);
connect();
}, delay);
};
return ws;
}
connect();
Health check
A simple HTTP endpoint confirms the streaming service is up:
GET https://v2.taapi.io/streaming/health
Returns 200 OK when the service is running.
Error messages
| Message | Cause |
|---|---|
Unauthorized |
Auth message missing or invalid API key |
Already subscribed |
Duplicate subscribe for the same stream id |
Unknown indicator |
Indicator name not recognised |
Exchange not supported |
Exchange identifier is invalid |
Rate limit exceeded |
Too many subscriptions for your plan |
Was this page helpful? Send us feedback or open a support ticket.