Skip to content

Docs/Market Structure API (GEX)

API reference

Market Structure API (GEX)

GET /api/v1/market-structure/:symbol reference: structural Gamma Exposure, intraday GEX, Gamma Flip, walls, Max Pain, IV context, session flow, and symbol metadata.

Open product
On this page

The Market Structure API returns a precomputed, symbol-level snapshot of full-chain dealer-positioning structure (GEX), open interest walls, Max Pain, volatility context, and five-minute session flow plus intraday GEX summaries.

Text
GET https://www.optiondata.io/api/v1/market-structure/:symbol

Included with the realtime plan (trialing or active). Authenticate with a signed API key.

Authentication

Send your API key as:

HTTP
Authorization: Bearer YOUR_API_KEY

YOUR_API_KEY may be a raw Stripe customer id (cus_...) or a portal-minted apikey_... token.

Path parameters

NameRequiredDescription
symbolRequiredUnderlying option root (e.g. SPY, SPXW, AAPL). Uppercased server-side.

Query parameters

NameRequiredDescription
dateOptionalReal YYYY-MM-DD calendar date selecting a retained trading-session snapshot. Omit for the latest available snapshot and check meta.effective_date. An explicit date is never replaced with another session.

Example

Shell
curl "https://www.optiondata.io/api/v1/market-structure/SPY" \
  -H "Authorization: Bearer YOUR_API_KEY"

curl "https://www.optiondata.io/api/v1/market-structure/SPY?date=YYYY-MM-DD" \
  -H "Authorization: Bearer YOUR_API_KEY"

Replace YYYY-MM-DD with a retained trading date. A weekend, holiday, future date, or session outside retention can return 404.

Response shape

Top-level:

FieldTypeDescription
data.symbolstringExact option root requested
data.symbol_metaobjectUnderlying metadata and volatility context
data.flowobjectLightweight traded-flow overlay for the symbol
data.intraday_gexobject | nullLatest full-chain summary GEX and spot
data.structureobjectFull-chain GEX, OI, levels, strike-by-expiration aggregates
meta.effective_datestringSnapshot trading date (YYYY-MM-DD)
meta.structure_as_ofstringUTC source time represented by the structural snapshot; not the request time
meta.flow_as_ofstringUTC update time for the session-flow summary; may equal structure_as_of before session flow is available
meta.intraday_gex_as_ofstring | nullUTC update time for the intraday GEX summary, or null when unavailable

Symbol metadata

Volatility values are annualized decimals where applicable (0.22 means 22%); IV rank and percentile are 0–1 fractions. Nullable fields are null when unavailable. The optional realized-volatility fields may also be absent on older snapshots.

FieldTypeDescription
underlying_typeSTOCK | ETF | INDEX | nullUnderlying classification
descriptionstringCompany, fund, or index name
exchange / sectorstring | nullExchange and sector classification
market_capnumber | nullUnderlying market capitalization in USD
outstanding_sharesnumber | nullOutstanding share count
earning_datestring | nullEarnings date, when available
average_stock_volumenumber | nullAverage underlying trading volume
volumenumberUnderlying volume in the symbol metadata; not option-contract volume
open / high / low / close / lastnumberUnderlying prices in USD from the latest completed session when the structure was built. During a session this is the previous session; use intraday_gex.spot for the latest available intraday price
previous_closenumber | nullPrevious underlying closing price in USD
historical_volatilitynumber | nullHistorical-volatility context; use rv20 or rv30 for an explicitly defined return window
rv20 / rv30number | null, optionalAnnualized sample realized volatility from the latest 20 / 30 valid trading-session log returns, using 252 trading days per year; null when there are insufficient returns
rv_as_ofstring | null, optionalLatest completed session included in RV20/RV30, as YYYY-MM-DD
iv30number | nullInterpolated 30-day ATM implied volatility (decimal)
iv_rank_1y / iv_percentile_1ynumber | nullOne-year IV rank / percentile as 0–1 fractions
skew_25d_30dnumber | null30-day 25-delta put/call skew
butterfly_25d_30dnumber | null30-day 25-delta volatility butterfly
iv_term_slope_30_90number | null30-to-90-day IV term slope
vol_datestring | nullTrading date of the IV analytics, as YYYY-MM-DD

