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

Discovery

Symbols, expiries, and the glossary.

Start here when you do not already have the canonical ticker, the expiry, or the meaning of a label.

These routes are POST with a flat JSON body. list_symbols and list_expiries are paged at 400 rows and cached for 3600 seconds. list_symbols is the allow-list. list_expiries needs one symbol and returns dates, not net gamma. get_glossary is the dictionary of labels; it is also on the glossary page. Omit terms for the full list and meta.request.terms is null. An empty array is the full list too, and meta.request.terms echoes [].

1 / 3

Symbols

POST/api/v1/discovery/symbolsMCP list_symbols

Lists the visible instrument universe. Optional symbols filters the list; unknown symbols are omitted. The MCP tool is list_symbols. The arguments are this same JSON body. The bearer token stays on the HTTP header.

Parameters · Symbols

NameTypeRequiredValues
symbolsarray of stringsNoUp to 300 tickers. Unknown names are left out. Order in the response is 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 3600 seconds (rc_ttl).

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

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

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": [
      {
        "symbol": "/ES1",
        "type": "FUTURES",
        "is_synthetic": true,
        "mapped_from": "SPX"
      },
      {
        "symbol": "AAPL",
        "type": "STOCK",
        "is_synthetic": false,
        "mapped_from": null
      },
      {
        "symbol": "SPX",
        "type": "INDEX",
        "is_synthetic": false,
        "mapped_from": null
      }
    ]
  },
  "meta": {
    "request": {
      "symbols": [
        "/ES1",
        "AAPL",
        "SPX"
      ]
    },
    "count": 3,
    "total": 3,
    "page": 1,
    "page_count": 1,
    "next_cursor": null,
    "generation": "04642afa2dbe",
    "as_of": {},
    "built_at": "2026-10-23T01:08:02-04:00",
    "omitted": [],
    "docs": {
      "reference": "https://tanukitrade.com/docs/api/discovery#list_symbols",
      "glossary": "https://tanukitrade.com/docs/api/glossary"
    }
  }
}

Response fields · Symbols

FieldTypeMeaning
symbolstringCanonical ticker. Copy it from list_symbols. Letter case folds to uppercase.
typestringSTOCK, ETF, INDEX, FUTURES, or CFD_CRYPTO.
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.

Errors on this route · Symbols

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).

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

2 / 3

Expiries

POST/api/v1/discovery/expiriesMCP list_expiries

Lists one symbol’s expiries. Each row is the date, DTE, aliases, and whether that date is the monthly. net_gex is not returned. There is no flags field. The MCP tool is list_expiries. The arguments are this same JSON body. The bearer token stays on the HTTP header.

Parameters · Expiries

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 3600 seconds (rc_ttl).

curl
curl --compressed \
  --request POST \
  --url "${TANUKI_BASE_URL}/api/v1/discovery/expiries" \
  --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 (52) and meta.total is the filtered total (52). built_at is the builder health clock of this capture.

200 application/json
{
  "ok": true,
  "data": {
    "items": [
      {
        "expiration_date": "2026-10-23",
        "dte": 0,
        "aliases": [
          "0",
          "w1"
        ],
        "is_monthly": false
      },
      {
        "expiration_date": "2026-10-26",
        "dte": 3,
        "aliases": [
          "1"
        ],
        "is_monthly": false
      },
      {
        "expiration_date": "2026-10-27",
        "dte": 4,
        "aliases": [],
        "is_monthly": false
      },
      "..."
    ]
  },
  "meta": {
    "request": {
      "symbol": "SPX"
    },
    "count": 52,
    "total": 52,
    "page": 1,
    "page_count": 1,
    "next_cursor": null,
    "generation": "934247a0818e",
    "as_of": {
      "chain": "2026-10-21T16:01:54.082-04:00",
      "secondary": "2026-10-21T15:59:05-04:00"
    },
    "built_at": "2026-10-23T01:08:02-04:00",
    "omitted": [],
    "docs": {
      "reference": "https://tanukitrade.com/docs/api/discovery#list_expiries",
      "glossary": "https://tanukitrade.com/docs/api/glossary"
    }
  }
}

Response fields · Expiries

FieldTypeMeaning
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.

Errors on this route · Expiries

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.

3 / 3

Glossary

POST/api/v1/discovery/glossaryMCP get_glossary

The dictionary of labels and concepts the other routes emit. Optional terms filters to those ids. Omit it for the full list; meta.request.terms is null. An empty array is the full list too, and meta.request.terms echoes []. The body is static. The MCP tool is get_glossary. The arguments are this same JSON body. The bearer token stays on the HTTP header.

