← tanukitrade.com Open WebApp (opens in a new tab) Start 7-day free trial

Chain

Open interest and volume.

Call and put totals per symbol, then one symbol’s counts split by expiry.

chain/activity takes an optional symbols list; without it every symbol is returned, by total volume (call plus put) descending. chain/expiry-distribution requires one symbol. Counts are not scaled for a synthetic. A missing count is 0; a count that is not finite or does not fit a signed 64-bit integer is null. A call/put ratio is at most 4 decimals, and null when the put side is 0 or a count it uses is null. oi_share_pct and volume_share_pct are rounded to 4 decimal places, and null when the symbol total is 0 or a count it uses is null. volume_is_prior_day is true on a weekday before 09:30 ET, except SPX, XSP, ES, and MES.

On the distribution, standalone is that expiry. cumulative is every expiry through that date. The last cumulative block matches chain activity. Share percents use the symbol total.

1 / 2

Chain activity

POST/api/v1/chain/activityMCP list_chain_activity

Lists call and put open interest and volume. Optional symbols filters the list; unknown symbols are omitted. Order is total volume descending, then symbol ascending. The MCP tool is list_chain_activity. The arguments are this same JSON body. The bearer token stays on the HTTP header.

Parameters · Chain activity

NameTypeRequiredValues
symbolsarray of stringsNoUp to 300 tickers. Unknown names are left out. Omit it for every symbol. Order is total volume descending, then symbol ascending.
cursorstringNoPrevious meta.next_cursor. Omit it on the first page.

Page size is fixed at 400 rows. The caller does not set it. The response cache refreshes in 180 seconds (rc_ttl).

Valid bodies, from the minimal to the one the sample answers:

  • {}
  • {"symbols":["SPX"]}
curl
curl --compressed \
  --request POST \
  --url "${TANUKI_BASE_URL}/api/v1/chain/activity" \
  --header "Authorization: Bearer 12345.YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{"symbols":["SPX"]}'

Live builder output for the request in this file. The row list was short enough to keep. built_at is the builder health clock of this capture.

200 application/json
{
  "ok": true,
  "data": {
    "items": [
      {
        "call_oi": 9129300,
        "put_oi": 13341203,
        "call_volume": 589751,
        "put_volume": 893118,
        "call_put_oi_ratio": 0.6843,
        "call_put_volume_ratio": 0.6603,
        "symbol": "SPX",
        "is_synthetic": false,
        "mapped_from": null,
        "volume_is_prior_day": false
      }
    ]
  },
  "meta": {
    "request": {
      "symbols": [
        "SPX"
      ]
    },
    "count": 1,
    "total": 1,
    "page": 1,
    "page_count": 1,
    "next_cursor": null,
    "generation": "dd5e362e22d5",
    "as_of": {},
    "built_at": "2026-10-23T01:08:02-04:00",
    "omitted": [],
    "docs": {
      "reference": "https://tanukitrade.com/docs/api/chain#list_chain_activity",
      "glossary": "https://tanukitrade.com/docs/api/glossary"
    }
  }
}

Response fields · Chain activity

FieldTypeMeaning
symbolstringCanonical ticker. Copy it from list_symbols. Letter case folds to uppercase.
is_syntheticbooleanTrue when the ticker is mapped from another symbol. False is a listed underlying.
mapped_fromstring or nullThe symbol a synthetic is mapped from. Null on a listed underlying. A micro names the optionable base, not its parent future.
call_oiinteger or nullCall open interest. 0 when none is stored; a measured zero stays 0. Null when the stored value is not a finite number or is an integer outside signed 64-bit.
put_oiinteger or nullPut open interest. 0 when none is stored; a measured zero stays 0. Null when the stored value is not a finite number or is an integer outside signed 64-bit.
call_volumeinteger or nullCall volume. 0 when none is stored; a measured zero stays 0. Null when the stored value is not a finite number or is an integer outside signed 64-bit.
put_volumeinteger or nullPut volume. 0 when none is stored; a measured zero stays 0. Null when the stored value is not a finite number or is an integer outside signed 64-bit.
call_put_oi_rationumber or nullcall_oi / put_oi, rounded to 4 decimal places. Null when put open interest is 0 or either open-interest count is null.
call_put_volume_rationumber or nullcall_volume / put_volume, rounded to 4 decimal places. Null when put volume is 0 or either volume count is null.
volume_is_prior_daybooleanTrue on a weekday before 09:30 ET, except SPX, XSP, ES, and MES.

