# Quant Data API — Full Reference for AI Agents > Exchange-licensed US options and equities market data over a hosted REST API and an MCP > server. This file is the complete, self-contained reference: base URL, authentication, > request conventions, every endpoint with its exact path and required parameters, the MCP > tools, rate limits, and the error format. A concise index lives at > https://quantdata.us/llms.txt and the human documentation at https://quantdata.us/api/docs. ## Anti-hallucination rules - Only call the endpoints, MCP tools, and parameters listed in this file. Never invent an endpoint, tool, path, field, or enum value. - Pass only documented fields. Field-name matching is case-, separator-, and whitespace-insensitive, but the field itself must be real. - Quant Data covers US options and equities market-structure data only. It does not provide crypto, forex, non-US markets, or company fundamentals. If asked for those, say so. - If you cannot map a request to a documented endpoint with confidence, return https://quantdata.us/api/docs instead of guessing. - Prefer the MCP server when available; its typed tools remove most chances to hallucinate. ## Base URL and protocol - Base URL: `https://api.quantdata.us` - All endpoints are `POST` with a JSON request body and `Content-Type: application/json`. There are no GET endpoints, query-string parameters, or path parameters. - Options paths: `https://api.quantdata.us/v1/options/tool/` - Equities paths: `https://api.quantdata.us/v1/equities/tool/` - News path: `https://api.quantdata.us/v1/news/tool/news-articles` - An empty body `{}` returns the latest completed trading session for that endpoint. ## Authentication - Header on every request: `Authorization: Bearer ` - API key format: `qd_` followed by 32 alphanumeric characters (regex `^qd_[0-9A-Za-z]{32}$`). - Keys are created in the dashboard at https://v3.quantdata.us. The same key authenticates the REST API and the MCP server. An active API subscription and a signed OPRA market-data agreement are required. ## Request conventions - Common top-level fields (pass only those an endpoint documents): - When: `sessionDate` (`YYYY-MM-DD`) or `timeRange` (`{ "startTime": "2026-05-13T14:30:00Z", "endTime": "2026-05-13T20:00:00Z" }`, ISO 8601 instants, start inclusive, end exclusive). Omit to get the latest session. - What: `filter` (a convenience object of camelCase fields) and/or `filterExpression` (the boolean DSL below). If both are present they are combined with AND. - How: `aggregationPeriod`, `includes`, `excludes`, `size`, `sort` where documented. - Collection fields accept singular or plural names and a scalar or array value. These are all equivalent: `{"ticker":"AAPL"}`, `{"ticker":["AAPL"]}`, `{"tickers":"AAPL"}`, `{"tickers":["AAPL"]}`. - Enum values are UPPER_SNAKE_CASE in both requests and responses (for example `CALL`, `PUT`, `ABOVE_ASK`, `MODERATELY_BULLISH`). - Response units: money is dollars with decimals (not cents), volume and size are integer counts, and timestamps are epoch milliseconds. Time-series responses are maps keyed by epoch-millisecond bucket; aggregation responses are maps keyed by ticker, strike, expiration, exchange, or contract type depending on the endpoint. ## Filter expression DSL (`filterExpression`) A recursive boolean tree. Two node kinds: - Terminal: `{ "field": "TICKER", "operation": "=", "values": ["AAPL", "NVDA"] }`. Use `value` for one value or `values` for several (OR semantics within one terminal). - Compound: `{ "conjunction": "AND", "filters": [ ...terminals or compounds... ] }`. `conjunction` is `AND` or `OR`. Operations accept canonical or shorthand spellings: `EQUALS` (`=`, `==`, `EQ`), `DOES_NOT_EQUAL` (`!=`, `<>`, `NEQ`), `GREATER_THAN` (`>`, `GT`), `GREATER_THAN_OR_EQUAL_TO` (`>=`, `GTE`, `GE`), `LESS_THAN` (`<`, `LT`), `LESS_THAN_OR_EQUAL_TO` (`<=`, `LTE`, `LE`). Limits: maximum nesting depth 5, maximum 100 total terminal filters. ## Pagination and projection (table-shaped endpoints only) Applies to Order Flow Consolidated, Order Flow Unconsolidated, Open Interest Change, Equity Prints, Exchange Notifications, and News Articles. Aggregation and time-series endpoints return a single response and ignore these. - `size`: rows per page, default 50, range 1 to 100. Order Flow Unconsolidated accepts up to 1000. - Cursor: each response includes `nextSearchAfter` (an opaque array). Pass it back verbatim as `searchAfter` on the next request. `null` means the walk is complete. Do not modify the cursor or change the filter, sort, session, or time range mid-walk. - `sort`: `{ "field": "TRADE_TIME", "direction": "DESCENDING" }`. Defaults vary by endpoint (most default to `tradeTime DESCENDING`; News Articles is always `publishedTime DESCENDING` and takes no `sort`). - Projection: `includes` (whitelist) or `excludes` (blacklist) of field names, mutually exclusive. Omit both to get every field. ## Rate limits - 240 requests per 60-second sliding window, plus a burst cap of 20 requests per 1 second, counted per user (shared across every key on the account and across REST and MCP traffic). - Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` (seconds). A `429` also carries `Retry-After`. - On `429`: sleep at least `Retry-After` seconds, add 50 to 500 ms of jitter, then retry. Pace proactively as `X-RateLimit-Remaining` nears zero. Stop after 2 to 3 consecutive `429`s. ## Errors RFC 9457 problem details (`application/problem+json`) with `type`, `title`, `status`, `detail`, and `instance`: - `400` `validation`: a field failed validation (see the `errors` array). Fix the field. - `400` `bad-request`: the body could not be parsed. Send valid JSON with the content type. - `401` `authentication`: key missing, malformed, unknown, or revoked. - `403` `authorization`: no active API subscription. - `403` `opra-agreement-required`: OPRA agreement unsigned (see the `agreementUrl` field). - `422` `data-unavailable`: the request was valid but no data exists for those inputs. - `429` `rate-limit-exceeded`: back off as above. - `500` `internal`: server error; retry later. ## Quickstart example ```bash curl -X POST https://api.quantdata.us/v1/options/tool/gainers-losers \ -H "Authorization: Bearer $QUANTDATA_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` ```json { "data": { "AAPL": { "bullishPremium": 6128974.25, "bearishPremium": 4821330.50, "premium": 11402108.75, "premiumRatio": 0.787, "tradeCount": 18472, "volume": 41208 } } } ``` Add a session and a filter expression: ```json { "sessionDate": "2026-05-13", "filterExpression": { "conjunction": "AND", "filters": [ { "field": "ticker", "operation": "=", "values": ["AAPL", "NVDA"] }, { "field": "premium", "operation": ">=", "value": 100000 } ] } } ``` ## Options endpoints (23) Each entry: name, exact path, required parameters, and response shape. All accept the common optional `sessionDate` / `timeRange`, `filter`, and `filterExpression` fields unless noted. - **Contract Statistics** — `POST /v1/options/tool/contract-statistics`. Required: none. Premium, trade count, and volume rolled up by contract type. Shape: map keyed by `CALL` / `PUT`. - **Contract Trade Side Statistics** — `POST /v1/options/tool/contract-trade-side-statistics`. Required: `dataMode` (`PREMIUM` | `TRADE_COUNT` | `VOLUME`). Adds an aggressor-side partition (`ABOVE_ASK`, `ASK`, `MID_MARKET`, `BID`, `BELOW_BID`). Shape: two-level map by contract type then side. - **Exposure By Expiration** — `POST /v1/options/tool/exposure-by-expiration`. Required: `filter.ticker`, `greekMode` (`CHARM` | `DELTA` | `GAMMA` | `VANNA`), `representationMode` (`PER_ONE_DOLLAR_MOVE` | `PER_ONE_PERCENT_MOVE` | `RAW`). Optional: `snapshotTime`. Shape: nested grid expiration then strike then leg, plus `stockPrice`. - **Exposure By Strike** — `POST /v1/options/tool/exposure-by-strike`. Required: `filter.ticker`, `greekMode`, `representationMode` (same enums as above). Optional: `snapshotTime`, `filter.expirationDate`, `filter.moneyTypes`. Shape: nested grid. - **Gainers / Losers** — `POST /v1/options/tool/gainers-losers`. Required: none. Per-ticker bullish vs bearish premium, volume, trade count, and `premiumRatio`. Shape: map keyed by ticker. - **Heat Map** — `POST /v1/options/tool/heat-map`. Required: `filter.ticker`, `dataMode`. Net modes (`NET_DELTA_EXPOSURE`, `NET_GAMMA_EXPOSURE`, `NET_VANNA_EXPOSURE`, `NET_CHARM_EXPOSURE`, `NET_OPEN_INTEREST`, `NET_PREMIUM`, `NET_TRADE_COUNT`, `NET_VOLUME`) return `{callValue, putValue}` per cell; per-leg modes (`CALL_DELTA`, `PUT_GAMMA`, and so on) return `{value}` per cell. Optional: `snapshotTime`. Shape: polymorphic strike-by-expiration grid (branch on the top-level `type`). - **Interval Map** — `POST /v1/options/tool/interval-map`. Required: `filter.ticker`, `greekMode` (`CHARM` | `DELTA` | `GAMMA` | `VANNA`). Optional: `aggregationPeriod`, `filter.expirationDate`. Shape: time-series of exposure grids keyed by epoch-ms bucket. - **IV Rank** — `POST /v1/options/tool/iv-rank`. Required: `filter.ticker`, `lookBackPeriod` (1 to 365 days), `maturity` (1 to 365 days). Optional: `filter.contractTypes`. Shape: per-session map with per-contract-type last / window-min / window-max IV. - **Market Share** — `POST /v1/options/tool/market-share`. Required: none. Per-exchange split into equity calls, equity puts, and index options. Shape: map keyed by exchange. - **Max Pain** — `POST /v1/options/tool/max-pain`. Required: `filter.ticker`, `filter.expirationDate`. Shape: per-strike call/put intrinsic value plus `maxPainStrikePrice` and `stockPrice`. - **Max Pain Over Time** — `POST /v1/options/tool/max-pain-over-time`. Required: `filter.ticker`. Shape: map keyed by expiration date to the max-pain strike (the over-time axis is expiration, not intraday). - **Net Drift** — `POST /v1/options/tool/net-drift`. Required: none. Optional: `aggregationPeriod`. Per-bucket (not cumulative) net call vs put premium and volume over time, with `stockPrice`; sum the buckets in timestamp order to build the drift curve. A still-forming bucket can grow on a later read. Shape: time-series keyed by epoch-ms. - **Net Flow** — `POST /v1/options/tool/net-flow`. Required: `dataMode` (`NET_PREMIUM` | `NET_VOLUME`). Optional: `aggregationPeriod`. Total call and put activity over time. Shape: time-series keyed by epoch-ms. - **Open Interest By Expiration** — `POST /v1/options/tool/open-interest-by-expiration`. Required: `filter.ticker`. Optional: `filter.strikePrice`. Shape: map keyed by expiration to call/put OI. - **Open Interest By Strike** — `POST /v1/options/tool/open-interest-by-strike`. Required: `filter.ticker`. Optional: `filter.expirationDate`. Shape: map keyed by strike to call/put OI. - **Open Interest Change** — `POST /v1/options/tool/open-interest-change`. Required: none. Table-shaped (supports `size`, `sort`, `searchAfter`, `includes` / `excludes`). Per-contract daily OI delta records (previous, current, signed change, percent change). Shape: row array plus `nextSearchAfter`. - **Open Interest Over Time** — `POST /v1/options/tool/open-interest-over-time`. Required: `filter.ticker`. Optional: `filter.expirationDate`, `filter.strikePrice`. Per-session call/put OI across all available sessions (no time-selection field). Shape: map keyed by session date. - **Option Price Over Time** — `POST /v1/options/tool/option-price-over-time`. Required: either `filter.osi` (21-character OSI symbol) or all of `filter.ticker` + `filter.expirationDate` + `filter.strikePrice` + `filter.contractType` (`CALL` | `PUT`). Optional: `aggregationPeriod`. OHLC plus volume for one contract. Shape: time-series keyed by epoch-ms. - **Order Flow Consolidated** — `POST /v1/options/tool/order-flow/consolidated`. Required: none. Table-shaped. Consolidated sweeps, splits, blocks, and multi-leg orders. Optional: `includeStatistics`, `includeComprisingTrades`. Shape: row array plus `nextSearchAfter`. - **Order Flow Unconsolidated** — `POST /v1/options/tool/order-flow/unconsolidated`. Required: none. Table-shaped. Individual option trades, one row per exchange leg. Optional: `includeStatistics`. Shape: row array plus `nextSearchAfter`. - **Term Structure** — `POST /v1/options/tool/term-structure`. Required: `filter.ticker`. Optional: `snapshotTime`, `filter.deltaRange`, `filter.moneyTypes`. Per-cell IV enriched with delta and moneyness, plus `stockPrice`. Shape: nested grid expiration then strike then leg. - **Volatility Drift** — `POST /v1/options/tool/volatility-drift`. Required: `filter.ticker`. Optional: `filter.expirationDate`. Per-minute ARV, average ATM IV, and stock price. Shape: 1-minute time-series keyed by epoch-ms (`iv` may be null in a bucket). - **Volatility Skew** — `POST /v1/options/tool/volatility-skew`. Required: `filter.ticker`. Optional: `snapshotTime`, `filter.contractTypes`, `filter.expirationDates`. Per-strike IV curve, plus `stockPrice`. Shape: nested grid expiration then strike then leg. ## Equities endpoints (6) - **Dark Flow** — `POST /v1/equities/tool/dark-flow`. Required: `filter.ticker`. Optional: `aggregationPeriod`. Off-exchange notional, size, and trade count over time, with `stockPrice`. Shape: time-series keyed by epoch-ms. - **Dark Pool Levels** — `POST /v1/equities/tool/dark-pool-levels`. Required: `filter.ticker`, `sessionDateRange.startDate` (`endDate` optional). Off-exchange print activity aggregated by price level, plus `latestStockPrice`. Shape: map keyed by price level. - **Equity Prints** — `POST /v1/equities/tool/equity-prints`. Required: none. Table-shaped. Individual lit and dark equity prints (`printType`, `tradeSide`, bid/ask context). Shape: row array plus `nextSearchAfter`. - **Exchange Notifications** — `POST /v1/equities/tool/exchange-notifications`. Required: none. Table-shaped. Trade-halt, IPO, regulatory, and circuit-breaker records (`filter.types` supports 36 values; expression fields `CREATED_TIME`, `TICKER`, `TYPE`). Shape: row array plus `nextSearchAfter`. - **Market Map** — `POST /v1/equities/tool/market-map`. Required: none. Optional: `snapshotTime`, `filter.sectors`, `filter.industries`. Market-wide snapshot with current and previous price, company name, sector, industry, and market cap (`size`). Shape: map keyed by ticker. - **Stock Price Over Time** — `POST /v1/equities/tool/stock-price-over-time`. Required: `filter.ticker`. Optional: `aggregationPeriod`. OHLC bars for the underlying. Shape: time-series keyed by epoch-ms (no volume field). ## News endpoint (1) - **News Articles** — `POST /v1/news/tool/news-articles`. Required: none. Table-shaped (always sorted `publishedTime DESCENDING`, no `sort` field). Optional: `includeBody` (default false), `filter.tickers`, `filter.topics` (121 values), `filter.sentiments` (7-point scale `EXTREMELY_BEARISH` to `EXTREMELY_BULLISH`). Projectable fields: `ID`, `PUBLISHED_TIME`, `TICKER`, `TITLE`, `TOPICS`. Shape: row array (each row tags tickers with per-ticker sentiment) plus `nextSearchAfter`. ## MCP server - URL: `https://api.quantdata.us/mcp` (streamable HTTP, hosted). - Auth: the same `Authorization: Bearer ` header as the REST API. One tool call counts as one request against the rate-limit bucket. - Tools are named `qd_get_` in snake_case and map one-to-one to the REST endpoints, for example `qd_get_gainers_losers`, `qd_get_heat_map`, `qd_get_exposure_by_strike`, `qd_get_volatility_skew`, `qd_get_order_flow_consolidated`, `qd_get_equity_prints`, `qd_get_news_articles`. A `qd_ping` health-check tool confirms the server is reachable. - Example Claude Desktop configuration: ```json { "mcpServers": { "quantdata": { "type": "http", "url": "https://api.quantdata.us/mcp", "headers": { "Authorization": "Bearer " } } } } ``` Per-client setup for Claude Desktop, Claude Code, ChatGPT, Cursor, VS Code, Windsurf, Cline, Gemini CLI, and Goose is documented at https://quantdata.us/api/docs/mcp-server. ## More - Index and intent-to-endpoint routing: https://quantdata.us/llms.txt - How to call the API end to end: https://quantdata.us/skill.md - Human documentation: https://quantdata.us/api/docs - Agent integration overview: https://quantdata.us/for-ai-agents