structure highlights

FieldTypeDescription
spotnumberUnderlying price used for exposure calculations
call_oi / put_oinumberAll-scope open-interest contract totals
call_gex / put_gexnumberAll-scope dollar GEX for a 1% move; put GEX is signed negative
scopesobjectLevels by DTE bucket, keyed all, zero_dte, weekly, and monthly. Each value is a levels object or null
max_pain_curvearray{ strike, payout } points: the multiplier-adjusted aggregate payout at each candidate strike. Its lowest point is scopes.all.max_pain
expirationsarrayFull-chain strike aggregates grouped by expiration

Days to expiration are calendar days measured from meta.effective_date: all includes every unexpired expiration, zero_dte is 0 days, weekly is 1–7 days, and monthly is 8–31 days. These are day ranges, not exchange expiration-series labels. A scope with no applicable contracts is null.

Each expirations entry contains expiration_date (YYYY-MM-DD) and a strikes array. Each strike contains numeric strike, call_oi, put_oi, call_gex, and put_gex; put GEX is signed negative. OI totals are contract counts and GEX is in USD for a 1% underlying move.

structure.scopes.<scope> levels

Levels are only inside a scope, for example data.structure.scopes.all.gamma_flip. structure has no top-level gamma_flip, max_pain, or wall fields.

FieldTypeDescription
gamma_flipnumber | nullNearest repriced zero-net-GEX underlying level
max_painnumber | nullStrike with lowest multiplier-adjusted aggregate payout
call_gex_wall / put_gex_wallnumber | nullStrongest call/put GEX strike on the corresponding side of spot
call_oi_wall / put_oi_wallnumber | nullHighest call/put OI strike on the corresponding side of spot

flow highlights

FieldTypeDescription
call_premium / put_premiumnumberSession option premium by side (USD)
bullish_dex / bearish_dexnumberBullish and bearish delta-exposure flow totals
trade_countnumberOption trades represented by the overlay
traded_contract_countnumberDistinct contracts with trades

intraday_gex highlights

FieldTypeDescription
spotnumberLatest positive underlying price used for the summary
call_gexnumberFull-chain positive call dollar GEX, including zero-trade contracts
put_gexnumberFull-chain signed-negative put dollar GEX, including zero-trade contracts

Semantics notes

  • Dealer positioning is a model, not reported dealer inventory. Put GEX uses a documented dealer-short-put signing convention.
  • Net GEX can be derived as call_gex + put_gex (put already signed).
  • Session flow and data.intraday_gex normally update about every five minutes during the regular session. Use meta.flow_as_of and meta.intraday_gex_as_of separately from meta.structure_as_of; this cadence does not promise fresh values for every symbol on every interval.
  • Structural strike GEX, walls, Gamma Flip, Max Pain, OI, and expiration aggregates update when a newer full-chain structural snapshot becomes available. They do not follow each trade update in the Option Chain API.
  • data.intraday_gex is null when no summary is available for the symbol. Its timestamp describes the summary update across the response's session, not a per-contract observation time. A zero flow total alone is not a completeness indicator.
  • Structural snapshots include unexpired supported standard contracts, including contracts with no trades. A root without supported structure data can return 404 even when the Option Chain API has contract rows for it.
  • Put/call OI ratio can be derived as put_oi / call_oi when call_oi > 0.
  • Prefer Market Structure for positioning dashboards; use the Option Chain API when you need filterable contract-level quotes and Greeks.

Errors

