Skip to content

Guide

Conventions

The rules every endpoint shares: how parameters are checked, how time is written, and how to name an option contract, a futures contract or an instrument.
On this page

Parameters#

All parameters go in the query string. POST /v1/exports and POST /mcp take JSON bodies.

TypeFormat
stringAt most 128 characters unless the endpoint says otherwise. Symbols have their own patterns.
integer, numberPlain decimal digits: 100, -3, 0.25. No exponent and no thousands separators.
decimal (strikes)Positive, at most 6 decimal places in general and 3 for option strikes: 5800, 5812.5.
booleanExactly true or false.
enumA lowercase snake_case token from the documented list: rth, above_ask.
listComma-separated in one parameter: symbols=SPX,NDX,VIX. Each endpoint documents the maximum number of items.
time (unix-ms)Unix epoch milliseconds, an integer between 946684800000 (2000-01-01) and 4102444800000 (2100-01-01).
dateYYYY-MM-DD.

Strict parameters#

Strictness is deliberate, so a typo never silently changes what you asked for:

  • An unknown parameter is 400 unknown_parameter (the names are listed), a repeated parameter is 400 duplicate_parameter (use a comma-separated list), a missing required parameter is 400 missing_parameter and an invalid value is 400 invalid_parameter. error.details names every offending parameter and what is wrong with it.
  • An empty value, or a value with leading or trailing spaces or control characters, is invalid.
  • The whole query string may be at most 2,048 bytes and 32 parameters (400 query_too_large).
  • Percent-encode values. curl --data-urlencode does it for you, and so does URLSearchParams.

Time#

  • Every timestamp, in requests and responses, is a Unix millisecond integer (UTC). Names are timestamp, *_timestamp, start_time, end_time and *_time (a bar's start). Never a string, never seconds.
  • start_time is inclusive and end_time is exclusive.
  • Native 64-bit values that can exceed 2^53 (tick counts, nanosecond order keys) are returned as strings so JavaScript clients do not lose precision. The field descriptions say which.
  • Dates are YYYY-MM-DD. A date is the exchange-local trading date (America/New_York). For futures and for overnight option sessions the trading date is the date the session belongs to: an overnight session that runs the evening before and the morning of 2026-10-16 is trading date 2026-10-16.

Sessions#

All times are Eastern Time. /v1/market/sessions, /v1/futures/sessions, /v1/options/sessions and /v1/market/calendar return the windows for a date, including holidays and early closes.

MarketSessionHours (ET)
OptionsRegular, rth09:30 to 16:15 for index and ETF options
OptionsOvernight, gth20:15 the evening before to 09:25
OptionsCurb16:15 to 17:00
FuturesGlobex18:00 to 17:00
StocksPre-market, regular, after-hoursFrom 04:00; 09:30 to 16:00; until 20:00

Option contracts#

An option contract is identified by four parameters, required on every contract-level endpoint (/v1/options/contract/...):

ParameterMeaning
underlying_symbolThe option root: SPXW (weekly and daily, PM-settled SPX options), SPX (monthly, AM-settled), NDXP, RUTW, XSP, QQQ, SPY and so on. SPX and SPXW are different roots with different contracts.
contract_typecall or put.
strikeDollars, for example 5800 or 5812.5 (at most three decimals).
date_of_expiryYYYY-MM-DD.

Responses identify a contract with option_symbol, an OCC-style 21-character symbol: the root padded to six characters, YYMMDD, C or P, then the strike times 1,000 in eight digits (SPXW 261016C05800000). Contract rows also carry underlying_symbol, contract_type, strike and date_of_expiry as separate fields.

Aggregate option endpoints (chains, flow, exposure, volatility, open interest) take underlying_symbol and optional contract_type, date_of_expiry, min_dte and max_dte, and strike bounds. On them SPX means the SPX family (both the SPX and SPXW roots) and SPXW selects the weekly root alone. The endpoint description says how it treats a family.

Futures roots and dated contracts#

symbol is the product root (ES, NQ, CL, GC; one to three letters or digits) and contract is an exact dated contract (ESZ6: root, month code FGHJKMNQUVXZ, year). Give one of them; a request with neither is 400 missing_parameter.

  • With only a root, the front month is used and every response echoes the resolved contract.
  • Two-digit years (ESZ26) are accepted and answered in the one-digit form.
  • Only the front month and the contracts listed by /v1/futures/contracts are served. Any other contract is 422 data_unavailable.
  • /v1/futures/products lists the supported products with tick size, point value, exchange and trading hours.

Indices and stocks#

symbol is a single instrument and symbols a comma-separated list, bounded per endpoint: 50 for the snapshots and 10 for /v1/indices/basis/snapshot. Indices use their plain symbols, never a feed prefix: SPX, NDX, DJI, RUT, XSP, VIX, VIX1D, VIX9D and VVIX are served, and /v1/indices/list returns the current set and which of them have a futures pair for the basis endpoints. Stock symbols are tickers such as AAPL or BRK.B.

Paths and versioning#

All paths are lowercase and kebab-case: /v1/{family}/{resource}[/{sub-resource}]. /v1 is the version. Additive changes (new endpoints, new optional parameters, new response fields) can appear in /v1 at any time, so ignore fields you do not know. A breaking change would be published under /v2 and /v1 would keep working alongside it.

Every REST endpoint is GET, with two documented exceptions because the protocols require it: POST /mcp and POST /v1/exports. Any other method on a known path answers 405 method_not_allowed with Allow: GET, and an unknown path answers 404 not_found. Both use the standard error body.