CompSniper Docs

Rate limits and quotas

Handle CompSniper per-minute rate limits and monthly quota exhaustion without retry storms.

Two independent limits protect every account.

Per-minute rate limit

Standard plans allow 60 requests per minute. When exceeded, the API returns:

{
  "error": "Per-minute rate limit exceeded.",
  "code": "rate_limited",
  "retry_after": 12
}

Wait for Retry-After, add a small random jitter, and retry with a strict maximum attempt count.

Monthly quota

When every request in the plan has been used, the API returns:

{
  "error": "Free plan quota exhausted. Upgrade your CompSniper plan to continue now, or wait for your monthly reset.",
  "code": "quota_exceeded",
  "plan": "basic",
  "quota": 100,
  "used": 100,
  "remaining": 0,
  "reset_at": "2026-09-18T05:30:36.000Z",
  "upgrade_url": "https://compsniper.com/dashboard/subscription"
}

Do not retry quota_exceeded. Stop the job, show upgrade_url, or wait until reset_at.

Response headers

HeaderMeaning
X-RateLimit-LimitRequests allowed in the current minute
X-RateLimit-RemainingRequests left in the current minute
X-RateLimit-ResetUnix timestamp when the minute window resets
X-Usage-LimitMonthly plan allowance
X-Usage-RemainingMonthly requests remaining
Retry-AfterSeconds before a temporary retry

Bounded retry example

async function searchWithRetries(url, apiKey) {
  for (let attempt = 0; attempt < 5; attempt += 1) {
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    const body = await response.json();

    if (response.ok) return body;
    if (response.status === 429 && body.code === "quota_exceeded") {
      throw new Error(`Quota exhausted. Upgrade: ${body.upgrade_url}`);
    }

    const temporary =
      (response.status === 429 && body.code === "rate_limited") ||
      [500, 502, 503].includes(response.status);

    if (!temporary || attempt === 4) throw new Error(body.error);
    const delay = Number(response.headers.get("Retry-After") || body.retry_after || 2 ** attempt);
    await new Promise((resolve) => setTimeout(resolve, (delay + Math.random() * 0.5) * 1000));
  }
}

On this page