Rate Limiting
Understand tier-based rate limits and how to handle them in your application.
Rate limits reset every minute using a sliding window algorithm.
Rate Limits by Tier
| Tier | Rate Limit | Window |
|---|---|---|
FREE | 20 requests | per minute |
BASIC | 40 requests | per minute |
PRO | 80 requests | per minute |
ENTERPRISE | 150 requests | per minute |
Response Headers
Every API response includes rate limit headers:
X-RateLimit-LimitThe maximum number of requests allowed per minute for your tier.
X-RateLimit-RemainingThe number of requests remaining in the current window.
X-RateLimit-ResetUnix timestamp (milliseconds) when the rate limit resets.
Handling Rate Limits
When you exceed your rate limit, the API returns a 429 status code.
Implement exponential backoff when you receive a 429 response:
- Check the
X-RateLimit-Resetheader - Calculate wait time until reset
- Wait before retrying the request
- Consider implementing a queue for large batches
Best Practices
- Monitor rate limit headers in responses
- Implement retry logic with exponential backoff
- Cache responses when possible to reduce API calls
- Upgrade your plan if you consistently hit rate limits
- Use batch operations wisely to stay within limits
Response Examples
429 Error
Request (Exceeds Limit)
curl -X POST https://snagkit.io/api/v1/capture \
-H "X-API-Key: sk_live_xxx" \
-d "url=https://example.com"Response (429 Too Many Requests)
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"limit": 20,
"remaining": 0,
"reset": 1695123456789
}Response Headers
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1695123456789Retry Logic Example (JavaScript)
async function captureWithRetry(url) {
const response = await fetch('https://snagkit.io/api/v1/capture', {
method: 'POST',
headers: { 'X-API-Key': 'sk_live_xxx' },
body: JSON.stringify({ url, response_type: 'json' })
})
if (response.status === 429) {
const reset = response.headers.get('X-RateLimit-Reset')
const waitTime = reset - Date.now()
console.log(`Waiting ${waitTime}ms before retry`)
await new Promise(resolve => setTimeout(resolve, waitTime))
return captureWithRetry(url)
}
return response.json()
}