Guides
Python client
A small httpx client: gzip, a bearer header, cursor paging, and a wait on 429 and 503. Install with pip install httpx.
import os import random import time import httpx RETRYABLE = {429, 503} class Tanuki: def __init__(self) -> None: self.base = os.environ["TANUKI_BASE_URL"].rstrip("/") self.client = httpx.Client( timeout=httpx.Timeout(30.0, connect=3.0), headers={ "Authorization": f"Bearer {os.environ['TANUKI_TOKEN']}", "Accept": "application/json", "Accept-Encoding": "gzip", "Content-Type": "application/json", }, ) def post(self, path: str, body: dict | None = None) -> dict: url = self.base + path payload = body or {} for attempt in range(4): response = self.client.post(url, json=payload) if response.status_code in RETRYABLE and attempt < 3: delay = float(response.headers.get("Retry-After", "1")) time.sleep(delay + random.random() * 0.25) continue response.raise_for_status() data = response.json() if data.get("ok") is not True: code = data.get("error", {}).get("code", "not ok") raise RuntimeError(code) return data raise RuntimeError("retry exhausted") def pages(self, path: str, body: dict | None = None): payload = dict(body or {}) payload.pop("cursor", None) while True: page = self.post(path, payload) yield page cursor = page["meta"].get("next_cursor") if not cursor: return payload["cursor"] = cursor api = Tanuki() expiries = api.post("/api/v1/discovery/expiries", {"symbol": "SPX"}) print(expiries["data"]["items"][0]["expiration_date"])
401, 403, and 422 fall through raise_for_status or the ok check. Retrying a bad token or a bad expiry only spends the auth counter. 429 and 503 wait for Retry-After, then try the same read again. The sleep adds a little jitter so a crowd does not wake on the same millisecond.
Paging
pages sends the same body with cursor set to meta.next_cursor until that field is null. The benchmark list is the one that paged in the captured data.
rows = [] for page in api.pages("/api/v1/fundamentals/benchmark-correlation"): for item in page["data"]["items"]: rows.append(item["symbol"]) print(len(rows), page["meta"]["total"])
Do not put the token in the JSON body. The example token in the shell exports on the overview page is a placeholder.
TanukiTrade API and MCP. Derived options analytics for your code and for agents. Not investment advice. tanukitrade.com