Historical Options Data API — OHLC Bars by Contract
The /mas endpoints mirror Massive’s aggregates API: historical
OHLC bars for individual option contracts at any resolution from one second
to one year, plus a daily open/close lookup. This is the time dimension the
live snapshot doesn’t have — use it for
candlestick charts, premium-decay studies, and backtest-style analysis of specific
contracts.
Requires the Research plan (the aggregates feature).
Other plans receive 402 with an upgrade pointer — see
plans & limits.
Endpoints
| Route | What it returns |
|---|---|
GET /mas/v2/aggs/ticker/{ticker}/range/{multiplier}/{timespan}/{from}/{to} | OHLC bars over a date range (Massive v2 mirror) |
POST /mas/aggs | Same, with all arguments in a JSON body (the form cvApi.call uses) |
GET /mas/v1/open-close/{ticker}/{date} | One trading day’s open/high/low/close/volume (v1 mirror) |
POST /mas/open-close | Same, JSON body |
Calling it
// Daily bars for one SPY call over six months
const bars = await cvApi.call('/mas/aggs', {
ticker: 'O:SPY260116C00400000', // contract ticker from the chain's "ticker" field
multiplier: 1,
timespan: 'day',
from: '2026-01-02',
to: '2026-07-02',
});
// One day's open/high/low/close for the same contract
const day = await cvApi.call('/mas/open-close', {
ticker: 'O:SPY260116C00400000',
date: '2026-06-30',
}); curl -H "Authorization: Bearer cv_live_..." \
"https://tap.convexvalue.com/api/data/mas/v2/aggs/ticker/O:SPY260116C00400000/range/1/day/2026-01-02/2026-07-02?sort=asc"
curl -H "Authorization: Bearer cv_live_..." \
"https://tap.convexvalue.com/api/data/mas/v1/open-close/O:SPY260116C00400000/2026-06-30"
From a coding agent, the MCP tools are get_option_bars and
get_option_daily — see the MCP reference.
Parameters
| Parameter | Type | Description |
|---|---|---|
ticker required | string | An option contract ticker like O:SPY260116C00400000 — take it from the chain’s "ticker" field. Stock/ETF tickers also work for equity bars. |
multiplier required | integer | Size of the window in timespan units, e.g. 5 with "minute" = 5-minute bars. |
timespan required | string | One of: second, minute, hour, day, week, month, quarter, year. |
from / to required | string | Window bounds: YYYY-MM-DD or epoch milliseconds (inclusive). |
adjusted | boolean | Adjust for splits. Default true. |
sort | string | "asc" (oldest first) or "desc" (newest first) by timestamp. |
limit | integer | Max base aggregates used to build the response. Default 5,000, max 50,000. |
Response shape
The upstream JSON passes through unmodified. Each bar:
o/h/l/c open, high, low, close; v volume;
vw volume-weighted average price; n number of trades;
t the window’s start as an epoch-millisecond timestamp.
{
"ticker": "O:SPY260116C00400000",
"queryCount": 124,
"resultsCount": 124,
"adjusted": true,
"results": [
{ "o": 210.1, "h": 214.9, "l": 209.0, "c": 213.4, "v": 182, "vw": 212.33, "t": 1767330000000, "n": 24 }
],
"status": "OK"
} Notes
- Responses set
Cache-Control: private, max-age=15; the most recent day’s bar mutates intraday, older bars are effectively immutable. - Upstream not-found (an unknown or never-traded contract/date) surfaces as
404; other upstream failures as502. - Options contracts trade sparsely: expect gaps between bars for illiquid strikes — render against time, not bar index, or gaps will look like trends.
Get example prompts & new data guides
Occasional emails with prompts worth trying and what’s new in the data.