Errors on this route · Chain activity

HTTPCodeWhen
422VALIDATION_ERRORUnknown field, nested value, repeated key, bad JSON, a bad alias, or a cursor that does not match this request.
413PAYLOAD_TOO_LARGEThe JSON body is larger than 4 KiB.
503DATA_WARMINGThe datapoint is not built yet. Wait Retry-After seconds (1).
422RESULT_TOO_LARGEThe uncompressed JSON would exceed 512 KiB. Narrow the filter.

Auth, rate limit, and the other shared failures are on Errors.

2 / 2

Expiry distribution

POST/api/v1/chain/expiry-distributionMCP list_chain_expiry_distribution

Lists per-expiry open interest and volume for one symbol. standalone is that expiry. cumulative is every expiry through that date. The MCP tool is list_chain_expiry_distribution. The arguments are this same JSON body. The bearer token stays on the HTTP header.

Parameters · Expiry distribution

NameTypeRequiredValues
symbolstringYesOne ticker. Letter case folds to uppercase.
cursorstringNoPrevious meta.next_cursor. Omit it on the first page.

Page size is fixed at 400 rows. The caller does not set it. The response cache refreshes in 180 seconds (rc_ttl).

curl
curl --compressed \
  --request POST \
  --url "${TANUKI_BASE_URL}/api/v1/chain/expiry-distribution" \
  --header "Authorization: Bearer 12345.YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{"symbol":"SPX"}'

Live builder output for the request in this file. The first 3 rows of the page are shown; "..." is not a row. meta.count is the untrimmed page length (54) and meta.total is the filtered total (54). built_at is the builder health clock of this capture.

