Rate Limits
The ReelBot API enforces rate limits to ensure fair usage and system stability.
Rate Limits by Endpoint
| Endpoint | Limit | Window |
|---|---|---|
POST /video/generate | 10 requests | 1 hour |
GET /video/status/{id} | 60 requests | 1 minute |
GET /video/download/{id} | 30 requests | 1 hour |
Why These Limits?
- Generate: Video generation is resource-intensive; 10/hour allows substantial usage while preventing abuse
- Status: Generous limit for polling; 60/minute = 1 request/second
- Download: URLs are valid for 1 hour; 30/hour is more than sufficient
Quota Limits
In addition to rate limits, your account has quota limits based on your subscription plan.
Video Generation Quota
| Plan | Videos per Month |
|---|---|
| Free | 3 |
| Starter | 15 |
| Creator | 50 |
| Pro | 150 |
| Business | 500 |
API usage counts against the same quota as the Video Studio.
Quota Reset
- Quotas reset on your billing cycle date
- Free plan quotas reset monthly from signup date
Rate Limit Headers
Every response includes rate limit information:
| Header | Description |
|---|---|
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | ISO timestamp when limit resets |
Retry-After | Seconds until you can retry (only on 429) |
Example Headers
HTTP/1.1 200 OK
X-RateLimit-Remaining: 8
X-RateLimit-Reset: 2025-01-21T17:00:00.000Z
Rate Limit Response
When you exceed a rate limit:
HTTP/1.1 429 Too Many Requests
Retry-After: 1847
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2025-01-21T17:00:00.000Z
{
"success": false,
"message": "Rate limit exceeded. Please try again later.",
"code": "RATE_LIMITED",
"details": {
"resetAt": "2025-01-21T17:00:00.000Z"
}
}
Handling Rate Limits
Check Headers Proactively
async function makeRequest(url, options) {
const response = await fetch(url, options);
const remaining = response.headers.get('X-RateLimit-Remaining');
const resetAt = response.headers.get('X-RateLimit-Reset');
console.log(`Rate limit: ${remaining} remaining, resets at ${resetAt}`);
if (remaining === '0') {
console.warn('Rate limit exhausted!');
}
return response;
}
Implement Retry Logic
async function requestWithRateLimitRetry(url, options) {
const response = await fetch(url, options);
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));
// Retry once
return fetch(url, options);
}
return response;
}
Queue Requests
For batch operations, implement a queue:
class RateLimitedQueue {
constructor(requestsPerWindow, windowMs) {
this.requestsPerWindow = requestsPerWindow;
this.windowMs = windowMs;
this.queue = [];
this.requestCount = 0;
this.windowStart = Date.now();
}
async add(fn) {
return new Promise((resolve, reject) => {
this.queue.push({ fn, resolve, reject });
this.process();
});
}
async process() {
if (this.queue.length === 0) return;
const now = Date.now();
if (now - this.windowStart >= this.windowMs) {
this.requestCount = 0;
this.windowStart = now;
}
if (this.requestCount >= this.requestsPerWindow) {
const waitTime = this.windowMs - (now - this.windowStart);
setTimeout(() => this.process(), waitTime);
return;
}
const { fn, resolve, reject } = this.queue.shift();
this.requestCount++;
try {
const result = await fn();
resolve(result);
} catch (error) {
reject(error);
}
this.process();
}
}
// Usage
const queue = new RateLimitedQueue(10, 3600000); // 10 per hour
for (const video of videosToGenerate) {
queue.add(() => generateVideo(video));
}
Best Practices
1. Respect Rate Limits
Don't try to circumvent rate limits. They protect both you and the service.
2. Use Efficient Polling
For status checks, use reasonable intervals:
// Good: 5 second intervals
const POLL_INTERVAL = 5000;
// Bad: 100ms intervals (will hit rate limit quickly)
const POLL_INTERVAL = 100;
3. Cache Download URLs
Download URLs are valid for 1 hour. Cache them instead of requesting new ones:
const urlCache = new Map();
async function getDownloadUrl(projectId) {
const cached = urlCache.get(projectId);
if (cached && new Date(cached.expiresAt) > new Date()) {
return cached.downloadUrl;
}
const response = await fetch(`/api/v1/video/download/${projectId}`, {
headers: { 'X-API-Key': API_KEY }
});
const data = await response.json();
urlCache.set(projectId, data);
return data.downloadUrl;
}
4. Batch Wisely
If generating multiple videos, spread requests over time:
async function generateBatch(videos) {
const results = [];
for (const video of videos) {
results.push(await generateVideo(video));
// Wait 6 minutes between requests to stay under 10/hour
if (videos.indexOf(video) < videos.length - 1) {
await new Promise(r => setTimeout(r, 360000));
}
}
return results;
}
Increasing Limits
If you need higher rate limits:
- Upgrade your plan: Higher plans may have increased limits
- Contact sales: Enterprise customers can negotiate custom limits
- Optimize usage: Often, better caching and batching reduces the need for higher limits
Contact: support@reelbot.space