๐Ÿ”

The bulk endpoint lets you send one request and get back indicator results for many symbols and timeframes at once. Each item in the constructs array defines one asset (exchange + symbol + timeframe) and the indicators you want for it.

What is a construct?

A construct is one exchange + symbol + timeframe, plus the list of indicators you want computed for it. Put several constructs in one request to pull multiple symbols and/or timeframes in a single call.

Maximum limits: 20 constructs per request ยท 20 indicators per construct. No two constructs may target the same exchange + symbol + timeframe combination.

Request body

FieldTypeRequiredDefaultDescription
constructs array Yes โ€” 1โ€“20 construct objects (see below).
verbose boolean No false When true, each indicator result is wrapped in a metadata envelope including indicator, params, result, and errors.

Construct object

FieldTypeRequiredDescription
idstringYesUnique key for this construct in the response. Alphanumeric + underscores only. Becomes the top-level key in the response object.
exchangestringYesExchange identifier, e.g. binance.
symbolstringYesTrading pair, e.g. BTCUSDT.
timeframestringYesCandle interval: 1m, 5m, 15m, 1h, 4h, 1d, 1w.
indicatorsarrayYes1โ€“20 indicator objects (see below).

Indicator object (within a construct)

FieldTypeRequiredDescription
idstringYesUnique key for this indicator within the construct. Becomes a key in the construct's response object.
indicatorstringYesIndicator name matching the GET /indicator/{name} path, e.g. rsi, ema, macd.
resultsintegerNoNumber of historical values (default: 1). See Historical Values.
backtrackintegerNoCandles to skip from most recent (default: 0).
[indicator params]variesNoAny indicator-specific parameters, e.g. "period": 14. Same params as the GET endpoint for that indicator.

The same indicator can appear multiple times in one construct with different parameters โ€” just give each a unique id:

Two EMAs with different periods
{ "id": "ema_fast", "indicator": "ema", "period": 9  }
{ "id": "ema_slow", "indicator": "ema", "period": 50 }

Example โ€” one symbol, multiple indicators

curl -X POST https://v2.taapi.io/bulk \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "constructs": [
      {
        "id": "btc_1h",
        "exchange": "binance",
        "symbol": "BTCUSDT",
        "timeframe": "1h",
        "indicators": [
          { "id": "rsi_14",  "indicator": "rsi", "period": 14 },
          { "id": "ema_fast","indicator": "ema", "period": 9  },
          { "id": "ema_slow","indicator": "ema", "period": 50 }
        ]
      }
    ]
  }'
const res = await fetch('https://v2.taapi.io/bulk', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    constructs: [{
      id: 'btc_1h',
      exchange: 'binance',
      symbol: 'BTCUSDT',
      timeframe: '1h',
      indicators: [
        { id: 'rsi_14',   indicator: 'rsi', period: 14 },
        { id: 'ema_fast', indicator: 'ema', period: 9  },
        { id: 'ema_slow', indicator: 'ema', period: 50 },
      ],
    }],
  }),
});
const data = await res.json();
import requests, json

payload = {
    "constructs": [{
        "id": "btc_1h",
        "exchange": "binance",
        "symbol": "BTCUSDT",
        "timeframe": "1h",
        "indicators": [
            {"id": "rsi_14",   "indicator": "rsi", "period": 14},
            {"id": "ema_fast", "indicator": "ema", "period": 9},
            {"id": "ema_slow", "indicator": "ema", "period": 50},
        ],
    }]
}
resp = requests.post(
    'https://v2.taapi.io/bulk',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json',
    },
    data=json.dumps(payload)
)
print(resp.json())
Response
{
  "btc_1h": {
    "rsi_14":   { "value": [62.34],    "timestamp": [1708300800] },
    "ema_fast": { "value": [49200.5],  "timestamp": [1708300800] },
    "ema_slow": { "value": [48100.75], "timestamp": [1708300800] }
  }
}

Example โ€” multiple symbols and timeframes

This is the most common use case for bulk: pull indicators for several different assets in one call. Add more constructs, each with its own exchange, symbol, and timeframe.

Two symbols, two timeframes โ€” one request
{
  "constructs": [
    {
      "id": "btc_1h",
      "exchange": "binance",
      "symbol": "BTCUSDT",
      "timeframe": "1h",
      "indicators": [
        { "id": "rsi", "indicator": "rsi" }
      ]
    },
    {
      "id": "eth_15m",
      "exchange": "binance",
      "symbol": "ETHUSDT",
      "timeframe": "15m",
      "indicators": [
        { "id": "rsi", "indicator": "rsi" }
      ]
    },
    {
      "id": "btc_4h",
      "exchange": "bybit",
      "symbol": "BTCUSDT",
      "timeframe": "4h",
      "indicators": [
        { "id": "macd", "indicator": "macd" }
      ]
    }
  ]
}
Response โ€” keyed by construct id
{
  "btc_1h": {
    "rsi": { "value": [62.34], "timestamp": [1708300800] }
  },
  "eth_15m": {
    "rsi": { "value": [55.10], "timestamp": [1708301700] }
  },
  "btc_4h": {
    "macd": {
      "valueMACD":     [-120.5],
      "valueMACDSignal": [-98.2],
      "valueMACDHist":   [-22.3],
      "timestamp":     [1708300800]
    }
  }
}

Verbose mode

Set "verbose": true to include metadata with each indicator result:

Verbose response
{
  "btc_1h": {
    "_asset": { "exchange": "binance", "symbol": "BTCUSDT", "timeframe": "1h" },
    "rsi_14": {
      "indicator": "rsi",
      "params":    { "period": 14 },
      "result":    { "value": [62.34], "timestamp": [1708300800] },
      "errors":    []
    }
  }
}

Error handling in bulk

If candle data cannot be fetched for a construct (e.g. invalid symbol), that construct returns _error and its indicators return null. Other constructs in the same request are not affected.

Partial failure
{
  "btc_1h": {
    "_error": "Failed to fetch candles: 404 Not Found โ€” check exchange, symbol and timeframe",
    "rsi_14": null
  }
}

Errors

Response
{ "btc_1h": { "rsi_14": { "value": [62.34], "timestamp": [1708300800] } } }
Response
{ "error": "constructs is required and must be a non-empty array" }
Response
{ "error": "Invalid or missing API key." }
Response
{ "error": "Rate limit exceeded. Your plan allows 30 requests per 15 seconds." }