Skip to main content

How quotas work

Every API key has a daily quota that resets at midnight UTC. Every request to /api/v1/* (and the MCP server) counts as one.
TierDaily quota
trial50 requests/day
pro500 requests/day
adminUnlimited
MCP requests count against the same quota as REST API requests. There’s no separate MCP allowance.

Rate limit headers

Every response includes three headers:
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 487
X-RateLimit-Reset: 2026-04-15T00:00:00+00:00
HeaderMeaning
X-RateLimit-LimitYour daily quota
X-RateLimit-RemainingRequests left until reset
X-RateLimit-ResetWhen the counter resets (ISO 8601, UTC)
The rate_limit field in the response body contains the same information:
{
  "data": { "..." },
  "meta": {
    "rate_limit": {
      "limit": 500,
      "remaining": 487,
      "reset": "2026-04-15T00:00:00+00:00"
    }
  }
}

Handling 429 responses

When you exceed your quota:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2026-04-15T00:00:00+00:00
Content-Type: application/json

{
  "error": "rate_limit_exceeded",
  "message": "Daily limit of 500 reached."
}
import time
from datetime import datetime, timezone

def call_with_retry(fn, max_retries=3):
    for attempt in range(max_retries):
        resp = fn()
        if resp.status_code != 429:
            return resp

        reset = resp.headers.get("X-RateLimit-Reset")
        if not reset:
            time.sleep(60)
            continue

        reset_ts = datetime.fromisoformat(reset).timestamp()
        wait = max(0, reset_ts - time.time())

        # Don't wait more than an hour — surface the error instead
        if wait > 3600:
            raise RuntimeError(f"Rate limited until {reset}")

        time.sleep(wait + 1)
    raise RuntimeError("Max retries exceeded")

Planning your quota

The underlying GEX data updates every 15 minutes (Lambda capture). Polling more often than that doesn’t yield new data. A typical trading bot pattern:
  • term-oi for BTC + ETH every 15 min = 2 × 4 = 8 req/hour
  • by-strike-enhanced for 2-3 expirations every 15 min = ~10 req/hour
  • Discovery endpoints (rare, cached locally) = 1-2 req/day
Total: ~430 req/day for a busy bot — comfortably within the 500/day Pro quota.

Running out of quota?

  • Cache responses locally. The data only changes every 15 min.
  • Use the virtual all exchange instead of calling each exchange separately.
  • Reduce polling frequency to once every 30 min if you don’t need sub-15-min latency.
  • Contact us at admin@gammaflip.io if you need a higher custom limit.