Docs/Option Chain API
Option Chain API
POST /api/option-chain reference: full U.S. option chains with strikes, expirations, bid/ask, OI, IV, Greeks, and optional flow fields.
Beta. This API is in beta testing. The request and response schema (fields, units, and semantics) may change. Each response includes
meta.api_version,meta.beta: true, andmeta.notice, plus anX-OptionData-Option-Chain-Beta: trueheader.
The Option Chain API exposes per-contract chain rows for an underlying, for a given trading date:
POST https://www.optiondata.io/api/option-chain
It is included with the realtime plan — both trialing and active realtime subscriptions get full access. Signed-in users without realtime access can use test_mode=true for 10 sample rows.
Request
JSON and form (application/x-www-form-urlencoded / multipart/form-data) bodies are supported. Field names are snake_case.
Required:
symbol: one underlying ticker (uppercased by the server; 1–16 chars).
Optional:
api_key:cus_...(raw Stripe customer id) or a generatedapikey_...token. If omitted, the signed-in session is used.date:YYYY-MM-DD. If omitted, the latest available date inmv_contract_rank_flowis used (meta.filters.date_modereportsexplicitvslatest).expiration_date:YYYY-MM-DD.put_call:CALLorPUT.min_strike,max_strike: numbers.min_expiry_days,max_expiry_days: integers (days to expiration).include_flow: boolean (defaultfalse) — include the flow fields (see below).limit: default1000, capped byOPTION_CHAIN_MAX_ROWS.test_mode: boolean — return 10 sample rows (still requires a resolvable customer; skips the realtime-subscription gate only).
Source and semantics
Reads mv_contract_rank_flow, a per-contract-per-day materialized mart, with aggregate-state merge functions grouped by option_symbol for the requested date. Several fields are derived in the query (see the Response tables). Prices are in USD; Greeks/IV are decimals (e.g. IV 0.22 = 22%).
Response — core fields (always returned)
{ "status": "SUCCESS", "data": [ ... ], "meta": { ... } }
| Field | Type | Notes |
|---|---|---|
symbol | string | Underlying ticker |
option_symbol | string | OCC option symbol |
put_call | CALL | PUT | |
strike | number | null | Strike price |
expiration_date | string | null | YYYY-MM-DD |
expiry_days | number | null | Days to expiration = dateDiff(date, expiration_date) |
bid | number | null | Best bid |
ask | number | null | Best ask |
mark | number | null | Bid/ask midpoint; falls back to the latest trade price when there is no two-sided quote (bid>0 && ask>0) |
close | number | null | Latest trade price — NOT a settlement/closing price |
open_interest | number | null | |
open_interest_change | number | null | open_interest − prior-day OI (prior OI null ⇒ treated as 0) |
volume | number | null | Daily volume |
implied_volatility | number | null | Decimal |
delta / gamma / theta / vega | number | null | Greeks (decimal) |
Response — flow fields (only when include_flow=true)
| Field | Type | Notes |
|---|---|---|
premium | number | null | Total premium = ask + bid + mid premium |
size | number | null | Total contracts = ask + bid + mid size |
trade_count | number | null | |
latest_trade_price | number | null | Last trade price (same value as close) |
latest_trade_time | string | null | |
vol_oi_ratio | number | null | volume / open_interest (open_interest 0 ⇒ 0) |
A field is null when the value is not present in the source row. (Note: dex/sentiment fields are not returned by this endpoint.)
Response — meta
| Field | Notes |
|---|---|
api_version | Schema version (currently v1) |
beta | true while the API is in beta |
notice | Beta notice string |
entitlement | active | trialing | sample (sample for test_mode) |
source | mv_contract_rank_flow |
date | The snapshot date used |
row_limit | Effective row cap |
returned | Row count returned |
filters | Echo of applied filters incl. date_mode (explicit/latest) |
statistics | Passthrough ClickHouse query stats (when available) |
test_mode | true for sample responses |
Errors
All errors return { "status": "ERROR", "errorMsg": "..." } with an HTTP status:
| Status | Meaning |
|---|---|
400 | Invalid body or failed request validation (errorMsg lists the problems) |
401 | Could not resolve a customer (missing/invalid api_key and no session) |
403 | Resolved, but no active/trialing realtime subscription |
429 | Rate limited (best-effort, in-memory, per-customer; honors Retry-After) |
504 | Query timed out |
500 | Unexpected server error |