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

API

Quickstart

Five steps. A new token can make a successful call in about five minutes.

  1. Copy the token from API Access.
  2. Send one curl to check the token.
  3. Send one Python request for a few symbols.
  4. Send the same request in JavaScript.
  5. Connect one MCP client.

1. Copy the token

Sign in and open API Access. Copy the bearer token. REST and MCP use that same token.

A real token is 8 lowercase letters or digits, a dot, then 16 to 128 letters or digits. 12345.YOUR_API_KEY is a placeholder. It is shorter than that on purpose, so it is not a live token.

shell
export TANUKI_TOKEN="12345.YOUR_API_KEY"

Replace the placeholder before you export it. Do not commit the real token, and do not put it in a URL.

2. One curl call

This checks the token. POST /api/v1/account/status takes an empty JSON object. It is not counted as market usage. The base URL is https://api.tanukitrade.com.

curl
curl --compressed \
  --request POST \
  --url "https://api.tanukitrade.com/api/v1/account/status" \
  --header "Authorization: Bearer ${TANUKI_TOKEN}" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{}'

curl --compressed sends Accept-Encoding: gzip and inflates the body. requests, httpx, and fetch send Accept-Encoding: gzip by default. Do not turn that off.

A 200 looks like this. The group list is cut. ... is not a group. Times are America/New_York, with a numeric offset.

200 application/json
{
  "ok": true,
  "data": {
    "service": "operational",
    "data_as_of": "2026-10-22T16:00:00.000-04:00",
    "client_id": "example",
    "enabled_groups": [
      "chain",
      "discovery",
      "..."
    ],
    "rate_limit": {
      "per_minute": 120
    },
    "server_time": "2026-10-22T16:00:00.000-04:00"
  },
  "meta": {
    "request_id": "req_example"
  }
}

ok is true when the token worked. A 401 means the token was cut off, quoted, or still the placeholder. More status fields are on Account.

3. One Python call

Install requests with pip install requests. This is one market read, POST /api/v1/discovery/symbols, with a short symbol list. httpx sends gzip the same way. Paging and a 503 wait are on the Python client page.

python
import os
import time

import requests

response = requests.post(
    "https://api.tanukitrade.com/api/v1/discovery/symbols",
    headers={"Authorization": "Bearer " + os.environ["TANUKI_TOKEN"]},
    json={"symbols": ["SPX", "AAPL", "/ES1"]},
    timeout=30,
)
if response.status_code == 429: time.sleep(int(response.headers.get("Retry-After", "1")))
print(response.status_code, response.json()["ok"])

On 429, that line waits Retry-After seconds. Run the request again. The header is seconds, not a timestamp. See Rate limits and headers.

One row from the captured response is below. meta.count is the untrimmed page. ... is not a row. built_at is America/New_York.

200 application/json
{
  "ok": true,
  "data": {
    "items": [
      {
        "symbol": "SPX",
        "type": "INDEX",
        "is_synthetic": false,
        "mapped_from": null
      },
      "..."
    ]
  },
  "meta": {
    "count": 3,
    "total": 3,
    "built_at": "2026-10-23T01:08:02-04:00"
  }
}

4. One JavaScript call

Node 18 or newer has fetch. Save this as first-call.mjs. From the same shell, run node first-call.mjs. fetch sends gzip by default, in Node and in the browser.

javascript
const response = await fetch("https://api.tanukitrade.com/api/v1/discovery/symbols", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.TANUKI_TOKEN,
    "Content-Type": "application/json",
    Accept: "application/json",
  },
  body: JSON.stringify({"symbols": ["SPX", "AAPL", "/ES1"]}),
});
if (response.status === 429) await new Promise((resolve) => setTimeout(resolve, Number(response.headers.get("Retry-After") || 1) * 1000));
const payload = await response.json();
console.log(response.status, payload.ok);

On 429, that line waits Retry-After seconds, then prints this attempt. Run the file again after the wait. The response shape is the Python sample above.

5. One MCP client

The MCP host is https://mcp.tanukitrade.com/mcp/v1. Do not append that path to the REST base URL. Every other client, and the protocol itself, is on Connect. The blocks below use the same placeholder. They do not contain a live token.

Claude Code

shell
claude mcp add --transport http -s user tanuki-pro https://mcp.tanukitrade.com/mcp/v1 \
  --header "Authorization: Bearer 12345.YOUR_API_KEY"

-s user stores the server for every project on this machine. Then run /mcp inside Claude Code. tanuki-pro should be connected.

Cursor

Put this in ~/.cursor/mcp.json. Do not commit a project copy that still has the real token.

mcp.json
{
  "mcpServers": {
    "tanuki-pro": {
      "url": "https://mcp.tanukitrade.com/mcp/v1",
      "headers": {
        "Authorization": "Bearer 12345.YOUR_API_KEY"
      }
    }
  }
}

Open Settings, then MCP. tanuki-pro should show a green dot. Ask it to list SPX with TanukiTrade. A 401 is the bearer token or the header, not the tool arguments.

Next: the API overview lists every route. Errors lists the shared failure codes.

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