Options: market data
Underlyings, expiries, the chain with Greeks, per-contract book and tape, and why quotes are often one-sided.
All options market data is public. Start from the underlying, narrow to an expiry, then pull the chain.
Underlyings and expiries
curl -s https://api-mainnet.1024ex.com/api/v1/options/underlyings
curl -s "https://api-mainnet.1024ex.com/api/v1/options/expiries?underlying=BTC-USDC"underlyings returns perp-style symbols (BTC-USDC, AAPL-USDC, …) — the same strings you pass to ?underlying= everywhere else. Pass them whole: underlying=BTC is accepted and answers with an empty list rather than an error, which reads like "no options listed" when the real answer is "wrong symbol". The listing is generated by a follow-the-spot lister that keeps at-the-money strikes stocked as the underlying moves, so it changes through the day: enumerate, don't hard-code.
The chain
The two endpoints disagree on date format
expiriesanswers with a full timestamp (2026-09-25T08:00:00Z), while
chainwants a plain date (expiry=2026-09-25). Feeding the timestamp
straight back gives400 Failed to deserialize query string: trailing input.
Truncate to the first 10 characters.
curl -s "https://api-mainnet.1024ex.com/api/v1/options/chain?underlying=BTC-USDC&expiry=2026-09-25"expiry is optional (YYYY-MM-DD, UTC); omitting it returns every listed expiry. The response carries the spot reference alongside the contracts:
{
"underlying": "BTC-USDC",
"indexPriceE6": 86134550000,
"contracts": [
{
"symbol": "BTC-20260925-81000-C",
"optionType": "call",
"strikePriceE6": 81000000000,
"expiryTime": "2026-09-25T08:00:00Z",
"markPriceE6": 5242947379,
"markIvE6": 383619,
"bestBidE6": 5059030000,
"bestAskE6": 5426870000,
"openInterestE6": 0,
"volume24hE6": 0,
"changePct24h": -2.54,
"delta": 0.9734,
"gamma": 2.19e-11,
"vega": 451733761.4,
"thetaPerDay": -32838851.0,
"greeksStructure": "capped_call_spread",
"tickSizeE6": 10000,
"lotSizeE6": 1000,
"minNotionalE6": 1000000
}
]
}The chain is the endpoint to build a screen on: it is one request per underlying, and it already contains the mark, the IV, the top of book, the Greeks and the trading grid. Polling per-contract endpoints across a chain will exhaust your read budget for no extra information.
bestBidE6 / bestAskE6 are frequently null or one-sided, and that is expected. Quoting floors and the tick grid mean a contract priced below roughly $0.11 cannot show both sides, and near-expiry deep-out-of-the-money contracts often have a mark below one tick. An empty book does not mean the contract is untradable — it means there is no resting size right now. Price against markPriceE6, and bound your execution with maxSlippageBps.
Contracts, book and tape
| Endpoint | Returns |
|---|---|
GET /api/v1/options/markets | contract catalog; ?underlying=, ?status= |
GET /api/v1/options/markets/{symbol} | one contract with its full spec |
GET /api/v1/options/markets/{symbol}/orderbook | depth snapshot for one contract |
GET /api/v1/options/markets/{symbol}/trades | that contract's tape |
GET /api/v1/options/trades?underlying=BTC-USDC | merged tape across every contract on one underlying |
GET /api/v1/options/markets excludes settled and cancelled contracts by default — pass ?status=settled to see history. The merged-tape form is the efficient way to watch flow on an underlying without subscribing per strike.
A worked screen
Find every BTC contract expiring on a given date whose mark is inside the book and whose delta is in a band:
import requests
BASE = "https://api-mainnet.1024ex.com"
chain = requests.get(f"{BASE}/api/v1/options/chain",
params={"underlying": "BTC-USDC", "expiry": "2026-09-25"}).json()["data"]
spot = chain["indexPriceE6"] / 1e6
for c in chain["contracts"]:
if not (0.2 <= abs(c["delta"]) <= 0.4):
continue
mark = c["markPriceE6"] / 1e6
bid = (c["bestBidE6"] or 0) / 1e6
ask = (c["bestAskE6"] or 0) / 1e6
print(f"{c['symbol']:<28} mark {mark:>10.2f} bid {bid:>10.2f} ask {ask:>10.2f} "
f" iv {c['markIvE6']/1e6:>6.1%} delta {c['delta']:>6.3f}")Real-time
There is no options WebSocket channel today — the streaming channels cover perps and prediction markets. For options, poll the chain at a cadence your read budget supports (the mark refreshes on the order of a second) and drive position state from GET /api/v1/options/positions.
Updated 9 days ago
