Rate Limits
Understanding API rate limits and how to optimize your integration.
Overview
The Heydeo API implements rate limiting to ensure fair usage and maintain service quality for all users. Rate limits are applied per API key and vary based on your subscription plan.
💡 Tip: All API responses include rate limit headers to help you track your usage.
Rate Limit Tiers
| Plan | Requests/Minute | Requests/Hour | Daily Limit |
|---|---|---|---|
| Free | 10 | 100 | 1,000 |
| Starter | 60 | 1,000 | 10,000 |
| Professional | 300 | 5,000 | 100,000 |
| Enterprise | Custom | Custom | Custom |
Rate Limit Headers
Every API response includes these headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Remaining requests in the current window |
X-RateLimit-Reset | Unix timestamp when the rate limit resets |
Retry-After | Seconds to wait before retrying (only on 429 errors) |
Example Response
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1701525600
{
"data": [...]
}Handling Rate Limits
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1701525600
Retry-After: 30
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please retry after 30 seconds.",
"retry_after": 30
}
}JavaScript Example
async function makeRequestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options);
// Log rate limit info
console.log('Rate limit:', {
limit: response.headers.get('X-RateLimit-Limit'),
remaining: response.headers.get('X-RateLimit-Remaining'),
reset: response.headers.get('X-RateLimit-Reset')
});
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
console.log(`Rate limited. Waiting ${retryAfter} seconds...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
return await response.json();
} catch (error) {
if (attempt === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
}
}
}Python Example
import time
import requests
from typing import Dict, Any
def make_request_with_retry(
url: str,
headers: Dict[str, str],
max_retries: int = 3
) -> Any:
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
# Log rate limit info
print(f"Rate limit: {response.headers.get('X-RateLimit-Remaining')}/{response.headers.get('X-RateLimit-Limit')}")
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
continue
response.raise_for_status()
return response.json()
raise Exception("Max retries exceeded")Best Practices
- 📊 Monitor rate limit headers - Check remaining requests before making calls
- 🔄 Implement exponential backoff - Wait progressively longer between retries
- 💾 Cache responses - Reduce API calls by caching frequently accessed data
- 📦 Batch requests - Use bulk endpoints when available to reduce request count
- ⏱️ Respect Retry-After - Always wait the specified time before retrying
- 🎯 Use webhooks - Receive push notifications instead of polling
- 📈 Upgrade when needed - Consider a higher tier if limits are constraining
Rate Limit Strategies
Token Bucket Algorithm
Heydeo uses the token bucket algorithm for rate limiting. This allows for short bursts of traffic while maintaining an average rate over time.
Request Queuing
Consider implementing a client-side queue for managing API requests:
class RateLimitedQueue {
constructor(requestsPerMinute) {
this.queue = [];
this.processing = false;
this.interval = 60000 / requestsPerMinute;
}
async add(requestFn) {
return new Promise((resolve, reject) => {
this.queue.push({ requestFn, resolve, reject });
this.process();
});
}
async process() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
const { requestFn, resolve, reject } = this.queue.shift();
try {
const result = await requestFn();
resolve(result);
} catch (error) {
reject(error);
}
setTimeout(() => {
this.processing = false;
this.process();
}, this.interval);
}
}
// Usage
const queue = new RateLimitedQueue(60); // 60 requests per minute
const result = await queue.add(() => fetch('https://api.heydeo.ai/v1/shipments'));Checking Your Usage
Get your current rate limit status:
GET https://api.heydeo.ai/v1/rate-limit
Response:
{
"limit": 60,
"remaining": 45,
"reset": 1701525600,
"period": "minute"
}Enterprise Plans
Need higher rate limits? Enterprise plans offer custom rate limits tailored to your needs:
- Custom request limits (up to 1000+ requests/minute)
- Dedicated API endpoints
- Priority support with guaranteed response times
- SLA guarantees
- Dedicated account manager
Frequently Asked Questions
Are rate limits per API key or per account?
Rate limits are applied per API key. If you need more capacity, you can create multiple API keys or upgrade your plan.
Do webhook deliveries count against rate limits?
No, webhook deliveries from Heydeo to your endpoint do not count against your API rate limits.
What happens if I consistently exceed rate limits?
Consistent rate limit violations may result in temporary throttling or account review. We recommend upgrading to a higher tier if you regularly hit limits.
Can I request a temporary rate limit increase?
Yes, contact support at support@heydeo.ai with your use case.