StatusMeaning
400Invalid symbol, or a date that is not a real YYYY-MM-DD calendar date
401Missing or invalid API key
403No active/trialing realtime entitlement
404SNAPSHOT_NOT_FOUND for a date with no snapshot, or SYMBOL_NOT_FOUND for a symbol with no data
405METHOD_NOT_ALLOWED: use GET; the Allow header lists the supported methods
429Rate limited
503UPSTREAM_UNAVAILABLE: the snapshot service or API key verification is unavailable or timed out; retry later, honoring Retry-After when present
500Unexpected server error

Errors return { "error": { "code": "...", "message": "..." } }. A 403 (SUBSCRIPTION_REQUIRED) also carries reason and billing_url inside error:

JSON
{
  "error": {
    "code": "SUBSCRIPTION_REQUIRED",
    "message": "An active or trialing subscription is required.",
    "reason": "NO_ACTIVE_SUBSCRIPTION",
    "billing_url": "/billing"
  }
}

reason is always NO_ACTIVE_SUBSCRIPTION: the API key is valid, but its account has no active or trialing Pro subscription. A Pro subscription whose renewal payment failed more than 7 days into the unpaid billing period gets the same response until the invoice is paid. billing_url is the path on https://www.optiondata.io where the account owner can restore Pro access. Do not retry until access is restored.

FAQ

Q: Rate limits and access?
A: Requires trialing or active Pro + API key. The current default is about 60 requests / 60 seconds per customer on this endpoint, for trial and paid users, enforced on a best-effort basis. HTTP 429 includes Retry-After.

Planned, not yet active: trial 30/minute and 1,200/hour; paid Pro 60/minute and 3,600/hour. Once enabled, both limits apply per customer across their keys and IPs; reaching either triggers rate limiting. No effective date has been announced. Enterprise limits are contract-specific. See API rate limits for the complete policy. Subscription access remains the same as Option Chain and Historical SQL.

Q: Freshness?
A: Structural levels update on builds (structure_as_of). Some intraday GEX fields can refresh about every five minutes in session—use response meta timestamps.

Q: History range?
A: Dated snapshots cover recent retained trading sessions; availability varies by date and option root, and older sessions age out over time. Request the required date explicitly and handle 404 when it is unavailable. A dated snapshot is session-level data, not an intraday replay. For individual trades, Historical SQL covers the past 15 days on paid plans.

Q: Free trial / extension?
A: Complete qualification, then explicitly activate the 14-day Pro trial when you are ready. Eligible trial users can receive 50% off for life with a promotion code from Sales; contact Sales for the code, then enter it on Billing before the trial ends. Trials are not auto-extended.

Q: Market Structure vs Option Chain?
A: Structure for GEX/walls/max pain dashboards; Option Chain for filterable contract quotes/Greeks.

Ask ChatGPT or Claude Code

Copy this prompt, paste it into ChatGPT, Claude, Claude Code, Cursor, or Codex, then add your question. It tells the model to read our public docs first — no API key needed for that step.

You are helping me use OptionData (https://www.optiondata.io/), an OPRA-licensed U.S. equity options data API.

Before answering, fetch these public files (no login required) and treat them as the source of truth:
- https://www.optiondata.io/llms.txt — short product map (same content as https://www.optiondata.io/llm.txt)
- https://www.optiondata.io/llms-full.txt — full API reference
- https://www.optiondata.io/openapi.json — HTTP OpenAPI

Do not invent endpoints, fields, tables, or limits. Prefer `Authorization: Bearer apikey_…` for HTTP APIs. Realtime uses `wss://ws.optiondata.io` with a `token` query parameter.

Products:
- Realtime trades WebSocket: wss://ws.optiondata.io
- Historical SQL: POST https://www.optiondata.io/api/historical/sql
- Option chain: POST https://www.optiondata.io/api/option-chain
- Market structure: GET https://www.optiondata.io/api/v1/market-structure/{symbol}

I am asking about: Market Structure API (GEX)
- Markdown: https://www.optiondata.io/md/market-structure-api
- HTML docs: https://www.optiondata.io/docs/market-structure-api

My question: