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

expiries answers with a full timestamp (2026-09-25T08:00:00Z), while
chain wants a plain date (expiry=2026-09-25). Feeding the timestamp
straight back gives 400 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

EndpointReturns
GET /api/v1/options/marketscontract catalog; ?underlying=, ?status=
GET /api/v1/options/markets/{symbol}one contract with its full spec
GET /api/v1/options/markets/{symbol}/orderbookdepth snapshot for one contract
GET /api/v1/options/markets/{symbol}/tradesthat contract's tape
GET /api/v1/options/trades?underlying=BTC-USDCmerged 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.


Did this page help you?