Rate Limits
Understanding and working within API rate limits.
General API Rate Limits
All API endpoints are protected by rate limiting. The default limits apply to all authenticated requests:
| Endpoint Type | Limit | Time Window |
|---|---|---|
| Standard API | 100 requests | 15 minutes |
| Heavy Operations | 20 requests | 1 hour |
QR Code Rate Limits (Tier-Based)
QR code generation has tier-specific rate limits based on your workspace plan:
| Plan | QR Codes/hour | Notes |
|---|---|---|
| Free | 10 | Upgrade to Pro for higher limits |
| Pro | 100 | Upgrade to Business for higher limits |
| Business | 1,000 | Contact support for custom limits |
Password-Protected Links
Password verification endpoints have stricter limits to protect against brute-force attacks:
| Window | Limit | Scope |
|---|---|---|
| Short | 5 attempts/minute | Per link + IP address |
| Long | 30 attempts/hour | Per link (distributed attack protection) |
Rate Limit Headers
Every API response includes rate limit information in the headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when window resets |
Retry-After | Seconds to wait (only on 429 response) |
Handling Rate Limits
When you exceed the rate limit, you'll receive a 429 response:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312800
Retry-After: 45
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please try again later.",
"details": {
"retryAfter": 45,
"limit": 100,
"windowMs": 900000
}
},
"meta": {
"timestamp": "2025-01-15T10:30:00.000Z"
}
}Best Practices
- Monitor rate limit headers - Check
X-RateLimit-Remainingproactively to avoid hitting limits. - Implement exponential backoff - When rate limited, wait and retry with increasing delays.
- Batch requests when possible - Use bulk endpoints to reduce the number of API calls.
- Cache responses - Cache read-only data locally to reduce API calls.
- Spread requests over time - Avoid bursts by distributing requests evenly.
Monitoring Example
Note: Replace apiKey with your actual API key from the dashboard. Example API keys like snip_example_key will not work. API keys are workspace-specific and should be kept secret.
async function apiRequest(url, options = {}) {
const response = await fetch(url, {
...options,
headers: {
'X-API-Key': apiKey,
...options.headers,
},
});
// Log rate limit info
const remaining = response.headers.get('X-RateLimit-Remaining');
const limit = response.headers.get('X-RateLimit-Limit');
const reset = response.headers.get('X-RateLimit-Reset');
console.log(`Rate limit: ${remaining}/${limit} remaining`);
// Warn when getting low
if (remaining && parseInt(remaining) < 10) {
console.warn('Rate limit getting low!');
}
// Handle rate limit exceeded
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const waitTime = retryAfter ? parseInt(retryAfter) : 60;
console.log(`Rate limited. Waiting ${waitTime}s...`);
await new Promise(r => setTimeout(r, waitTime * 1000));
// Retry the request
return apiRequest(url, options);
}
return response;
}Distributed Rate Limiting
The API uses Redis-based distributed rate limiting for multi-instance deployments. This ensures consistent rate limiting across all API servers. If Redis is unavailable, the API falls back to in-memory rate limiting per server.
Tip: If you need higher limits for a specific use case, contact our support team to discuss your requirements.