research
REST endpoint for on-demand gbR options chart assets, 3D volatility surfaces, and tabular CSV/JSON datasets across US optionable equities.
Research API Specification & Interactive Builder
The complete REST endpoint specification, accepted parameter schemas, response models, and interactive URL testing tools are maintained directly on the platform.
View Full API Specification & Builder on gexbot.com ↗Endpoint Overview
The Research API computes on-demand Greek exposures, volatility surfaces, open interest profiles, and price-spread parity. It serves index options, ETFs, and all US optionable equities.
GET /research/{ticker}/{metric}Architecture & Service Base URLs
- API Gateway:
/research/{ticker}/{metric} - Asset Storage & CDN:
https://assets.gexbot.com/(orhttps://r.gex.bot/). Theurlfield of a descriptor already starts withgbR/.
Operating Hours & Data Cadence
- Regular Market Hours (09:30–16:00 ET):
- Evaluates live option market quotes using the
gbRpricing model. - Caches requests on 15-minute floor intervals on-demand.
- Evaluates live option market quotes using the
- Index Option Extended Hours (16:00–16:15 ET):
- Index options (such as SPX and NDX) trade until 16:15 ET.
- Requests submitted at or after 16:15 ET include trades from this 15-minute post-close window.
- Premarket Hours (Before 09:30 ET):
- Open Interest (OI) refreshes daily at 08:00 ET.
- Calculations use previous session quotes under the
gbRmodel. The premarket cache refreshes once after 08:00 ET. - Option volume metrics remain disabled until market open at 09:30 ET.
- After Hours, Final Snapshots & Weekends:
- The final scheduled End-of-Day (EOD) snapshot generates every evening at 23:00 UTC (19:00 EDT / 18:00 EST).
- After 17:00 ET, all after-hours queries return the stabilized closing snapshot from the session.
- Queries on weekends and market holidays return the cached snapshot from the previous trading session.
Option Expiration & Settlement Cadence
- Settlement Timestamps:
- AM-Settled Series: Standard monthly index contracts expire at 10:00 ET on their expiration date.
- PM-Settled Series: Daily and weekly equity and index contracts expire at 16:00 ET on their expiration date.
- Expired Series Filtering:
- Contracts drop immediately from active expirations and calculations once the market clock reaches their expiration timestamp.
- DTE resolution, exposure metrics, and API responses exclude expired contracts automatically.
Authentication & Headers
All requests require a Research API key (prefix research_). You can create one when your account has the Research add-on. The endpoint refuses gexbot keys, including Quant keys, with 403. Pass the key in the Authorization header as a Bearer token:
Authorization: Bearer <YOUR_API_KEY>
User-Agent: <YOUR_APP_NAME>/1.0
Accept: application/json| Header | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Bearer token format: Bearer <YOUR_API_KEY>. |
User-Agent | string | Yes | Unique identifier for your client application. |
Accept | string | Yes | Set to application/json, or text/csv for the csv format. |
Path Parameters
| Parameter | Type | Required | Example | Description |
|---|---|---|---|---|
ticker | string | Yes | SPX, NVDA, AAPL | Ticker symbol of the underlying asset (1 to 6 letters, not case-sensitive). Digits, dots and slashes are not accepted. |
metric | string | Yes | gex_oi, iv_mid, oi | The analytical metric or Greek exposure to calculate. |
Metric Aliases
The API translates legacy and shorthand metric names to internal engines. Metric names are not case-sensitive.
| Request Alias | Canonical Engine Metric | Category |
|---|---|---|
oi | open_interest | Market Data |
parity | put_call_parity | Market Data |
gamma_wall | gamma_wall_abs | Market Data |
vol_trigger | gamma_flip | Market Data |
iv_ask | ask_iv | Implied Volatility |
iv_mid | mid_iv | Implied Volatility |
iv_bid | bid_iv | Implied Volatility |
extrinsic | time_value | Market Data |
intrinsic | intrinsic_value | Market Data |
Query Parameters
The view and type values are case-sensitive. All other values are not. Only the value true (any case) turns a boolean on. Any other value is false. A start_dte or end_dte value that is not an integer resets both parameters to their defaults. For chart formats an empty expiration window moves to the nearest expiration.
| Parameter | Type | Default | Accepted Values | Description |
|---|---|---|---|---|
format | string | webp | webp, png, jpeg, svg, pdf, json, csv | Response payload format. Image formats return an asset descriptor. |
view | string | skew | skew, term, surface, mirror (implied-volatility metrics only) | Chart visualization mode. mirror applies to iv_bid, iv_mid and iv_ask only. Other metrics fall back to skew. |
type | string | line (bar for oi, volume and exposure metrics; scatter for parity) | bar, line, histogram, scatter | Series render style. |
theme | string | dark | dark, light | Color palette for rendered chart images. |
strikes | integer | 15 (50 for oi and volume, 30 for exposure metrics) | Integer 5-250 (values outside the range are clamped) | Number of strike intervals calculated around spot price. |
start_dte | integer | 0 | Integer 0-1000 | Start days-to-expiration boundary (inclusive). |
end_dte | integer | 98 (365 for view=term, 64 for max_pain) | Integer 0-1000 | End days-to-expiration boundary (inclusive). |
expiration_filter | string | None | m (monthly), w (weekly), q (quarterly) | Restricts calculations to specific expiration types. |
contract_filter | string | all | all, calls, puts | Filters calculation contracts by option side. |
moneyness_filter | string | None (ntm for iv_bid, iv_mid and iv_ask) | otm, ntm, itm, atm, d10, d15, d20, d25 | Filters contracts by moneyness or delta bucket. Default is ntm for iv_bid, iv_mid and iv_ask. |
contract_agg | boolean | true | true, false | When true, nets calls and puts into one value per strike. When false, keeps calls and puts as separate rows. |
expiry_agg | boolean | false | true, false | When true, aggregates all expiries across each strike. |
skew_adj | boolean | false | true, false | Adjusts Greek calculations for volatility skew. |
limit_y | boolean | true | true, false | Clamps the Y-axis scale to remove extreme statistical outliers. Send limit_y=false to disable the clamp. |
series | string | None | deltas, moneyness, strikes | For IV term view, plots term structure across delta tiers. |
Response Schemas
1. Image Asset Descriptor Response
When format is webp, png, svg, jpeg, or pdf, the server returns a JSON object containing the relative asset URL:
{
"url": "gbR/QUFQTF9za2V3X2NvbnRyYWN0X2FnZ18yMDI2MDcwOFQxNTQ4MDU.svg",
"name": "QUFQTF9za2V3X2NvbnRyYWN0X2FnZ18yMDI2MDcwOFQxNTQ4MDU.svg",
"content_type": "image/svg+xml",
"description": "$AAPL skew 20260708T154805",
"time_stamp": "20260708T154805",
"model_ts": "2026-07-08T15:45:00-04:00",
"model": "gbR"
}| Field | Type | Description |
|---|---|---|
url | string | Relative asset path. Resolve against https://r.gex.bot/ to fetch the file. |
name | string | Asset filename. Matches the last path segment of url. |
content_type | string | MIME type of the rendered file. |
description | string | Summary containing ticker, metric, and generation timestamp. |
time_stamp | string | Generation timestamp in YYYYMMDDTHHMMSS format. |
model_ts | string or null | ISO-8601 timestamp of the options-chain snapshot the chart used. |
model | string | Volatility model of the request. Default gbR. |
2. Tabular Data Response (format=csv and format=json)
When format=csv the endpoint returns text/csv with Content-Disposition: attachment; filename="SPX_data.csv". When format=json it returns application/json: an array of row objects with the same columns, with Content-Disposition: attachment; filename="SPX_data.json".
- Skew view columns:
idx_strike_price,idx_expiration_date(absent whenexpiry_agg=true),idx_call_put_flag(absent whencontract_agg=true, the default) and the metric id in upper case, for exampleGEX_OI. - Term view columns:
idx_expiration_date,idx_call_put_flag(absent whencontract_agg=true) and the metric. - Surface view: one row per strike and expiration with the metric.
gamma_flip,vol_trigger,gamma_wallandgamma_wall_absreturn the gamma-flip table instead.skew_adjandexpiration_filterhave no effect oncsvorjsonoutput.
Example header with contract_agg=false:
idx_strike_price,idx_expiration_date,idx_call_put_flag,GEX_OIError Handling & Rate Limits
| HTTP Status | Error Reason | Response Body / Behavior |
|---|---|---|
400 Bad Request | Unknown or restricted metric, or an invalid parameter. | {"error": "invalid request"}. Other messages: Invalid ticker., Invalid metric., Ticker ZZZZ is not a valid symbol., GEX_OI does not support skew adjustment., Volume-based metrics are unavailable during pre-market hours. Please wait for market open., User-Agent not found., Authorization header not found. |
401 Unauthorized | Invalid API key. A missing Authorization header returns 400. | The response carries no {"error": ...} body. |
403 Forbidden | The key is not a Research API key. | The response carries no {"error": ...} body. |
403 Forbidden | The requested format is not available to this key. | {"error": "This research data format is not available for restricted commercial access."} |
429 Too Many Requests | Query quota exceeded for the current window. | {"error": "Rate limit exceeded."} |
500 Internal Server Error | The research service failed. | {"error": "Failed to reach upstream research service."}, or a research-service message such as Failed to load data. or Failed to build chart. |
Code Examples
BASE_URL="<your host and version>"
# Request SVG chart asset descriptor
curl -X GET "$BASE_URL/research/SPX/gex_oi?format=svg&strikes=25&contract_agg=true" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "User-Agent: MyResearchApp/1.0" \
-H "Accept: application/json"
# Request raw CSV dataset
curl -X GET "$BASE_URL/research/AAPL/gex_oi?format=csv&start_dte=0&end_dte=30" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "User-Agent: MyResearchApp/1.0" \
-H "Accept: text/csv"import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "<your host and version>"
headers = {
"Authorization": f"Bearer {API_KEY}",
"User-Agent": "PythonClient/1.0",
"Accept": "application/json",
}
# Fetch chart asset descriptor
url = f"{BASE_URL}/research/NVDA/iv_mid"
params = {
"format": "webp",
"view": "term",
"start_dte": 0,
"end_dte": 180
}
response = requests.get(url, headers=headers, params=params)
data = response.json()
image_url = f"https://assets.gexbot.com/{data['url']}"
print(f"Chart available at: {image_url}")const API_KEY = 'YOUR_API_KEY';
const BASE_URL = '<your host and version>';
async function fetchResearchCSV(ticker: string, metric: string) {
const url = new URL(`${BASE_URL}/research/${ticker}/${metric}`);
url.searchParams.set('format', 'csv');
url.searchParams.set('start_dte', '0');
url.searchParams.set('end_dte', '98');
const res = await fetch(url.toString(), {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'User-Agent': 'NodeApp/1.0',
'Accept': 'text/csv',
},
});
if (!res.ok) {
throw new Error(`Request failed with status ${res.status}`);
}
const csvData = await res.text();
return csvData;
}