Skip to content

Last updated: Oct 14, 2026

API Changelog

Schema and contract changes to the OptionData data APIs — Market Structure, Option Chain, Realtime WebSocket, and Historical SQL. Breaking changes are marked.

For the current request/response schema, see the API references: Option Chain · Market Structure · Historical SQL · Realtime

34 changes

  1. ChangedHistorical SQLBreakingUnreleased

    Trial Historical SQL: past 7 days, up to 1,000 rows per response

    Trialing subscriptions now query a rolling 7-day window (168 elapsed hours, about five trading sessions) and receive up to 1,000 rows per response instead of 10. Trial success responses include meta.lookback_days: 7.

    • Trades older than the window are excluded before joins and aggregations, as for paid subscriptions. Trial queries that targeted older dates now return only in-window trades.
    • meta.capped stays true for trial responses. Paid access, the 15-minute delay, and synthetic test-mode samples are unchanged.
  2. AddedGeneralUnreleased

    403 SUBSCRIPTION_REQUIRED says why and where to restore access

    Option Chain, Market Structure and Historical SQL add reason "NO_ACTIVE_SUBSCRIPTION" and billing_url "/billing" to the HTTP 403 SUBSCRIPTION_REQUIRED body. Option Chain and Market Structure add them inside error; Historical SQL adds them next to errorCode and errorMsg.

    • Existing fields and status codes are unchanged. billing_url is a path on www.optiondata.io where the account owner can restore Pro access.
  3. FixedRealtime WebSocketUnreleased

    AGGREGATED market_cap and updated_timestamp are sent as numbers

    In AGGREGATED mode, the realtime stream sent market_cap and updated_timestamp as JSON strings. They are now JSON numbers, as the field reference documents. RAW mode already sent updated_timestamp as a number.

    • Values are unchanged. A client that converts either field with a number parser keeps working; a client that handles the raw value as a string must accept a number.
  4. FixedMarket StructureUnreleased

    Retryable 503 when the snapshot service cannot be reached

    Market Structure returns HTTP 503 with code UPSTREAM_UNAVAILABLE when its request to the snapshot service fails before any response arrives. These requests previously returned HTTP 500 with INTERNAL_ERROR.

    • Retry the same request later. A timeout or an error status from the snapshot service already returned 503.
  5. FixedGeneralOct 14, 2026

    Retryable 503 when an API key cannot be verified in time

    Option Chain, Market Structure and Historical SQL return HTTP 503 with code UPSTREAM_UNAVAILABLE and a Retry-After header when the account services cannot confirm an API key in time. These requests previously returned HTTP 500 with INTERNAL_ERROR.

    • Retry the same request after the Retry-After seconds. An invalid or revoked key still returns 401 UNAUTHORIZED.
    • Option Chain uses { error: { code, message } } and Historical SQL uses errorCode; Market Structure already used UPSTREAM_UNAVAILABLE for an unavailable snapshot service.
  6. AddedRealtime WebSocketOct 8, 2026

    Realtime stream filters by exact expiration date

    The WebSocket and SSE stream accepts an expiration_date query parameter: one or more YYYY-MM-DD dates, comma-separated. Existing parameters are unchanged.

    • A record passes when its expiration_date equals one of the listed dates. Unlike expiry_days, the selection does not shift from one session to the next, so symbols, put_call, strike and expiration_date together follow one contract.
    • Dates must be YYYY-MM-DD; a value in another format matches nothing. The parameter works in AGGREGATED and RAW modes.
  7. ChangedMarket StructureOct 8, 2026

    Market Structure fields and freshness documented

    The API reference and OpenAPI schema now document RV20/RV30, volatility metadata, expiry scopes, and the separate freshness timestamps. This is a documentation update, not a change to response behavior.

    • rv20 and rv30 are annualized realized-volatility decimals from 20 or 30 valid trading-session log returns. rv_as_of identifies the latest completed session included. These fields are optional and can be absent on older snapshots.
    • Expiry scopes use calendar days from meta.effective_date: zero_dte is 0 days, weekly is 1–7 days, monthly is 8–31 days, and all includes every unexpired expiration.
    • Read meta.structure_as_of, meta.flow_as_of, and meta.intraday_gex_as_of separately. Structural levels follow full-chain snapshot updates; session flow and intraday GEX normally update about every five minutes. An explicit date is never replaced with another session.
  8. ChangedOption ChainOct 8, 2026

    Option Chain freshness and date semantics clarified

    The API reference and quickstart now distinguish the latest available session, trade-derived updates, and contract-level freshness. This is a documentation update; the response fields and expected 90-second update interval are unchanged.

    • Check meta.trading_date and meta.as_of before treating a response as current. meta.as_of is the newest contributing chain snapshot or trade time, not a freshness guarantee for every contract. Contracts without newer trades can retain earlier chain values.
    • An explicit date selects that session’s stored chain, not an intraday replay. Strike filters must be positive; strike cannot be combined with strike_min or strike_max.
  9. FixedOption ChainOct 2, 2026

    Bid and ask filled from session trades

    bid and ask are now the best bid and ask recorded with the contract's most recent trade in the session. Previously most contracts returned no quote, and past sessions had none.

    • This applies to the latest session and to every past date. A contract that did not trade in the session still returns null for both fields.
    • The quote is from the contract's last trade, so a contract that last traded early in the day carries that earlier quote.
  10. ChangedOption ChainBreakingOct 2, 2026

    Invalid dates and missing chains return errors

    Requests that cannot return a chain now fail with an error instead of returning another session or an empty 200.

    • An impossible calendar date such as 2026-02-30 in date or expiration_date returns 400 INVALID_REQUEST. Previously it could return the chain of a later session.
    • A date with no stored session (weekend, holiday, future, or outside retention) returns 404 SNAPSHOT_NOT_FOUND. A symbol with no chain on the session returns 404 SYMBOL_NOT_FOUND.
    • A chain whose filters match no contract still returns 200 with an empty data array.
  11. FixedOption ChainBreakingOct 2, 2026

    Unavailable quotes and Greeks are null

    bid and ask are null when no quote is stored for a contract, instead of 0. implied_volatility and the Greeks are null together when no model value is available, instead of 0.

    • Handle null before arithmetic on these fields. A single 0, such as a bid of 0 with a positive ask, is still a real value.
  12. AddedHistorical SQLOct 2, 2026

    Historical SQL reports truncation and error codes

    Successful responses include meta.truncated, which is true when the query produced more rows than meta.row_limit. Every error response now includes errorCode.

    • meta.capped is unchanged: it means the trial row cap applies, not that rows were cut off.
    • New errorCode values: INVALID_REQUEST, INVALID_SQL, UNAUTHORIZED, SUBSCRIPTION_REQUIRED, RATE_LIMITED, and METHOD_NOT_ALLOWED.
  13. FixedGeneralOct 2, 2026

    Unsupported HTTP methods return 405

    Calling an HTTP data API with the wrong method returns 405 METHOD_NOT_ALLOWED with an Allow header, instead of the website home page.

    • Applies to /api/option-chain and /api/historical/sql (POST) and /api/v1/market-structure/{symbol} (GET). OPTIONS returns 204 with the Allow header.
  14. ChangedOption ChainOct 1, 2026

    Latest option chains update about every 90 seconds

    During U.S. market hours, requests without date return a chain that refreshes about every 90 seconds: contracts that trade receive newer quotes, Greeks, IV, volume, open interest, and last price.

    • The request and response contract is unchanged. Poll every one to two minutes at most and compare meta.as_of before doing new work.
  15. ChangedHistorical SQLBreakingSep 12, 2026

    Paid Historical SQL access limited to the past 15 days

    Paid (active) subscriptions query only the past 15 days of trades — 360 elapsed hours, including weekends and holidays. The existing 15-minute delay remains.

    • Older trades are excluded before joins and aggregations. A query spanning the boundary includes only eligible trades; an older-only row query returns no rows.
    • Update queries that use older dates to target recent dates. Paid success responses include meta.lookback_days: 15.
    • Trial access, row limits, and synthetic test-mode samples are unchanged.
  16. FixedRealtime WebSocketAug 19, 2026

    Connection-limit retries are now protected

    When an API token already has five concurrent realtime connections, a new WebSocket or SSE handshake now returns HTTP 429 with Retry-After while existing connections remain open.

    • Respect Retry-After and use exponential backoff before retrying. Close unused connections so one token stays within its five-connection limit.
    • The server no longer evicts an existing connection when a sixth handshake arrives.
  17. FixedHistorical SQLAug 15, 2026

    Numeric overflow now returns an actionable query error

    Historical SQL expressions that exceed the supported numeric range now return HTTP 422 with errorCode = INVALID_QUERY and reason = NUMERIC_OVERFLOW instead of HTTP 500.

    • Cast fixed-precision operands before multiplying or aggregating them; for example, use SUM(toFloat64(price) * size * 100) for premium calculations.
    • The response remains privacy-safe and does not include the submitted SQL or database-internal error text.
  18. FixedHistorical SQLAug 13, 2026

    Invalid Historical SQL now returns INVALID_QUERY

    Queries with unknown columns, functions, aliases, or incompatible data types now return HTTP 422 with errorCode = INVALID_QUERY instead of HTTP 500.

    • The response now includes a privacy-safe reason such as UNKNOWN_IDENTIFIER plus an actionable errorMsg, without exposing database-internal text.
    • Correct the SQL before retrying. Use errorCode to distinguish INVALID_QUERY from QUERY_TOO_BROAD, QUERY_TIMEOUT, and INTERNAL_ERROR.
  19. AddedGeneralAug 10, 2026

    Bearer authentication added to HTTP data APIs

    Historical SQL and Option Chain now accept API keys through Authorization: Bearer, matching Market Structure.

    • Send Authorization: Bearer YOUR_API_KEY using the API key generated in the OptionData portal.
    • The api_key field in a JSON or form body remains supported for backward compatibility when the Authorization header is absent.
    • When Authorization is present, it takes precedence over api_key. Unsupported authentication schemes or invalid header formatting return HTTP 401.
  20. ChangedHistorical SQLBreakingAug 10, 2026

    Stable Historical SQL execution errors

    Historical SQL execution failures now return consistent HTTP statuses, error codes, and messages.

    • Queries that scan too much data return HTTP 422 with errorCode = QUERY_TOO_BROAD. Add narrower date, symbol, or other filters before retrying.
    • Execution timeouts return HTTP 504 with errorCode = QUERY_TIMEOUT.
    • Unexpected execution failures return HTTP 500 with errorCode = INTERNAL_ERROR.
  21. FixedOption ChainAug 10, 2026

    Option Chain as_of timestamp corrected

    Option Chain meta.as_of now reports the correct UTC timestamp for the latest data included in the response.

    • Previous values could be shifted by four or five hours. The correction applies automatically and requires no client changes.
    • The response shape is unchanged: meta.as_of remains a nullable UTC ISO 8601 string.
  22. ChangedHistorical SQLBreakingAug 10, 2026

    Minimum 15-minute data delay enforced

    Historical SQL now returns only trades whose execution timestamps are at least 15 minutes old.

    • The cutoff applies to all Historical SQL queries, including nested queries, joins, and aggregations.
    • At 10:00:00 ET, the newest visible execution timestamp is 09:45:00 ET. Data can be older than 15 minutes, but never newer than the minimum delay.
    • Success metadata now includes meta.minimum_data_delay_minutes = 15 and the matching X-OptionData-Historical-Sql-Minimum-Data-Delay-Minutes response header.
    • Use the Realtime WebSocket API when current-session trades are needed without the historical cutoff.
  23. AddedMarket StructureJul 27, 2026

    Intraday GEX summary and update time

    Added a nullable five-minute full-chain GEX summary and its update timestamp to v1 responses.

    • Successful responses now include data.intraday_gex: { spot, call_gex, put_gex } | null and meta.intraday_gex_as_of: string | null.
    • During the regular session, flow and intraday GEX can refresh every five minutes. GEX includes zero-trade contracts; flow fields continue to include traded contracts only.
    • structure_as_of identifies when strike GEX, walls, Gamma Flip, Max Pain, OI, and expirations were last calculated. These values do not refresh with the five-minute flow update.
    • This is an additive v1 schema change; existing structure and flow fields retain their meaning.
  24. AddedMarket StructureJul 24, 2026

    Market Structure API response schema v1

    Added the v1 success and error contracts for full-chain symbol snapshots.

    • New endpoint: GET /api/v1/market-structure/:symbol. Authenticate with Authorization: Bearer YOUR_API_KEY; add date=YYYY-MM-DD for a retained historical snapshot.
    • Successful responses use { data: { symbol, symbol_meta, structure, flow }, meta: { effective_date, structure_as_of, flow_as_of } }.
    • Errors use { error: { code, message } }. Stable codes include INVALID_REQUEST, UNAUTHORIZED, SUBSCRIPTION_REQUIRED, SNAPSHOT_NOT_FOUND, SYMBOL_NOT_FOUND, RATE_LIMITED, UPSTREAM_UNAVAILABLE and INTERNAL_ERROR.
    • The data and meta objects include call/put GEX by strike and expiration, GEX/OI walls, Gamma Flip and Max Pain by scope, plus the latest options-flow metrics.
    • Symbol metadata is self-contained: underlying type, description, exchange, sector, market cap, shares, earnings, prices, average volume, historical volatility, IV30, IV Rank/Percentile, skew, butterfly, and term slope.
    • Put GEX is signed negative. Net GEX, gross GEX, put/call ratios, and gamma regime are intentionally derivable from the strike data rather than duplicated in the payload.
  25. ChangedOption ChainBreakingJul 9, 2026

    Option Chain response schema simplified

    Breaking change: successful responses now use { data, meta: { trading_date, as_of } }, while errors use { error: { code, message } }.

    • meta.trading_date is the returned market session. meta.as_of is the latest data update represented in the response, formatted as a UTC ISO 8601 timestamp; it can be null when unavailable.
    • Contract rows removed symbol, expiry_days and mark. close was renamed to last_price; strike and expiration_date are now non-null fields.
    • Removed response fields status, api_version, beta, notice, entitlement, source, returned, filters and statistics. The test_mode request parameter was also removed.
    • Errors now provide a stable code and message. Codes include INVALID_REQUEST, UNAUTHORIZED, SUBSCRIPTION_REQUIRED, REQUEST_TOO_BROAD, RATE_LIMITED, INTERNAL_ERROR and QUERY_TIMEOUT.
    • Migration: read data directly instead of checking status === "SUCCESS"; replace meta.date with meta.trading_date, and replace close with last_price.
    • Requests whose result exceeds the maximum supported chain size return HTTP 422 with REQUEST_TOO_BROAD instead of partial data.
  26. ChangedHistorical SQLJul 3, 2026

    Historical SQL validation rules expanded

    Unsupported multi-table and table-function query forms now return validation errors.

    • Comma-separated joins such as FROM table_a, table_b are rejected.
    • Use the documented table names without a database prefix; references to other databases are rejected.
    • Table functions such as url(), remote(), and merge(), plus # comments, are rejected.
    • The documented single-table SELECT examples are unaffected.
  27. AddedOption ChainJul 1, 2026

    Strike price filters

    Added strike filtering to the Option Chain request.

    • New request parameters: strike for an exact match, plus strike_min and strike_max for an inclusive range.
    • strike cannot be combined with strike_min or strike_max.
    • Each value can be sent as a number or as a numeric string in a form-encoded request.
  28. RemovedOption ChainBreakingJun 26, 2026

    Removed the limit request parameter

    The API no longer accepts a client-supplied limit parameter.

    • Use date, expiration_date, put_call, strike, strike_min, or strike_max to narrow a symbol request.
    • As of July 9, 2026, requests that exceed the maximum response size return an error instead of partial data.
  29. RemovedOption ChainBreakingJun 25, 2026

    Removed strike and expiry range parameters

    Removed the older strike and expiry range parameters.

    • Removed request parameters: min_strike, max_strike, min_expiry_days, and max_expiry_days.
    • Strike filtering returned on July 1, 2026 through strike, strike_min, and strike_max.
  30. RemovedOption ChainBreakingJun 25, 2026

    Removed flow fields and include_flow

    The optional flow fields and the include_flow toggle were removed from the response.

    • Removed the include_flow request parameter and the premium, size, trade_count, latest_trade_price, latest_trade_time, and vol_oi_ratio response fields.
    • At the time of this change, close continued to provide the latest trade price for each contract.
  31. ChangedGeneralBreakingJun 22, 2026

    API base URL moved to www

    The canonical API host is now the www subdomain.

    • The base URL is now https://www.optiondata.io; it was previously https://optiondata.io.
    • Update requests to POST /api/historical/sql and POST /api/option-chain to use the new base URL.
  32. AddedOption ChainJun 21, 2026

    Beta metadata in responses

    Every Option Chain response now advertises its beta status.

    • Responses include meta.api_version = "v1", meta.beta = true, and meta.notice.
    • Responses also include X-OptionData-Option-Chain-Beta: true.
    • These beta fields were later removed by the July 9, 2026 response schema change.
  33. FixedRealtime WebSocketMar 5, 2026

    Corrected the documented sentiment value

    The documented neutral sentiment value is NEUTRAL.

    • Use NEUTRAL. The previous documentation misspelled the value as NEUTRUAL.
  34. RemovedRealtime WebSocketBreakingFeb 24, 2026

    Removed realtime trade-data fields

    Several fields were dropped from real-time trade messages.

    • Removed fields: bid_size, ask_size, vega, theta, rho, and exchange.

This changelog covers data-API schema and contract changes. For product, billing, and platform updates, see the blog.