A Massive options ticker follows the OCC standard with an O: prefix, and it is four fields joined with no separators. Reading O:SPY260918C00650000 left to right: the underlying is SPY, the expiry is 260918 for 18 September 2026, C means call, and 00650000 is the strike in thousandths of a dollar, so 650. The two things that catch people are that the strike is multiplied by 1,000 and that both the date and the strike are zero-padded to a fixed width.
Applies to
- Plans: an Options subscription for the data; the symbol format itself applies everywhere.
- Endpoints: every options endpoint takes this ticker, including /v3/trades, /v3/quotes, /v2/aggs and the snapshots.
- Asset classes: US-listed options, on both equities and indices.
The four parts
The four parts run left to right with no separators between them:
| Part | Width | Example | Meaning |
|---|---|---|---|
| Underlying | 1 to 6 characters | SPY | The root symbol, left-aligned and not padded |
| Expiry | 6 digits | 260918 | Year, month, day |
| Type | 1 character | C | C for a call, P for a put |
| Strike | 8 digits | 00650000 | The strike times 1,000, zero-padded |
To get the strike back, divide the last eight digits by 1,000. 00650000 is 650, 00003000 is 3, and 07600000 is 7,600.
How to build one
curl -X GET "https://api.massive.com/v3/reference/options/contracts/O:SPY260911C00500000?as_of=2026-09-11&apiKey=YOUR_API_KEY"
Response
{
"results": {
"contract_type": "call",
"exercise_style": "american",
"expiration_date": "2026-09-11",
"primary_exchange": "BATO",
"shares_per_contract": 100,
"strike_price": 500,
"ticker": "O:SPY260911C00500000",
"underlying_ticker": "SPY"
},
"status": "OK"
}
Reading that one back: SPY, expiring 260911, a C for call, and 00500000 for a strike of 500. That contract has since expired, which is why the request passes as_of=2026-09-11, its expiration date: without as_of the contract overview endpoint looks the contract up as of today, and an expired contract comes back as HTTP 404 with Option Ticker not found. rather than its details.
Build the ticker from the reference endpoint rather than assembling the string yourself. Padding mistakes are silent on the data endpoints: a wrongly padded strike is a well-formed ticker for a contract that does not exist, so the trades and aggregates endpoints return an empty result rather than an error. The contract overview endpoint above answers the same ticker with HTTP 404 and Option Ticker not found., so it can check a ticker you built by hand, with as_of set to a date on or before the expiration.
Index options and adjusted contracts
Two variations are worth recognizing. An index option uses the index root without a prefix inside the ticker, so an S&P 500 weekly is O:SPXW260915C07600000, where SPXW is the root rather than SPX with something appended. And a contract adjusted after a corporate action often carries a digit after the underlying, as in O:GME1261016C00003000, which marks it as a different series from the standard O:GME... contracts.
Why the strike is in thousandths
The strike is an integer in thousandths because the format is fixed width and has to hold strikes from cents to tens of thousands without a decimal point or a variable length. Storing 650 as 00650000 lets one eight-character field carry 00003000 for a three-dollar strike and 07600000 for a 7,600-point index strike, and it means tickers sort correctly as plain text.
If you see an error
An empty results array for a ticker you built by hand is almost always the padding. Count the digits: six for the date, eight for the strike.
Option Ticker not found. with HTTP 404 from the contract overview endpoint means the same padding mistake, or a contract that had already expired on the as_of date, which is today unless you set it.
A contract that exists on another vendor but not here may be an adjusted series. Look for the same expiry and strike with a digit after the underlying.
A strike that comes back a thousand times too large or too small is the multiplier. The ticker carries thousandths; the strike_price field carries the real number.

