Reference
Every public endpoint, parameter, response field, tier requirement, and rate limit. Base URL: https://gexboard.com. All paths return JSON.
Authentication
Every request requires an Authorization header with a Bearer token, except /api/v1/spot which is public (it returns the same data the dashboard's logged-out landing preview uses).
Authorization: Bearer gxb_live_AbCdEfGh1JKLmnopQRSTuvwxYZ012345_aBcD
Keys live forever until you regenerate or cancel the addon. Each key is tied to one paid subscriber; do not share keys across teams (see terms). Manage keys at /account.
Rate limits
Per-minute and per-day caps depend on your addon tier. The window is rolling:
| Tier | Per minute | Per day |
|---|---|---|
| Pro API | 60 | 50,000 |
| Trader API | 300 | unlimited |
When you cross a cap, responses return HTTP 429 with a Retry-After header (seconds). Counters reset at the boundary, not on a fixed timer.
Practical guidance: don't poll faster than 1 request per second per ticker — the underlying chain refreshes every ~1 s for 0DTE and ~110 s otherwise, so faster polling burns rate limit without producing fresher data.
Errors
All errors return JSON: {"detail": "..."}. Common codes:
| Code | Meaning |
|---|---|
| 400 | Malformed request — bad query parameter, invalid header. |
| 401 | Missing or invalid Authorization header. |
| 403 | Endpoint or ticker requires a higher tier. |
| 404 | Path not found — verify URL spelling. |
| 410 | Key revoked / regenerated. Reauthenticate or rotate. |
| 429 | Rate limit hit. Use Retry-After header. |
| 5xx | Server error. Retry with exponential backoff. |
Tiers
Each endpoint requires a minimum tier. Pro API addon inherits the Pro plan's data scope; Trader API addon inherits the Trader plan's. Owner customers (debug only) bypass all tier gates.
| Endpoint | Min tier | Notes |
|---|---|---|
| /api/v1/radar | Starter+ | Ticker + DTE gated by plan. |
| /api/v1/spot | Public | No auth required. |
| /api/v1/history | Starter+ | Lookback gated: 7d / 14d / 30d. |
| /api/v1/heatmap | Pro+ | |
| /api/v1/greeks | Trader | DEX, VEX, CEX (Charm/Vanna/Vomma). |
| /api/v1/premium-map | Trader | |
| /api/v1/volume | Pro+ | Requires active 0DTE session. |
Radar
Live GEX snapshot for a ticker. Returns Net GEX, Call/Put Walls, Gamma Flip, dealer regime, and per-strike contributions. Same payload the dashboard renders.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | no | Ticker symbol (default SPY). Must be in your tier's whitelist. |
| dte | int | no | DTE filter: 0=0DTE, 1=1DTE, 7=Weekly, 30=Monthly. Omit = all expirations. Range 0–365. Starter cannot pass 0 or 1. |
Example
curl "https://gexboard.com/api/v1/radar?ticker=SPY&dte=0" \ -H "Authorization: Bearer $GEXBOARD_API_KEY"
import os, requests r = requests.get("https://gexboard.com/api/v1/radar", params={"ticker": "SPY", "dte": 0}, headers={"Authorization": f"Bearer {os.environ['GEXBOARD_API_KEY']}"}, timeout=10) data = r.json()
Response
{
"ticker": "SPY",
"spot": 737.62,
"net_gamma": 2.4e9, // signed dollar gamma (top-level)
"call_wall": 745, // strike with max NET call gamma
"put_wall": 730, // strike with max NET put gamma
"gamma_flip": 735.5, // zero-gamma level
"gamma_flip_type": "confirmed", // confirmed | below_range | above_range
"dealer_mode": "positive_gamma", // or "negative_gamma"
"levels": [ // per-strike GEX array (value key is "gamma")
{ "strike": 730, "gamma": -3.2e8, "call_gamma": 1.1e8, "put_gamma": -4.3e8, "oi_call": 12000, "oi_put": 31000 },
...
],
"contracts_used": 1843,
"live_spot_used": 737.62,
"spot_source": "websocket", // websocket | intraday_rest | finnhub | yahoo_index | …
"spot_updated_at": "2026-05-08T22:55:30Z",
"available_dte_modes": ["0","1","weekly","monthly"]
// + more fields: net_gex_oi, call/put_wall_oi, zero_gamma_oi, cp_call_wall,
// cp_put_wall, levels_oi, cumulative_gex_oi, flip_distance_pct, behavior{}, alignment{}, pressure{}.
}Spot
Latest cached spot price for a ticker. Source: Finnhub WebSocket (real-time during market hours) → REST fallback → mock for offline. No authentication required — same data the logged-out landing preview uses.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | no | Ticker symbol (default SPY). |
Response
{
"ticker": "SPY",
"spot": 737.62,
"price": 737.62, // alias for spot
"change_amt": 6.04,
"change_pct": 0.8256,
"source": "finnhub", // or "yahoo", "massive", "mock_change"
"updated_at": "2026-05-08T22:55:30Z"
}History
Time-series history of GEX snapshots for a ticker. Each row is a snapshot at the time the radar engine ran (~1/min during market hours, less frequent otherwise). Tier gates the maximum lookback window.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | no | Ticker symbol (default SPY). |
| minutes | int | no | Lookback in minutes (default 30, max 43,200 = 30 days). Clamped to your tier's cap (see below). |
Lookback caps by tier
| Tier | Max minutes | Equivalent |
|---|---|---|
| Starter | 10,080 | 7 days |
| Pro / Pro API | 20,160 | 14 days |
| Trader / Trader API | 43,200 | 30 days |
Response
{
"minutes": 120,
"count": 38,
"snapshots": [
{ "id": 5921044, "timestamp": "2026-05-08T13:30:00Z", "spot": 734.10,
"net_gamma": 1.8e9, "gamma_flip": 733, "flip_type": "confirmed",
"call_wall": 740, "put_wall": 728, "dealer_mode": "positive_gamma",
"contracts_used": 1790, "spot_source": "websocket" },
...
]
}Heatmap
Strike × expiry GEX matrix from the in-memory chain (refreshed every ~110 s, 24/7). Useful for visualizing concentration and spotting which expiry drives a wall.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | no | Ticker symbol (default SPY). Must be in your tier's whitelist. |
Response
{
"ticker": "SPY",
"date": "2026-05-08",
"spot": 737.62,
"strikes": [730, 735, 740, ...],
"expiries": ["2026-05-09", "2026-05-16", ...],
"cells": [ // sparse — only non-zero GEX cells
{ "strike": 730, "expiry": "2026-05-09", "gex": -3.2e8 },
...
]
}Greeks
Per-strike Greeks Exposure: Delta (DEX), Vanna trigger, Charm flow, Vomma. Includes IV, OI, and computed dealer-hedge contributions. Trader API addon required.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | no | Ticker symbol (default SPY). |
| dte | string | no | DTE filter (preferred): "0", "1", "7", "30", or omit for all expirations. |
| dte_bucket | string | no | Legacy: 0dte / weekly / monthly / quarterly / leaps / all. If both supplied, dte wins. |
Response
{
"ticker": "SPY",
"spot": 737.62,
"dte": "0",
"strikes": [
{ "strike": 740.0, "oi_call": 7668, "oi_put": 27211,
"volume_call": 184, "volume_put": 5401,
"iv_call": 59.53, "iv_put": 29.49, "delta_call": 0.9,
"dex": 321153178.0, "vanna": -5505674.0,
"charm": 414842909.0, "vex": 566236.0,
"theta": -14764454.0 },
...
],
"net_dex": 4771672079.0,
"net_vanna": -309166025.0,
"net_vex": 33112573.0,
"net_theta": -392870135.0,
"charm_flow": 8487403120.0,
"vanna_trigger": 768.7,
"delta_neutral": 694.01,
"atm_iv": 14.35,
"iv_skew": [ { "strike": 550.0, "iv_call": 2.77, "iv_put": 2.15, ... }, ... ]
}Premium Map
Premium concentration by strike: OI × price × 100 (dollar premium). All expirations pre-computed so you can filter client-side without round-trips.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | no | Ticker symbol (default SPY). |
Response
{
"ticker": "SPY",
"spot": 737.62,
"expirations": [
{ "date": "2026-08-07", "label": "Fri 8/7", "dte": 0, "contract_count": 282 },
...
],
"strikes": [
{ "strike": 705.0, "call_premium": 99219826.8, "put_premium": 7943144.57,
"call_oi": 14509, "put_oi": 69787, "net_premium": 91276682.23 },
...
],
"strikes_by_exp": {
"2026-08-07": [
{ "strike": 715.0, "call_premium": 3773955.0, "put_premium": 8451.0,
"call_oi": 690, "put_oi": 8451, "net_premium": 3765504.0 },
...
],
"2026-08-10": [...]
},
"totals": { "call_premium": 4390820096.0, "put_premium": 674931643.0,
"total_premium": 5065751738.0 },
"institutional_signals": { "enabled": false, ... }
}Volume
Live 0DTE per-contract volume from Massive's per-minute aggregates WebSocket. Returns cumulative volume since session start + last-minute volume per contract.
active=false and rows=[]. The dashboard auto-starts sessions during market hours; the API does not (yet).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | no | Ticker symbol (default SPY). Must be in your tier's whitelist. |
Response
{
"ticker": "SPY",
"spot": 737.62,
"active": true,
"rows": [
{ "contract": "O:SPY260508C00738000",
"strike": 738.0,
"type": "C", // "C" or "P"
"volume": 346253, // cumulative since session start
"last_minute": 234 }, // volume in latest minute bar
...
],
"warming_up": false // true right after a session starts, before the first bar lands
}Start a volume session
Starts a live 0DTE volume session for a ticker so that GET /api/v1/volume has data to return. Without an active session that endpoint answers active: false with no rows. Headless consumers need this because the dashboard is what normally opens a session.
Idempotent. Calling it for a ticker that already has a session returns reason: "already_active" and takes no slot.
Request body
{ "ticker": "SPY" }Response
{
"ticker": "SPY",
"session_active": true,
"warming_up": true, // live, but the first minute bar has not landed yet
"started_by_this_call": true,
"reason": "started",
"slots": { "in_use": 2, "max": 3, "tickers": ["SPY", "SPX"] }
}Values of reason
| Value | Meaning |
|---|---|
started | A new session was opened by this call. |
already_active | The ticker already had a session. No slot consumed. |
capacity_full | All concurrent slots are in use. slots.tickers lists which tickers hold them. No existing session is ever displaced. |
market_closed | Outside 09:30–16:00 ET. Sessions only exist during regular trading hours. |
start_failed | The upstream feed refused the subscription. Retry. |
Concurrency
Three concurrent tickers across all sessions — that is what our data plan carries. slots tells you the current state on every response. If you routinely need more, tell us which tickers and we will work it out.
Usage
Poll GET /api/v1/volume about 60 seconds after a started response — the first per-minute bar has to land before rows appear. While warming_up is true, an empty rows array is expected, not an error.
Need something else?
Webhooks, additional fields, custom rate limits, or Enterprise (with redistribution rights): contact@gexboard.com. Reply within 24h.