Understand rate limiting, response headers, and how to handle 429 errors gracefully.

Rate limits keep the API stable for everyone. They're per-key and operate over a one-hour window.

Limits by Key Type

Key Type Requests/Hour
Secret (sk_live_*, sk_test_*) 1,000
Publishable (pk_live_*, pk_test_*) 100

The public Library API is rate-limited at the edge per IP to prevent abuse, separate from the per-key buckets above.

Rate Limit Headers

Every API response includes these headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1711800000
X-RateLimit-Window: 3600
Header What It Tells You
X-RateLimit-Limit Maximum requests allowed in the current window
X-RateLimit-Remaining Requests you have left
X-RateLimit-Reset Unix timestamp when the window resets
X-RateLimit-Window Window duration in seconds (3600 = 1 hour)

When You Hit the Limit

You'll get a 429 Too Many Requests response:

{
  "success": false,
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Try again in 42 seconds.",
    "doc_url": "https://cstar.help/developers/errors#rate_limit_error",
    "request_id": "req_a1B2c3D4e5F6"
  }
}

The response also includes a Retry-After header with the number of seconds to wait.

Retry with Exponential Backoff

Don't just retry immediately. Back off exponentially:

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) return response;

    const retryAfter = parseInt(response.headers.get('Retry-After') || '0', 10)
      || Math.pow(2, attempt);

    console.log(`Rate limited. Waiting ${retryAfter}s (attempt ${attempt}/${maxRetries})`);
    await new Promise(r => setTimeout(r, retryAfter * 1000));
  }

  throw new Error('Max retries exceeded');
}

Staying Under the Limit

  • Check X-RateLimit-Remaining before making bursts of requests
  • Cache responses when the data doesn't change often (customer lists, articles)
  • Batch your work. Fetch a page of 100 results instead of 100 individual requests.
  • Use webhooks instead of polling. cStar pushes events to you in real time.

Monitoring Your Usage

View per-key usage stats in Settings → Team → API Keys:

  • Total requests made
  • Requests in current window
  • Last used timestamp

Custom Limits

Need higher limits? Contact support with your use case. Teams can have custom per-key or per-endpoint limits configured on the backend.