Crypto Options Data API: BTC, ETH, IBIT and MSTR | FlashAlpha
api · 9 min read

Crypto Options Data API: BTC, ETH, IBIT and MSTR

Endpoints, symbol conventions and tier requirements for pulling crypto options exposure across CME futures, spot ETFs and the equity proxies - with the gotchas that cost people a day.

T
Tomasz Dobrowolski Quant Engineer
Aug 17, 2026
9 min read
API Crypto Bitcoin BTC ETH IBIT MSTR COIN DeveloperGuide Python OptionsAPI GEX Black76

This is a developer reference rather than an analysis piece. For what the numbers mean, see crypto options dealer positioning.


Symbols

Two conventions, and mixing them up is the most common first error.

InstrumentSymbolConventionNotes
CME BitcoinBTC=FFutures, encode as BTC%3DF$5 / point, 5 BTC
CME EtherETH=FFutures, encode as ETH%3DF$50 / point, 50 ETH
Spot BTC ETFIBITPlain equity ticker100 shares / contract
Spot ETH ETFETHAPlain equity ticker100 shares / contract
ProxiesMSTR, COINPlain equity ticker100 shares / contract

The =F suffix disambiguates futures from equities. In REST paths the = must be URL-encoded as %3D. SDK methods take the plain string "BTC=F" and handle encoding for you.


Entitlements

Gating is by endpoint, not by symbol, with one symbol-level exception. Worth reading carefully, because "IBIT is just an equity" does not mean every call is available on every plan.

CallRequired plan
Any =F futures symbolGrowth or higher
GET /v1/exposure/gex/{symbol} full chainGrowth or higher
GET /v1/exposure/gex/{symbol}?expiration=All plans
GET /v1/exposure/summary/{symbol}Growth or higher
GET /v1/exposure/narrative/{symbol}Growth or higher
GET /v1/exposure/zero-dte/{symbol}Growth or higher
Any endpoint with ?expiration= set to today (0DTE)Growth or higher
svi_vol field on the surfaceAlpha or higher

A request below the required tier returns 403 with error: "tier_restricted" and required_plan: "Growth". Accounts created before 2026-03-20 are grandfathered for 0DTE access on their existing plan.

The useful workaround on lower plans: full-chain GEX is gated but single-expiry GEX is not. Passing ?expiration=yyyy-MM-dd for a non-0DTE date gives you the strike map for that expiry on any plan. For most positioning work a single monthly expiry is what you actually wanted anyway.

The Endpoints That Matter

# Aggregate exposure, one call, all greeks
GET /v1/exposure/summary/IBIT
GET /v1/exposure/summary/MSTR
GET /v1/exposure/summary/BTC%3DF

# Gamma by strike - walls, flip
GET /v1/exposure/gex/IBIT
GET /v1/exposure/gex/IBIT?expiration=2026-09-18
GET /v1/exposure/gex/BTC%3DF

# Other greeks
GET /v1/exposure/dex/MSTR              # delta
GET /v1/exposure/vex/MSTR              # vanna - dominant in MSTR
GET /v1/exposure/chex/MSTR             # charm

# Levels and context
GET /v1/levels/IBIT                    # key levels incl. max pain
GET /v1/stock/IBIT/summary             # incl. IV term structure

The summary endpoint returns net GEX, DEX, VEX and CHEX, the regime label, the gamma flip, a hedging estimate for a 1% move, and the 0DTE breakdown in a single response. If you are polling several symbols, prefer it over four separate greek calls - see one call versus separate endpoints.


Python

import requests

BASE = "https://api.flashalpha.com/v1"
HEADERS = {"X-API-Key": API_KEY}

def exposure(symbol: str) -> dict:
    # SDK-free: encode "=" for futures symbols, leave equities alone
    path = symbol.replace("=", "%3D")
    r = requests.get(f"{BASE}/exposure/summary/{path}", headers=HEADERS, timeout=10)
    r.raise_for_status()
    return r.json()

complex_ = ["IBIT", "ETHA", "MSTR", "COIN", "BTC=F"]

for sym in complex_:
    d = exposure(sym)
    gex = d["exposures"]["net_gex"]
    print(f"{sym:6} {d['regime']:16} net_gex ${gex:>14,.0f}  flip {d['gamma_flip']:,.2f}")

That loop is the whole cross-wrapper divergence check. When the regime column is not uniform across the complex, the wrappers disagree - which is the thing worth knowing.


Three Gotchas

1. Unencoded =. /v1/exposure/gex/BTC=F will not route as intended. Encode it as BTC%3DF. If you are building URLs by string concatenation this is the bug you will hit first.

2. Comparing contracts across wrappers. One CME bitcoin contract is 5 BTC, roughly $317,000 of notional at a bitcoin price near 63,500. One IBIT contract is 100 shares, roughly $3,600. Open-interest counts differ by about two orders of magnitude and are not comparable. Compare the dollar exposure fields, never the contract counts.

3. Assuming crypto trades when the options do. IBIT, ETHA, MSTR and COIN options trade US equity hours. The underlying asset trades continuously. Exposure figures pulled outside the session reflect the last settled book, not a live one, and a large weekend move in coin will not be reflected in ETF exposure until the equity market reopens. Read the as_of timestamp on every response.


Historical

The same exposures are available historically for backtesting, on the /v1/historical/ prefix:

GET /v1/historical/exposure/gex/IBIT?date=2026-06-16
GET /v1/historical/exposure/summary/MSTR?date=2026-06-16

Coverage varies by symbol and start date. Check /v1/historical/coverage before assuming depth on the newer crypto listings, several of which have short histories. A worked study is in historical crypto gamma.

Two symbol conventions, one encoding rule, and a tier map that gates by endpoint rather than by symbol. CME contracts need %3D and a Growth entitlement; the ETFs and proxies are plain tickers but full-chain GEX and the exposure summary still require Growth, with single-expiry GEX available below that. The three mistakes that cost the most time are forgetting to encode the =, comparing contract counts across wrappers whose sizes differ by two orders of magnitude, and reading equity-hours exposure as though it reflected a continuously traded underlying. Check the as_of timestamp and compare dollars.

Live Market Pulse

Get fast visibility into market shifts with full-chain analytics over low-latency REST and MCP polling.

Intelligent Screening

Screen millions of option pairs per second using your custom EV rules, filters, and setups.

Export-Ready

Export structured signals to your own execution stack or broker integration - FlashAlpha delivers the analytics, you keep control of order routing.

Join the Community

Discord

Engage in real time conversations with us!

Twitter / X

Follow us for real-time updates and insights!

GitHub

Explore our open-source SDK, examples, and analytics resources!