1. API
  2. Historical options data

Historical options data

Any past close,
priced as it was.

End-of-day option chains for past trade dates, with the closing bid and ask, per-contract IV, the Greeks, volume and open interest. Next to them, the daily history behind IV rank, realized vol, skew and earnings moves. One Bearer token, JSON back.

Included with every paid plan; there is no free API tier. 7 days free, card required.

10Endpoints on this page
7Matching MCP tools
60/minPer token, 1,000 an hour

A real response

This is what
comes back.

How was SPY's 21 August chain priced at the close on 14 August? Captured from the live endpoint on 2026-09-08, lists cut to a few rows so it fits on a page. The shape is exactly what your code receives. The endpoint page has every parameter and field.

GET /api/mcp/data/chain-at-time/SPY?expiration=2026-08-21&trade_date=2026-08-14200, application/json
{
  "calls": [
    {
      "ask": 4.75,
      "bid": 4.69,
      "delta": 0.5747,
      "epsilon": -0.0857,
      "expiration": "2026-08-21",
      "gamma": 0.0436,
      "implied_vol": 0.0895,
      "open_interest": 54326,
      "rho": 0.0848,
      "right": "C",
      "strike": 775,
      "theta": -0.3008,
      "underlying_price": 776.07,
      "vega": 0.4203,
      "volume": 6045
    },
    {
      "ask": 4.14,
      "bid": 4.12,
      "delta": 0.5315,
      "epsilon": -0.0792,
      "expiration": "2026-08-21",
      "gamma": 0.0452,
      "implied_vol": 0.0885,
      "open_interest": 5227,
      "rho": 0.0785,
      "right": "C",
      "strike": 776,
      "theta": -0.2954,
      "underlying_price": 776.07,
      "vega": 0.4277,
      "volume": 8446
    },
    {
      "ask": 3.59,
      "bid": 3.57,
      "delta": 0.486,
      "epsilon": -0.0724,
      "expiration": "2026-08-21",
      "gamma": 0.0462,
      "implied_vol": 0.0874,
      "open_interest": 5722,
      "rho": 0.0718,
      "right": "C",
      "strike": 777,
      "theta": -0.2877,
      "underlying_price": 776.07,
      "vega": 0.427,
      "volume": 15012
    }
  ],
  "expiration": "2026-08-21",
  "puts": [
    {
      "ask": 3.13,
      "bid": 3.12,
      "delta": -0.4253,
      "epsilon": -0.0857,
      "expiration": "2026-08-21",
      "gamma": 0.0436,
      "implied_vol": 0.09,
      "open_interest": 6989,
      "rho": -0.0637,
      "right": "P",
      "strike": 775,
      "theta": -0.3008,
      "underlying_price": 776.07,
      "vega": 0.4203,
      "volume": 17977
    },
    {
      "ask": 3.55,
      "bid": 3.53,
      "delta": -0.4685,
      "epsilon": -0.0792,
      "expiration": "2026-08-21",
      "gamma": 0.0452,
      "implied_vol": 0.0889,
      "open_interest": 1969,
      "rho": -0.0702,
      "right": "P",
      "strike": 776,
      "theta": -0.2954,
      "underlying_price": 776.07,
      "vega": 0.4277,
      "volume": 8064
    },
    {
      "ask": 4.0,
      "bid": 3.98,
      "delta": -0.514,
      "epsilon": -0.0724,
      "expiration": "2026-08-21",
      "gamma": 0.0462,
      "implied_vol": 0.0877,
      "open_interest": 2999,
      "rho": -0.0771,
      "right": "P",
      "strike": 777,
      "theta": -0.2877,
      "underlying_price": 776.07,
      "vega": 0.427,
      "volume": 8247
    }
  ],
  "ticker": "SPY",
  "time_of_day": "EOD",
  "trade_date": "2026-08-14",
  "underlying_price": 776.07
}

Every response is wrapped as {"success": true, "data": {...}}. Errors use the same envelope with an error string and a status code that means what it says.

