{"openapi": "3.1.0", "info": {"title": "VolStrata key gamma levels feed", "version": "1.0.0", "summary": "Free JSON feed of today's dealer-gamma key levels \u2014 call wall, put wall, gamma flip and max pain.", "description": "A free, no-key, CORS-open JSON feed of today's key dealer-gamma levels for major index and ETF symbols. No account and no sign-up; callable from a browser on any origin. Full documentation, freshness terms and fair-use policy: https://volstrata.com/levels-api", "termsOfService": "https://volstrata.com/levels-api", "contact": {"name": "VolStrata", "url": "https://volstrata.com/"}, "license": {"name": "Free to use with visible attribution to volstrata.com", "url": "https://volstrata.com/levels-api"}}, "servers": [{"url": "https://volstrata.com"}], "externalDocs": {"description": "Human documentation", "url": "https://volstrata.com/levels-api"}, "paths": {"/embed/levels.json": {"get": {"operationId": "getKeyLevels", "summary": "Today's key gamma levels for a symbol", "description": "Returns one JSON object. Always 200 \u2014 an unknown symbol is answered with SPX and `clamped: true` rather than a 4xx, and a session with no levels yet returns `has_data: false` with null prices. Read `delayed`, `delay_secs`, `stale` and `as_of_epoch` before printing a number. The `ticker` parameter is optional; the parameter-free URL returns SPX.", "parameters": [{"name": "ticker", "in": "query", "required": false, "description": "The symbol to return. Published: SPX, NDX, QQQ, SPY. Defaults to SPX; an unpublished symbol is answered with SPX and clamped:true.", "schema": {"type": "string", "default": "SPX"}}], "responses": {"200": {"description": "One levels record. Served with Access-Control-Allow-Origin: * and Cache-Control: public, max-age=30.", "headers": {"Access-Control-Allow-Origin": {"schema": {"type": "string"}, "description": "Always '*' \u2014 CORS-open."}, "Cache-Control": {"schema": {"type": "string"}, "description": "public, max-age=30."}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LevelsRecord"}}}}, "429": {"description": "Per-IP fair-use limit exceeded (120 requests per 60s). Carries a Retry-After header.", "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until the window resets."}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}}}}, "components": {"schemas": {"LevelsRecord": {"type": "object", "required": ["ticker", "requested_ticker", "clamped", "spot", "call_wall", "put_wall", "flip", "max_pain", "em_high", "em_low", "vol_high", "vol_low", "regime", "net_gex_bn", "as_of_epoch", "as_of_label", "delayed", "delay_secs", "stale", "has_data", "source", "status", "reason"], "properties": {"ticker": {"type": "string", "description": "The symbol these levels belong to. This is the symbol we answered with, which is not always the one you asked for \u2014 see clamped."}, "requested_ticker": {"type": ["string", "null"], "description": "Exactly what you passed in ?ticker=, echoed back. Null when you passed nothing at all."}, "clamped": {"type": "boolean", "description": "True when you asked for a symbol this feed does not publish and we answered with SPX instead of an error."}, "spot": {"type": ["number", "null"], "description": "The price of the underlying that the levels were measured against."}, "call_wall": {"type": ["number", "null"], "description": "The call wall strike \u2014 the level that most often acts as resistance."}, "put_wall": {"type": ["number", "null"], "description": "The put wall strike \u2014 the level that most often acts as support."}, "flip": {"type": ["number", "null"], "description": "The gamma flip (zero-gamma) level. Above it moves tend to be dampened, below it they tend to be amplified."}, "max_pain": {"type": ["number", "null"], "description": "The max pain strike \u2014 where the most option value expires worthless."}, "em_high": {"type": ["number", "null"], "description": "The upper expected-move band \u2014 the top of the range implied volatility priced in for the session. Null when no band is published."}, "em_low": {"type": ["number", "null"], "description": "The lower expected-move band \u2014 the bottom of that same implied range. Null when no band is published."}, "vol_high": {"type": ["number", "null"], "description": "The upper volatility-trigger band. Null when no band is published."}, "vol_low": {"type": ["number", "null"], "description": "The lower volatility-trigger band. Null when no band is published."}, "regime": {"type": ["string", "null"], "description": "A one-word summary of the gamma regime. Frequently null on this feed; always check before you rely on it."}, "net_gex_bn": {"type": ["number", "null"], "description": "Net gamma exposure in billions. Frequently null on this feed; always check before you rely on it."}, "as_of_epoch": {"type": ["integer", "null"], "description": "Unix time, in seconds, of the market data these levels were computed from. This is the age of the NUMBERS, not the time you called us \u2014 subtract it from your own clock to find out how old they are."}, "as_of_label": {"type": "string", "description": "The same instant already formatted in US Eastern time, for display. The string \u201c\u2014\u201d when we do not have a timestamp."}, "delayed": {"type": "boolean", "description": "True when a deliberate delay was applied to this symbol before serving it to you. See How fresh is it, really."}, "delay_secs": {"type": "integer", "description": "The size of that delay in seconds, or 0. It is a FLOOR, not a promise of precision \u2014 read the note under the freshness table."}, "stale": {"type": "boolean", "description": "True when we could not build a level set at the point you were entitled to and are showing you the most recent one we do have instead. as_of_epoch still tells you its real age."}, "has_data": {"type": "boolean", "description": "False before the first level set of the session exists. Every price field is null when this is false, and the response is still a 200."}, "source": {"type": "string", "description": "How this record was arrived at: \u201clive\u201d, \u201cdelayed\u201d, \u201clast-known\u201d, or \u201cnone\u201d when there is nothing to serve yet."}, "status": {"type": "string", "description": "What kind of answer this is: \u201cok\u201d when the levels below are a real reading, \u201cno_data\u201d when the session has genuinely not published any yet (nothing is wrong \u2014 it is pre-open, or a sparsely-polled symbol), and \u201cunavailable\u201d when WE failed and this record is standing in for a reading we could not take. Branch on this rather than inferring health from the absence of numbers: the last two look identical otherwise."}, "reason": {"type": ["string", "null"], "description": "A short machine-readable tag naming the fault when status is \u201cunavailable\u201d, and null otherwise. Log it; do not parse it for meaning \u2014 the set of tags is not part of this contract."}}, "additionalProperties": true}, "Error": {"type": "object", "properties": {"error": {"type": "string"}, "detail": {"type": "string"}, "retry_after": {"type": "integer"}}}}}}