Appearance
Rate Limits
The API enforces rate limits per IP address.
Also See
Check out Query Complexity Limits to learn about per-query cost restrictions that work alongside rate limits.
Limits
60 requests per 60 seconds
The API uses a token bucket algorithm. Tokens refill at 1 per second with a maximum of 60 tokens.
Headers
Every response includes rate limit headers:
| Header | Description |
|---|---|
RateLimit-Limit | Maximum number of requests allowed in the time window (60) |
RateLimit-Remaining | Number of requests remaining in the current window |
RateLimit-Reset | Unix timestamp (seconds) when the rate limit window resets |
Example Response Headers
RateLimit-Limit: 60
RateLimit-Remaining: 45
RateLimit-Reset: 1704067200Handling Rate Limits
When you exceed the rate limit, the API returns a 429 Too Many Requests status code with a GraphQL error response:
json
{
"errors": [
{
"message": "Rate limit exceeded. Please retry after the reset time.",
"extensions": {
"code": "RATE_LIMIT_EXCEEDED"
}
}
]
}The response also includes a Retry-After header indicating how many seconds you should wait before retrying:
Retry-After: 15Best Practices
- Monitor
RateLimit-Remainingheader - Implement exponential backoff on 429 responses
- Cache query results
- Request only needed fields
- Batch queries using aliases
- Choose appropriate page sizes
Token Bucket Details
- Each IP has a bucket with maximum 60 tokens
- Tokens refill at 1 per second
- Each request consumes 1 token
- Empty bucket results in 429 status
You can burst up to 60 requests then wait for refill. Average rate is 1 request per second.
Checking Headers
bash
# Make a GraphQL request and check headers
curl -I -X POST https://api.lcbo.dev/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ health { status } }"}'
# Response includes:
# RateLimit-Limit: 60
# RateLimit-Remaining: 59
# RateLimit-Reset: 1704067200Handling 429 Errors
javascript
async function executeGraphQLQuery(query, variables) {
const response = await fetch('https://api.lcbo.dev/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ query, variables }),
});
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
// Wait and retry
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return executeGraphQLQuery(query, variables);
}
// Check remaining requests
const remaining = response.headers.get('RateLimit-Remaining');
if (parseInt(remaining) < 10) {
console.warn(`Low rate limit remaining: ${remaining}`);
}
return response.json();
}GraphQL Queries
- Field selection doesn't affect rate limit
- Complex nested queries count as 1 request
- Multiple aliased queries count as 1 request
- Batch queries to reduce request count
Query Complexity
While rate limits control how many requests you can make, query complexity limits control what you can request in each query. Both work together to ensure fair API usage.
Next Steps
- Explore Quick Start for practical use cases
- Learn by building with the Tutorial
- Browse the GraphQL API Reference for complete documentation