Rate Limits

1 request/minute, 30 requests/day, the X-RateLimit headers, and backoff.

Rate Limits

The live endpoint GET /v1/graph-stats/chart is metered per user:

WindowLimit
Per minute1 request
Per day30 requests

The public demo (/v1/demo/chart) and health (/health) endpoints are
unmetered — use the demo endpoint freely while developing.

Rate-limit headers

Every response on the live endpoint (both 200 and 429) carries these headers:

HeaderMeaning
X-RateLimit-LimitPer-minute request ceiling (1).
X-RateLimit-RemainingRequests left in the current minute window.
X-RateLimit-Daily-LimitPer-day request ceiling (30).
X-RateLimit-Daily-RemainingRequests left today.
X-RateLimit-ResetUnix epoch seconds when the current minute window resets.

On a 429, an additional Retry-After header tells you how many seconds to
wait before retrying.

The 429 body

A throttled request returns the standard error envelope. The per-minute limit uses code
RATE_LIMITED; exhausting the daily quota uses DAILY_QUOTA_EXCEEDED:

{
  "success": false,
  "errors": [
    { "code": "RATE_LIMITED", "message": "rate limit exceeded: 1 request/minute. Retry in 47s." }
  ],
  "data": null,
  "meta": { "generated_at": "2026-07-15T09:32:11Z" }
}

Retry / backoff example

Respect Retry-After; stop retrying once the daily quota is exhausted (there is no
point waiting seconds for a limit that resets tomorrow):

import time
import requests

URL = "https://graph-api.skyliferesearch.com/v1/graph-stats/chart"

def get_graph_stats(token, params=None, max_retries=5):
    headers = {"Authorization": f"Bearer {token}"}
    for _ in range(max_retries):
        r = requests.get(URL, headers=headers, params=params)
        if r.status_code != 429:
            r.raise_for_status()
            return r.json()

        code = (r.json().get("errors") or [{}])[0].get("code")
        if code == "DAILY_QUOTA_EXCEEDED":
            raise RuntimeError("daily quota exhausted — try again tomorrow")

        wait = int(r.headers.get("Retry-After", "60"))
        time.sleep(wait)
    raise RuntimeError("still rate-limited after retries")

Tips

  • Because the live endpoint allows only one request per minute, batch your needs
    into a single call: request all metrics at once, or use periods>1 to pull a rolling
    time series in one shot instead of polling.
  • Develop and test against /v1/demo/chart (unmetered), then switch to the live
    endpoint for real data.

Did this page help you?