Parameters · Glossary

NameTypeRequiredValues
termsarray of stringsNoOptional JSON array of glossary ids, at most 64. Omit it for the full glossary; meta.request.terms is null. An empty array is the full list too, and meta.request.terms echoes []. Ids are case-sensitive. An unknown id is 422 and error.details[].available lists every id.

This response is the whole document. It is not paged and it is not stored in the response cache.

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

  • {}
  • {"terms":["P1","HVL","cT"]}
curl
curl --compressed \
  --request POST \
  --url "${TANUKI_BASE_URL}/api/v1/discovery/glossary" \
  --header "Authorization: Bearer 12345.YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{"terms":["P1","HVL","cT"]}'

The terms named in the request, in that order. Omit terms for the full glossary.

200 application/json
{
  "ok": true,
  "data": {
    "items": [
      {
        "id": "P1",
        "name": "P1",
        "family": "Labels",
        "summary": "Put support: the primary put wall, the strongest negative net-GEX strike.",
        "definition": "P1 is the largest put-side gamma wall. Dealers hedging a put-dominated strike often lean against downside through that strike, so it is read as structural support. It is the first label in the primary order P1, pT, HVL, cT, C1.",
        "how_to_read": "On an unbroken profile P1 is at or below pT. Spot at or below P1 is the NEG_SQUEEZE state. weight, when present, is the signed normalized size and is negative on a put wall.",
        "related": [
          "pT",
          "P2",
          "NEG_SQUEEZE",
          "norm"
        ],
        "learn_url": "https://tanukitrade.com/docs/learn/walls"
      },
      {
        "id": "HVL",
        "name": "HVL",
        "family": "Labels",
        "summary": "High Volatility Level: the structural pivot inside the transition zone.",
        "definition": "HVL marks the steepest change in the net-GEX profile, inside the band pT ≤ HVL ≤ cT. It is the reference Tanuki uses instead of a single gamma-flip price. The knowledge base also titles this level Highest Volatility Level; the Learn page and this glossary use High Volatility Level for the same strike. Below HVL, dealer hedging is read as tending to amplify moves. Above HVL, it is read as tending to dampen them. That is a tendency, not a forecast.",
        "how_to_read": "Require pT ≤ HVL ≤ cT before you trust the zone. Spot at or above HVL and still below cT is POS_TRANSITION. Spot below HVL and still above pT is NEG_TRANSITION.",
        "related": [
          "pT",
          "cT",
          "transition-zone",
          "POS_TRANSITION",
          "NEG_TRANSITION"
        ],
        "learn_url": "https://tanukitrade.com/docs/learn/hvl"
      },
      {
        "id": "cT",
        "name": "cT",
        "family": "Labels",
        "summary": "Call transition (cTrans): the upper boundary of the transition zone.",
        "definition": "cT is the upper edge of the band that contains HVL. Above cT the net-GEX structure is read as positive-gamma territory. The label is cT; the same level is cTrans in the classification text.",
        "how_to_read": "An unbroken profile keeps cT between HVL and C1, inclusive. Spot above cT and still below C1 is POS. Spot at or above C1 (and at or above cT) is POS_SQUEEZE.",
        "related": [
          "HVL",
          "C1",
          "transition-zone",
          "POS"
        ],
        "learn_url": "https://tanukitrade.com/docs/learn/walls"
      }
    ]
  },
  "meta": {
    "request": {
      "terms": [
        "P1",
        "HVL",
        "cT"
      ]
    },
    "count": 3,
    "docs": {
      "reference": "https://tanukitrade.com/docs/api/glossary",
      "glossary": "https://tanukitrade.com/docs/api/glossary"
    }
  }
}

Response fields · Glossary

FieldTypeMeaning
idstringStable term id. Use it in terms and as the pro-docs anchor.
namestringDisplay name. For a label it is the label itself.
familystringGroup: Labels, Profile, Metrics, Expiry, Clocks, Symbols, or Ecosystem.
summarystringOne sentence.
definitionstringWhat the term means in the WebApp and in this API.
how_to_readstringSign, order, zone, or clock. How to use the value.
relatedarray of stringsOther glossary ids.
learn_urlstringhttps://tanukitrade.com/docs/… page for this term.

Errors on this route · Glossary

HTTPCodeWhen
422VALIDATION_ERRORterms is not an array, an item is too long, there are more than 64 ids, or an id is unknown.
413PAYLOAD_TOO_LARGEThe JSON body is larger than 4 KiB.
429RATE_LIMIT_EXCEEDEDThe per-minute user limit. Wait Retry-After seconds.

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