Error format
All errors return a JSON body witherror and message:
erroris a stable slug. Branch on this — it will not change for a given condition.messageis prose for humans. Never parse it; the wording may change at any time without notice.
data / meta envelope used by
successful responses — on any endpoint — so response.json()["error"] is safe
everywhere.
HTTP status codes
Error codes
unauthorized (401)
- The
X-API-Keyheader is present - The key is correct (no copy-paste whitespace)
- The key hasn’t been revoked
- The key starts with
gex_sk_
unauthorized covers two cases: no credential was supplied, and a credential
was supplied but did not resolve to a user — the latter returns
"Could not resolve a user identity from the supplied credentials." Both share
one code deliberately, so you only need a single branch.subscription_required (403)
current_tier field shows
your current plan. Upgrade to Pro
to get API access.
market_not_in_plan (403)
SPX, and a
tradfi-only plan gets it on BTC.
Only endpoints taking a
<coin> path parameter can return this. The discovery
endpoints (/exchanges, /coins) list availability rather than market data,
and are never gated this way.
To fix it, add the market to your subscription, or request a symbol from a
market you already have.
invalid_exchange (400)
bybit, deribit, okx, and the virtual all / combined
(aggregated).
no_data (404)
- The exchange doesn’t list options for this coin (e.g., OKX doesn’t have XRP)
- The expiration has already expired
- The basecoin is mistyped (must be uppercase)
rate_limit_exceeded (429)
rate_limit object repeats the figures from the X-RateLimit-* headers.
See Rate Limits for handling strategies.
Getting help
- Bug reports / unclear errors: admin@gammaflip.io
- Feature requests: open an issue on gammaflip-docs