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-Remainingbefore 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.