200 application/json
{
  "ok": true,
  "data": {
    "items": [
      {
        "symbol": "SPX",
        "is_synthetic": false,
        "mapped_from": null,
        "expiration_date": "2026-10-23",
        "dte": 0,
        "aliases": [
          "0",
          "w1"
        ],
        "is_monthly": false,
        "volume_is_prior_day": false,
        "standalone": {
          "call_oi": 141462,
          "put_oi": 507282,
          "call_volume": 72062,
          "put_volume": 120484,
          "call_put_oi_ratio": 0.2789,
          "call_put_volume_ratio": 0.5981,
          "oi_share_pct": 2.8871,
          "volume_share_pct": 12.9847
        },
        "cumulative": {
          "call_oi": 141462,
          "put_oi": 507282,
          "call_volume": 72062,
          "put_volume": 120484,
          "call_put_oi_ratio": 0.2789,
          "call_put_volume_ratio": 0.5981,
          "oi_share_pct": 2.8871,
          "volume_share_pct": 12.9847
        }
      },
      {
        "symbol": "SPX",
        "is_synthetic": false,
        "mapped_from": null,
        "expiration_date": "2026-10-26",
        "dte": 3,
        "aliases": [
          "1"
        ],
        "is_monthly": false,
        "volume_is_prior_day": false,
        "standalone": {
          "call_oi": 37293,
          "put_oi": 83392,
          "call_volume": 21867,
          "put_volume": 34606,
          "call_put_oi_ratio": 0.4472,
          "call_put_volume_ratio": 0.6319,
          "oi_share_pct": 0.5371,
          "volume_share_pct": 3.8084
        },
        "cumulative": {
          "call_oi": 178755,
          "put_oi": 590674,
          "call_volume": 93929,
          "put_volume": 155090,
          "call_put_oi_ratio": 0.3026,
          "call_put_volume_ratio": 0.6056,
          "oi_share_pct": 3.4242,
          "volume_share_pct": 16.7931
        }
      },
      {
        "symbol": "SPX",
        "is_synthetic": false,
        "mapped_from": null,
        "expiration_date": "2026-10-27",
        "dte": 4,
        "aliases": [],
        "is_monthly": false,
        "volume_is_prior_day": false,
        "standalone": {
          "call_oi": 60799,
          "put_oi": 74703,
          "call_volume": 53493,
          "put_volume": 19956,
          "call_put_oi_ratio": 0.8139,
          "call_put_volume_ratio": 2.6805,
          "oi_share_pct": 0.603,
          "volume_share_pct": 4.9532
        },
        "cumulative": {
          "call_oi": 239554,
          "put_oi": 665377,
          "call_volume": 147422,
          "put_volume": 175046,
          "call_put_oi_ratio": 0.36,
          "call_put_volume_ratio": 0.8422,
          "oi_share_pct": 4.0272,
          "volume_share_pct": 21.7462
        }
      },
      "..."
    ]
  },
  "meta": {
    "request": {
      "symbol": "SPX"
    },
    "count": 54,
    "total": 54,
    "page": 1,
    "page_count": 1,
    "next_cursor": null,
    "generation": "dd5e362e22d5",
    "as_of": {},
    "built_at": "2026-10-23T01:08:02-04:00",
    "omitted": [],
    "docs": {
      "reference": "https://tanukitrade.com/docs/api/chain#list_chain_expiry_distribution",
      "glossary": "https://tanukitrade.com/docs/api/glossary"
    }
  }
}

Response fields · Expiry distribution

FieldTypeMeaning
symbolstringCanonical ticker. Copy it from list_symbols. Letter case folds to uppercase.
is_syntheticbooleanTrue when the ticker is mapped from another symbol. False is a listed underlying.
mapped_fromstring or nullThe symbol a synthetic is mapped from. Null on a listed underlying. A micro names the optionable base, not its parent future.
expiration_datedateCalendar expiry, YYYY-MM-DD, ET.
dteintegerDays to that expiry, as stored for the row.
aliasesarray of strings0, 1, w1–w4, M1–M3, ALL. Weekly aliases use a lowercase w. Monthly aliases and ALL stay uppercase.
is_monthlybooleanTrue on the monthly expiry date. Same rule as discovery expiries.
volume_is_prior_daybooleanTrue on a weekday before 09:30 ET, when volume is still the previous session's. SPX, XSP, ES, and MES are always false.
standaloneobjectThat expiry’s counts, ratios, oi_share_pct, and volume_share_pct.
cumulativeobjectEvery expiry through this date. The last block matches chain activity.
oi_share_pctnumber or nullInside standalone and cumulative. Share of the symbol's total open interest on this expiry, in percent, rounded to 4 decimal places. volume_share_pct is the same for volume. Null when the symbol total is 0 or a count in that share is null.

Errors on this route · Expiry distribution

HTTPCodeWhen
422VALIDATION_ERRORUnknown field, nested value, repeated key, bad JSON, a bad alias, or a cursor that does not match this request.
413PAYLOAD_TOO_LARGEThe JSON body is larger than 4 KiB.
503DATA_WARMINGThe datapoint is not built yet. Wait Retry-After seconds (1).
422RESULT_TOO_LARGEThe uncompressed JSON would exceed 512 KiB. Narrow the filter.
422UNKNOWN_SYMBOLRequired symbol is not in the universe.

Auth, rate limit, and the other shared failures are on Errors.

TanukiTrade API and MCP. Derived options analytics for your code and for agents. Not investment advice. tanukitrade.com