Call it three ways. Same token, same JSON.

curlBearer token from Account, then API Access
curl -H "Authorization: Bearer avmcp_YOUR_TOKEN" \
     "https://apexvol.com/api/mcp/data/chain-at-time/SPY?expiration=2026-08-21&trade_date=2026-08-14"
Pythonrequests, nothing else
import requests

headers = {"Authorization": "Bearer avmcp_YOUR_TOKEN"}
params = {"expiration": "2026-08-21", "trade_date": "2026-08-14"}
r = requests.get("https://apexvol.com/api/mcp/data/chain-at-time/SPY", headers=headers, params=params)
r.raise_for_status()
data = r.json()["data"]
print(data["underlying_price"])
In Claude, Cursor or ChatGPTthrough the MCP server, no code
You

Show the SPY chain for 21 August as it was priced on 14 August.

The assistant calls get_historical_chain and answers from the JSON above.

Endpoints that read history

10 endpoints,
one prefix.

All under https://apexvol.com/api/mcp/data. The historical chain first, then the endpoints built on daily history: IV against realized vol, realized-vol regimes, skew, IV rank, the cone, past moves and earnings. Each card opens a page with the parameters and their bounds, every response field and a real captured response.

GET /chain-at-time/{ticker} How was SPY's 21 August chain priced at the close on 14 August? The end-of-day chain snapshot for a past trade date. Pro GET /vrp/{ticker}/timeseries How has the gap between NVDA's implied and realized vol moved over the last few months? Daily IV, realized vol and their difference through time. Premium GET /hv-regimes/{ticker} What realized-vol regime is NVDA in, and are the short windows above or below the long ones? Historical volatility across windows, its term structure and the regime crossovers. Premium GET /skew/{ticker} How steep is NVDA's put skew today compared with its own history and its sector? Put-call skew slope, curvature and the percentile of today's skew. Pro GET /iv-rank/{ticker} Is NVDA's implied volatility high or low for NVDA right now? IV rank and IV percentile against the last year, with the range they were measured on. Premium GET /volatility-cone/{ticker} How does NVDA's implied vol at each tenor compare with what the stock has actually realized over the same windows? A realized-volatility cone per tenor next to the chain IV at the same tenor. Premium GET /historical-moves/{ticker} How big a move does NVDA typically make over 7, 14, 21 and 30 days? The distribution of past moves per horizon. Pro GET /earnings-history/{ticker} How much has NVDA moved on each of its last eight reports? Per-report moves, surprises and IV crush, with the statistics. Pro GET /post-earnings-drift/{ticker} After NVDA gaps on earnings, does the move continue or fade? Drift after the earnings gap over 1 to 20 days, split by gap direction. Pro GET /seasonality/{ticker} Which months have historically been strongest and weakest for NVDA? Average and median returns and volatility by month and quarter. Pro

Depth and grain

What is kept,
and how far back.

Grain
End of day. Each past chain is the close of one trading day; there are no intraday snapshots for past sessions.
What a past chain holds
One expiration per call: calls and puts with bid, ask, implied_vol, delta, gamma, theta, vega, rho, volume and open_interest, plus the underlying price that day. Contracts that have since expired are included.
How far back
The end-of-day chain archive starts in 2007. Each symbol's history starts when its options did, so newer listings go back less far.
The latest session
A trading day appears once the feed finalizes it overnight. Until then a request for it returns 404, as does a weekend or a market holiday.
Daily series
Daily IV against realized vol for up to 504 trading days, realized-vol regimes and skew history for up to 1,000, IV rank over up to 1,260, and monthly seasonality over up to 10 years.
Earnings history
Up to 40 past reports per call: the gap move, the EPS surprise, IV before and after the report, and the drift over the following days.

Before you build

What it
does not do.

