API  /  Reference

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:

TierPer minutePer day
Pro API6050,000
Trader API300unlimited

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:

CodeMeaning
400Malformed request — bad query parameter, invalid header.
401Missing or invalid Authorization header.
403Endpoint or ticker requires a higher tier.
404Path not found — verify URL spelling.
410Key revoked / regenerated. Reauthenticate or rotate.
429Rate limit hit. Use Retry-After header.
5xxServer 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.

EndpointMin tierNotes
/api/v1/radarStarter+Ticker + DTE gated by plan.
/api/v1/spotPublicNo auth required.
/api/v1/historyStarter+Lookback gated: 7d / 14d / 30d.
/api/v1/heatmapPro+
/api/v1/greeksTraderDEX, VEX, CEX (Charm/Vanna/Vomma).
/api/v1/premium-mapTrader
/api/v1/volumePro+Requires active 0DTE session.

Radar

GET/api/v1/radarStarter+

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

NameTypeRequiredDescription
tickerstringnoTicker symbol (default SPY). Must be in your tier's whitelist.
dteintnoDTE 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

GET/api/v1/spotPublic

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

NameTypeRequiredDescription
tickerstringnoTicker 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

GET/api/v1/historyStarter+

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

NameTypeRequiredDescription
tickerstringnoTicker symbol (default SPY).
minutesintnoLookback in minutes (default 30, max 43,200 = 30 days). Clamped to your tier's cap (see below).

Lookback caps by tier

TierMax minutesEquivalent
Starter10,0807 days
Pro / Pro API20,16014 days
Trader / Trader API43,20030 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

GET/api/v1/heatmapPro+

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

NameTypeRequiredDescription
tickerstringnoTicker 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

GET/api/v1/greeksTrader

Per-strike Greeks Exposure: Delta (DEX), Vanna trigger, Charm flow, Vomma. Includes IV, OI, and computed dealer-hedge contributions. Trader API addon required.

Parameters

NameTypeRequiredDescription
tickerstringnoTicker symbol (default SPY).
dtestringnoDTE filter (preferred): "0", "1", "7", "30", or omit for all expirations.
dte_bucketstringnoLegacy: 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

GET/api/v1/premium-mapTrader

Premium concentration by strike: OI × price × 100 (dollar premium). All expirations pre-computed so you can filter client-side without round-trips.

Parameters

NameTypeRequiredDescription
tickerstringnoTicker 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

GET/api/v1/volumePro+

Live 0DTE per-contract volume from Massive's per-minute aggregates WebSocket. Returns cumulative volume since session start + last-minute volume per contract.

Note: Volume requires an active 0DTE session for the ticker. A session starts when (a) a paying dashboard user toggles VOL on for the ticker, or (b) admin starts one explicitly. If no session is active, this returns active=false and rows=[]. The dashboard auto-starts sessions during market hours; the API does not (yet).

Parameters

NameTypeRequiredDescription
tickerstringnoTicker 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

POST/api/v1/volume/sessionPro+

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

ValueMeaning
startedA new session was opened by this call.
already_activeThe ticker already had a session. No slot consumed.
capacity_fullAll concurrent slots are in use. slots.tickers lists which tickers hold them. No existing session is ever displaced.
market_closedOutside 09:30–16:00 ET. Sessions only exist during regular trading hours.
start_failedThe 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.