Lab API Historical API
Alpha · Historical API Replay

Historical API: Point-in-Time Replay

Ask what GEX, gamma flip, VRP, narrative, max pain, or the full stock summary looked like at any minute in history - returned in the same response shape as the live API. Backed by 6.7 B option rows since April 2018.

What's different from the live API

Every endpoint you already know on the live API is mirrored here. Point your existing SDK at a different host, add one query parameter, and you have a backtest-ready data source. No new response shapes to learn - GEX, gamma flip, regime labels, narrative text, VRP percentiles, SVI surfaces and everything else come back in the exact same JSON you already parse.

The analytics run through the same code path as live - so any fix or refinement that lands on api.flashalpha.com shows up here on the next deploy. The only difference is the data store underneath: minute-level quotes and greeks going back to April 2018 instead of the live feed.

Host
historical.flashalpha.com
Auth
Same X-Api-Key as live. Alpha tier on every endpoint.
Quota
Shared with live daily bucket.

The at parameter

Every analytics endpoint takes a required at query parameter - the as-of timestamp. Treated as ET wall-clock (same clock as the stored data). Do not shift by UTC offset.

FormatExampleSemantics
yyyy-MM-ddTHH:mm:ss2026-03-05T15:30:00Minute-level as-of
yyyy-MM-dd2026-03-05Defaults to 16:00 ET (session close)

Intraday-accurate vs EOD-stamped

Not every underlying series is minute-resolution. Here's what moves at the minute you ask for, and what's stamped at the close of that trade day:

Data layerGranularityNotes
Option quotes + greeks (bid, ask, iv, δ, γ, θ, ν, ρ, vanna, charm)1 minute (9:30 → 16:00 ET)Last value per contract at or before at
Stock spot (bid, ask, mid)1 minuteSame
Open interestEODOne value per trade day, applied to all intraday at= on that day
SVI params, forward pricesEOD
Macro: VIX, VVIX, SKEW, MOVE, SPX, VIX9D/3M/6M, DGS10EOD
Realized-vol lookback closes (HV20/HV60)EODLast tick per day

Why this is OK: intraday GEX / DEX / VEX / CHEX shifts are driven by greek + spot changes; OI is dealer-positioning context and barely moves intraday anyway.

Coverage: GET /v1/tickers

The only historical-specific endpoint. Lists every symbol with historical coverage, the date range, and any gaps. Regenerated after every backfill run, so whatever comes back is the current ground truth for what you can query.

GET https://historical.flashalpha.com/v1/tickers

Auth: required (X-Api-Key, Alpha tier)

Query params: symbol=SPY (optional) - returns a single object instead of the wrapped list

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://historical.flashalpha.com/v1/tickers"

Response 200:

{
  "count": 1,
  "tickers": [
    {
      "symbol": "SPY",
      "coverage": {
        "first": "2018-04-16",
        "last":  "2026-04-02",
        "total_days": 2909,
        "healthy_days": 1972
      },
      "tables": {
        "stocks_days":    2009,
        "options_days":   1972,
        "option_eod_days": 2006,
        "svi_days":        1972
      },
      "gaps": {
        "missing_eod": 3,
        "missing_svi": 36,
        "uncovered_calendar": 3
      },
      "updated_at": "2026-04-14T07:07:36.55353"
    }
  ]
}
FieldMeaning
coverage.first / coverage.lastDate range where every data layer is healthy - you can query any minute inside this window
coverage.healthy_daysTrading days on which every data layer has data
tables.*_daysPer-layer day counts - useful when a single layer is lagging
gaps.missing_eodDays where EOD option data hasn't been pulled yet (usually resolves on the next backfill)
gaps.missing_sviDays without an SVI fit
gaps.uncovered_calendarNYSE trading days that were never pulled (genuine exchange-closed days like 2018-12-05 Bush funeral, 2025-01-09 Carter funeral)
updated_atUTC timestamp of the last coverage refresh

Available symbols. SPY is fully backfilled from 2018-04-16 through 2026-04-02 and extended on every refresh. Additional symbols are backfilled on demand - ask us to prioritize what you need. Live coverage is always queryable at GET /v1/tickers.

Analytics endpoints

Every live analytics endpoint is mirrored with the addition of a required at. Paths, query params, and response shapes are identical to the live docs - don't re-document them here. Click through for the per-endpoint reference:

VRP date-bounding matters. VRP percentile and z-score only consider history prior to at, so at any historical point the percentile reflects only what was knowable at that moment. No future leakage in backtests.

Example: replay March 16, 2020 (COVID crash, -12% close)

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://historical.flashalpha.com/v1/exposure/summary/SPY?at=2020-03-16T15:30:00"
{
  "symbol": "SPY",
  "underlying_price": 246.01,
  "as_of": "2020-03-16T15:30:00",
  "gamma_flip": 270.92,
  "regime": "negative_gamma",
  "exposures": {
    "net_gex":  -2633970601,
    "net_dex": -169419489077,
    "net_vex":  152461756844,
    "net_chex":   -13122349
  },
  "interpretation": {
    "gamma":  "Dealers short gamma - moves amplified, trend following likely",
    "vanna":  "Vol up = dealers buy delta - downside dampened if vol spikes",
    "charm":  "Time decay pushing dealers to sell - pressure into close"
  }
}

Real dealer positioning, at 15:30 ET on the day SPY closed -12%. Not a re-derived reconstruction - these are the minute-level greeks as they were at that moment, run through today's analytics.

Field coverage vs live

Most fields are identical to the live API. These are the exceptions:

FieldStatus on historicalWhy
optionquote.bidSize, askSize, volumeAlways 0Minute-resolution quotes don't carry sizes or volume
optionquote.svi_volAlways null with svi_vol_gated: "backtest_mode"SVI surface available via /v1/adv_volatility; per-contract derivation not yet exposed
exposure.call_volume, put_volumeAlways 0No minute volume stored
exposure.call_oi_change, put_oi_changeAlways nullPrior-day OI comparison not yet computed
narrative.data.top_oi_changesAlways []Same - per-strike prior-day OI diff not computed
0DTE intraday greeks (δ/γ/θ/iv on zero-dte.strikes[])Often 0/nullMinute-level greeks on very-near-expiry contracts are still being backfilled; the strike distribution / OI is available
summary.options_flow.total_*_volume, pc_ratio_volumeAlways 0 / nullNo minute volume stored
summary.macro.vix_futures, fear_and_greedAlways nullCME VIX futures curves and CNN Fear & Greed aren't archived historically
vrp.macro.hy_spreadHard-coded 3.5Historical high-yield spread series isn't loaded yet

Everything else - greeks, IV, exposures, flip, walls, regime, narrative, VRP percentiles, SVI fits, variance surface, arbitrage flags - is real, computed from the data as it stood at at.

How coverage grows

New trading days and new symbols are added by a gap-aware backfill that runs on a schedule. The coverage window on /v1/tickers is what you can query right now; it extends forward on each refresh. Transient upstream misses self-heal on subsequent runs, so a gap you see today may fill in later - check /v1/tickers before concluding that a specific date is unavailable.

Latency & caching

Point-in-time reads are fast (~50–300 ms typical). Composite endpoints that rebuild surfaces on demand - /v1/adv_volatility and /v1/stock/{symbol}/summary - can take ~500–1500 ms on a cold request for a new (symbol, at). Cache at your proxy or client for repeat queries on the same tuple - responses are deterministic for a given at, so they're safe to cache indefinitely.

Try it live

Point-and-replay - pick an endpoint, pick a minute in history, hit Replay. Works with your existing API key.

Ready to build?

Get your free API key and start pulling live options data in 30 seconds.