No list of past expirations
GET /expirations lists today's expirations only. For a past date, pass an expiration you know was listed, such as a monthly third Friday. One that was not listed that day comes back with empty calls and puts.
Renamed tickers
The API only accepts symbols that are listed today, and a renamed ticker's older history can sit under its old symbol. The known case is QQQ before 23 March 2011, which the archive files as QQQQ, so that stretch is out of reach.
One day per call
Each chain call returns one ticker, one trade date and one expiration. A backtest walks the dates one call at a time, inside 60 calls a minute and 1,000 an hour per token and the monthly allowance.
No tick data
There are no past trades, quotes or time and sales, and no intraday history. Volume and open interest are daily figures.
Plans
Historical chains are a Pro endpoint. The daily IV, realized-vol, IV rank and cone history start on Premium; skew history, past moves, earnings history, drift and seasonality are Pro.

The same data, in plain English

7 MCP tools
cover these endpoints.

Connect the ApexVol MCP server and Claude, ChatGPT, Cursor or another MCP client calls these by name. Add it from Claude's connector directory or paste https://apexvol.com/mcp-server; it signs in to your ApexVol account, so there is no token to paste.

  • get_historical_chain
  • get_volatility_risk_premium
  • get_ticker_analytics
  • get_iv_rank
  • get_volatility_cone
  • get_earnings_move_analysis
  • analyze_earnings_history

Set it up in:

Ready-made questions for every family in the prompt library.

What people build

3 things
this is for.

Access, limits and price

Who can call it
Accounts on a paid plan or a trial. There is no free API tier: a token needs an active plan, and a token whose plan lapses stops working until the plan is active again.
Auth
Bearer token, prefix avmcp_, created under Account, then API Access. Shown once, hashed at rest, rotates in one click.
Rate limits
60 requests a minute and 1,000 an hour per token. Every response carries the remaining counts in headers, and a 429 carries Retry-After.
Monthly allowance
10,000 data requests a month per account on every plan, 75,000 on a paid Pro plan (trials use 10,000). Most calls cost 1; GET /me/usage shows what is left and costs nothing. How it is counted.
Plans
Basic, $55 a month, reaches 18 of 64 endpoints; Premium, $95, reaches 42; Pro, $195, reaches all 64. Each endpoint follows the plan of its feature in the web app, and every card and endpoint page shows which. Compare plans.
Use of the data
For your own analysis, models and tools. The terms do not allow redistributing or reselling API data to third parties.
Spec
OpenAPI 3.1 at /docs/api/openapi.json, the whole reference as one Markdown file at /llms-full.txt. Shared conventions, the error model and the changelog.

Questions

Asked before
the first call.

How far back does the historical options data go?

The end-of-day chain archive starts in 2007, and each symbol's history starts when its options began trading. The daily series are bounded per call: up to 504 trading days for IV against realized vol, and up to 1,000 for realized-vol regimes and skew history.

Is intraday historical data available?

No. Past chains are end-of-day snapshots, one per trading day. Intraday data covers the current session only, through the live chain endpoint.

Does the historical chain include bid and ask?

Yes. Each row carries the closing bid and ask next to the implied volatility and the Greeks, so a backtest can price fills at the quote instead of guessing from a mid.

What does a backtest cost against the allowance?

Plan on one data request per ticker per trading day you read. Calls are capped at 60 a minute and 1,000 an hour per token, and GET /me/usage shows what is left of the month before a long run.

Which plan includes historical chains?

Pro. The daily IV, realized-vol and IV rank history is on Premium. Every plan starts with a free trial that includes the API; a trial uses the standard allowance, and the larger paid Pro allowance starts once the first charge goes through.

Can I download the whole archive?

No. The API answers one ticker, date and expiration per call, inside the rate limits and the monthly allowance, and the terms do not allow redistributing the data. It suits backtests and research on the names you trade, not a bulk copy of the archive.

Past chains
come with Pro.

Historical chains are on Pro, and the daily IV and realized-vol history starts on Premium. Pro is $195 a month, with a 7-day trial, card required.

API and MCP access need a paid or trial plan.