Rate Limits
API requests are rate limited to ensure fair usage and service stability.
Limits
| Endpoint | Limit | Window |
|---|---|---|
POST /api/v1/mockup | 60 requests | 60 seconds |
Limits are applied per user (based on API key).
Response Headers
Every API response includes rate limit information in headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the limit resets |
Example Response Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705312800Rate Limit Exceeded
When you exceed the rate limit, you'll receive a 429 Too Many Requests response:
json
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"retryAfter": 30
}The response includes a Retry-After header indicating how many seconds to wait.
Handling Rate Limits
JavaScript
javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
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}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}Python
python
import requests
import time
def fetch_with_retry(url, headers, json_body, max_retries=3):
for i in range(max_retries):
response = requests.post(url, headers=headers, json=json_body)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f'Rate limited. Waiting {retry_after}s...')
time.sleep(retry_after)
continue
return response
raise Exception('Max retries exceeded')Best Practices
- Monitor remaining requests - Check
X-RateLimit-Remainingto avoid hitting limits - Implement backoff - Use exponential backoff for retries
- Queue requests - Spread requests over time instead of bursting
- Cache results - Store generated mockups to avoid redundant requests
Batch Processing Tips
When processing many screenshots:
javascript
// Process in batches with delays
const BATCH_SIZE = 10;
const DELAY_MS = 1000;
for (let i = 0; i < screenshots.length; i += BATCH_SIZE) {
const batch = screenshots.slice(i, i + BATCH_SIZE);
await Promise.all(batch.map(url => generateMockup(url)));
// Wait between batches
if (i + BATCH_SIZE < screenshots.length) {
await new Promise(r => setTimeout(r, DELAY_MS));
}
}