FlashAlpha Lab API: Real-Time Options Exposure Analytics
Real-time options exposure analytics. Live gamma (GEX), delta (DEX), vanna (VEX), and charm (CHEX) exposure data, key levels, dealer hedging estimates, and verbal narrative analysis.
Options Exposure REST API Overview
The FlashAlpha Lab API provides programmatic access to real-time options exposure analytics derived from live options flow. Build trading tools, dashboards, and research platforms on top of production-grade exposure data.
Base URL: https://lab.flashalpha.com
What you can build:
- Real-time gamma exposure dashboards with support/resistance levels
- Automated trading signals based on dealer positioning shifts
- Options flow analytics platforms with narrative interpretation
- Historical exposure trend analysis and regime detection
Quick Start: Make Your First Options API Call
Make your first API call in under a minute. Create a free account to get your API key (no credit card required), then run:
# Fetch SPY exposure summary
curl -H "X-Api-Key: YOUR_API_KEY" \
https://lab.flashalpha.com/v1/exposure/summary/SPY
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://lab.flashalpha.com"
# 1. Check gamma regime
summary = requests.get(
f"{BASE}/v1/exposure/summary/SPY",
headers={"X-Api-Key": API_KEY}
).json()
print(f"Regime: {summary['regime']}")
print(f"Net GEX: ${summary['exposures']['net_gex']:,.0f}")
print(f"Gamma Flip: {summary['gamma_flip']}")
# 2. Get key support/resistance levels
levels = requests.get(
f"{BASE}/v1/exposure/levels/SPY",
headers={"X-Api-Key": API_KEY}
).json()["levels"]
print(f"Call Wall: {levels['call_wall']}")
print(f"Put Wall: {levels['put_wall']}")
print(f"0DTE Magnet: {levels['zero_dte_magnet']}")
const API_KEY = "YOUR_API_KEY";
const BASE = "https://lab.flashalpha.com";
const headers = { "X-Api-Key": API_KEY };
// 1. Check gamma regime
const summary = await fetch(`${BASE}/v1/exposure/summary/SPY`, { headers })
.then(r => r.json());
console.log(`Regime: ${summary.regime}`);
console.log(`Net GEX: $${summary.exposures.net_gex.toLocaleString()}`);
console.log(`Gamma Flip: ${summary.gamma_flip}`);
// 2. Get key support/resistance levels
const { levels } = await fetch(`${BASE}/v1/exposure/levels/SPY`, { headers })
.then(r => r.json());
console.log(`Call Wall: ${levels.call_wall}`);
console.log(`Put Wall: ${levels.put_wall}`);
That's it. If you see JSON output with regime, net_gex, and gamma_flip fields, your API key is working. Explore the Exposure Analytics endpoints next.
API Key Authentication via X-Api-Key Header
Step 1: Create a free account. Sign up here — no credit card required. Your API key can be found on your profile page and will appear automatically in the examples below once you're logged in.
All endpoints (except /health) require an API key. Pass it in the X-Api-Key header (recommended):
curl -H "X-Api-Key: YOUR_API_KEY" https://lab.flashalpha.com/v1/symbols
Or as a query parameter (useful for quick browser testing):
https://lab.flashalpha.com/v1/symbols?apiKey=YOUR_API_KEY
Security tip: Always prefer the X-Api-Key header in production. Query parameters may be logged in server access logs, browser history, and proxy caches.
Here's a reusable setup for your projects:
import requests, os
API_KEY = os.environ["FLASHALPHA_API_KEY"]
BASE = "https://lab.flashalpha.com"
HEADERS = {"X-Api-Key": API_KEY}
def fa_get(path, params=None):
"""Reusable helper for FlashAlpha API calls."""
resp = requests.get(f"{BASE}{path}", headers=HEADERS, params=params)
resp.raise_for_status()
return resp.json()
# Usage
summary = fa_get("/v1/exposure/summary/SPY")
quote = fa_get("/stockquote/SPY")
const API_KEY = process.env.FLASHALPHA_API_KEY;
const BASE = "https://lab.flashalpha.com";
const HEADERS = { "X-Api-Key": API_KEY };
async function faGet(path, params = {}) {
const url = new URL(`${BASE}${path}`);
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
const resp = await fetch(url, { headers: HEADERS });
if (!resp.ok) throw new Error(`${resp.status}: ${await resp.text()}`);
return resp.json();
}
// Usage
const summary = await faGet("/v1/exposure/summary/SPY");
const quote = await faGet("/stockquote/SPY");
Need higher limits? The free tier includes 5 requests/day. Upgrade your plan for higher daily quotas and additional endpoints, or contact sales for enterprise access.
API Rate Limits and Throttling Policy
Every response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Max requests per day (or unlimited) |
X-RateLimit-Remaining | Requests remaining today |
X-RateLimit-Reset | Unix timestamp when quota resets |
Retry-After | Seconds to wait (only on 429) |
When you hit the daily quota, the API returns 429 with a Retry-After header. Here's how to handle it gracefully:
import time, requests
def fa_get_safe(path, params=None):
resp = requests.get(f"{BASE}{path}", headers=HEADERS, params=params)
# Check remaining quota
remaining = resp.headers.get("X-RateLimit-Remaining")
if remaining and int(remaining) < 10:
print(f"Warning: only {remaining} requests remaining today")
if resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 60))
print(f"Rate limited. Retrying in {retry_after}s...")
time.sleep(retry_after)
return fa_get_safe(path, params) # retry once
resp.raise_for_status()
return resp.json()
async function faGetSafe(path, params = {}) {
const url = new URL(`${BASE}${path}`);
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
const resp = await fetch(url, { headers: HEADERS });
// Check remaining quota
const remaining = resp.headers.get("X-RateLimit-Remaining");
if (remaining && parseInt(remaining) < 10) {
console.warn(`Warning: only ${remaining} requests remaining today`);
}
if (resp.status === 429) {
const retryAfter = parseInt(resp.headers.get("Retry-After") || "60");
console.log(`Rate limited. Retrying in ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
return faGetSafe(path, params); // retry once
}
if (!resp.ok) throw new Error(`${resp.status}: ${await resp.text()}`);
return resp.json();
}
API Plans, Pricing Tiers, and Request Quotas
Higher tiers unlock more daily requests and additional endpoints. Free and Basic plans cover stock quotes, exposure endpoints (GEX, DEX, VEX, CHEX, levels), tickers, options meta, symbols, and vol surface. Growth adds summary, narrative, history, option quotes, and full-chain GEX (no expiry filter).
- 5 requests/day
- Stock quotes, exposure (GEX, DEX, VEX, CHEX, levels), tickers, options meta, symbols, surface
- Community support
- 100 requests/day
- Everything in Free
- Community support
- 1,000 requests/day
- + Summary, narrative, history, option quotes, full-chain GEX
- FlashMind AI included
- Priority support
- Unlimited requests
- Full access to all endpoints
- Dedicated support & SLA
- Unlimited requests
- Full access to all endpoints
- White-glove onboarding
Billing: Payments are processed securely via Stripe. You can upgrade, downgrade, or cancel anytime from your account page. Check your current usage with the GET /v1/account endpoint.
Available REST API Endpoints for Options Data
Market Data
GET /stockquote/{ticker}— Live stock quoteGET /optionquote/{ticker}— Option quotes with greeks (Growth+)GET /v1/options/{ticker}— Option chain metadata (expirations + strikes)GET /v1/surface/{symbol}— Vol surface grid (public, no auth)
Exposure Analytics
GET /v1/exposure/gex/{symbol}— Gamma exposure by strikeGET /v1/exposure/dex/{symbol}— Delta exposure by strikeGET /v1/exposure/vex/{symbol}— Vanna exposure by strikeGET /v1/exposure/chex/{symbol}— Charm exposure by strikeGET /v1/exposure/summary/{symbol}— Full exposure summary (Growth+)GET /v1/exposure/levels/{symbol}— Key support/resistance levelsGET /v1/exposure/narrative/{symbol}— Verbal narrative analysis (Growth+)GET /v1/exposure/history/{symbol}— Daily exposure history (Growth+)
Account & System
GET /v1/account— Account infoGET /v1/symbols— Tracked symbolsGET /v1/tickers— Available tickersGET /health— Health check (public, no auth)
HTTP Error Codes and Error Response Format
The API returns consistent JSON error responses. Errors include a machine-readable error field and a human-readable message or detail.
401 Unauthorized
{
"title": "Unauthorized",
"status": 401,
"detail": "Invalid API key."
}
404 Not Found
{
"error": "symbol_not_found",
"message": "No data for XYZ."
}
403 Forbidden (Tier Restricted)
{
"status": "ERROR",
"error": "tier_restricted",
"message": "This endpoint requires a Growth plan or higher.",
"current_plan": "Free",
"required_plan": "Growth"
}
429 Too Many Requests
{
"status": "ERROR",
"error": "Quota exceeded",
"message": "You have exceeded your daily API quota of 5 requests on the Free plan.",
"current_plan": "Free",
"limit": 5,
"upgrade_to": "Basic",
"reset_at": "2026-03-06T00:00:00Z"
}
Handling Errors in Code
resp = requests.get(f"{BASE}/v1/exposure/gex/INVALID", headers=HEADERS)
if resp.status_code == 200:
data = resp.json()
elif resp.status_code == 401:
print("Bad API key — check your X-Api-Key header")
elif resp.status_code == 403:
err = resp.json()
print(f"Tier restricted: {err['message']}")
print(f"Current plan: {err['current_plan']}, required: {err['required_plan']}")
elif resp.status_code == 404:
err = resp.json()
print(f"Not found: {err['message']}") # "No data for INVALID."
elif resp.status_code == 429:
err = resp.json()
print(f"Quota exceeded on {err['current_plan']} plan")
print(f"Resets at: {err['reset_at']}")
else:
print(f"Unexpected error: {resp.status_code}")
const resp = await fetch(`${BASE}/v1/exposure/gex/INVALID`, { headers: HEADERS });
switch (resp.status) {
case 200:
const data = await resp.json();
break;
case 401:
console.error("Bad API key — check your X-Api-Key header");
break;
case 403:
const err403 = await resp.json();
console.error(`Tier restricted: ${err403.message}`);
console.error(`Current: ${err403.current_plan}, required: ${err403.required_plan}`);
break;
case 404:
const err404 = await resp.json();
console.error(`Not found: ${err404.message}`);
break;
case 429:
const err429 = await resp.json();
console.error(`Quota exceeded on ${err429.current_plan} plan`);
console.error(`Resets at: ${err429.reset_at}`);
break;
default:
console.error(`Unexpected error: ${resp.status}`);
}
API Conventions: JSON Format, Dates, and Pagination
- All timestamps are UTC in ISO 8601 format
- All exposure values are in USD notional
- GEX formula:
gamma × OI × 100 × spot² × 0.01 - Greeks are calculated via Black-Scholes-Merton (BSM) — not sourced from vendor
- Implied volatility is SVI-smoothed across the surface
- Any US equity or ETF is supported
- Responses are cached for 15 seconds
- Dealer position is the opposite of net exposure (dealers are counterparty)
- OI changes are day-over-day deltas