🔍

The streaming service pushes indicator updates over a WebSocket connection. Instead of polling the REST API, you subscribe to indicators and receive values as they are computed.

WebSocket URL
wss://v2.taapi.io/streaming

Connection flow

  1. Open a WebSocket connection to wss://v2.taapi.io/streaming.
  2. Send an auth message with your API key. You must authenticate before subscribing.
  3. Send subscribe messages for the indicators you want.
  4. Receive update messages as indicator values are computed.
  5. 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.

Send
{ "type": "auth", "token": "Bearer YOUR_API_KEY" }
Receive — success
{ "type": "auth_ok" }
Receive — failure
{ "type": "auth_error", "error": "Invalid or inactive token" }

Connections that fail authentication are closed by the server.

Subscribe

After authenticating, send a subscribe message for each indicator you want.

Subscribe — single indicator
{
  "type":       "subscribe",
  "id":         "my-rsi-id",
  "exchange":   "binance",
  "symbol":     "BTCUSDT",
  "interval":   "1m",
  "indicator":  "rsi",
  "params":     { "period": 14 }
}
FieldRequiredDescription
typeYesMust be "subscribe".
idYesSubscription identifier, e.g. my-rsi-id. It is required and will be included in the update events.
exchangeYesExchange identifier, e.g. binance.
symbolYesTrading pair, e.g. BTCUSDT.
intervalYesCandle interval: 1m, 5m, 15m, 1h, 4h, 1d, 1w.
indicatorYesIndicator name, e.g. rsi, ema, macd.
paramsNoIndicator-specific parameters, e.g. { "period": 14 }.

Receiving updates

After subscribing, the server sends update messages as values are computed.

Receive — update
{
  "type":         "update",
  "subscription": "binance:btcusdt:1m",
  "data": {
    "binance_btcusdt_1m_my-rsi-id": {
      "value":     [45.2],
      "timestamp": [1782389580]
    }
  }
}

The subscription key is lowercase and uses the format exchange:symbol:interval. The data object is keyed by a compound string combining exchange, symbol, interval, and the id you provided when subscribing.

Subscribe bulk

Subscribe to many indicators, symbols, and timeframes in one message using a subscribe_bulk message.

subscribe_bulk
{
  "type":       "subscribe_bulk",
  "exchange":   "binance",
  "symbols":    ["BTCUSDT", "ETHUSDT"],
  "intervals":  ["1m", "5m"],
  "indicators": [
    { "id": "my-rsi", "name": "rsi", "params": { "period": 14 } },
    { "id": "my-ema", "name": "ema", "params": { "period": 9  } }
  ]
}

The server will subscribe to every combination of symbol × interval × indicator. Each indicator entry requires its own id and uses name (not indicator) for the indicator name.

Unsubscribe

To remove a single subscription, send an unsubscribe message with the generated compound ID that was returned when you subscribed. This ID is formed by the server as exchange_symbol_interval_yourId (all lowercase), for example:

Unsubscribe — single
{
  "type": "unsubscribe",
  "id":   "binance_btcusdt_1m_my-rsi-id"
}
Receive — acknowledgement
{
  "type": "unsubscribed",
  "id":   "binance_btcusdt_1m_my-rsi-id"
}

You can retrieve the compound IDs for all your active subscriptions at any time by sending a list message (see below).

To remove all active subscriptions at once, send an unsubscribe_all message. No acknowledgement is sent for this variant — confirm with a subsequent list.

Unsubscribe — all
{ "type": "unsubscribe_all" }

List subscriptions

Send
{ "type": "list" }
Receive
{
  "type": "subscriptions",
  "data": {
    "binance:btcusdt:1m": [
      { "id": "binance_btcusdt_1m_my-rsi-id", "indicator": "rsi", ... }
    ]
  }
}

Pass "unpack": true to receive a flat array instead of the grouped object — useful when you want to iterate subscriptions directly.

Send — flat array
{ "type": "list", "unpack": true }
Receive — flat array
{
  "type": "subscriptions",
  "data": [
    { "id": "binance_btcusdt_1m_my-rsi-id", "indicator": "rsi",
      "exchange": "binance", "symbol": "BTCUSDT", "timeframe": "1m", ... },
    { "id": "binance_ethusdt_5m_my-ema-id", "indicator": "ema",
      "exchange": "binance", "symbol": "ETHUSDT", "timeframe": "5m", ... }
  ]
}

Throttle limits

TODO(human): Document per-plan subscription limits and per-connection throttle rules for the streaming service.

Error messages

The server sends error messages for invalid subscribe/unsubscribe requests without closing the connection:

Error message format
{
  "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:

Node.js — reconnect example
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', id: 'my-rsi-id',
        exchange: 'binance', symbol: 'BTCUSDT',
        interval: '1m', indicator: 'rsi',
        params: { period: 14 }
      }));
    }
    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

HTTP health endpoint
GET https://v2.taapi.io/streaming/health