Rate Limits
ApiBiblia uses rate limiting to ensure fair usage and API stability.
Limits by Plan
| Plan | Requests/Minute | Requests/Day |
|---|---|---|
| Basic | 30 | 5,000 |
| Pro | 100 | 50,000 |
| Enterprise | 500 | 500,000 |
Subscription-Based Limits
Rate limits are determined by your subscription tier, not individual API keys. All API keys under your account share the same limits based on your current plan.
Rate Limit Headers
Every response includes rate limit information:
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4925
X-RateLimit-Reset: 1699574400
X-RateLimit-Tier: basic| Header | Description |
|---|---|
X-RateLimit-Limit | Your daily request limit |
X-RateLimit-Remaining | Remaining requests today |
X-RateLimit-Reset | Unix timestamp when limit resets (midnight UTC) |
X-RateLimit-Tier | Your current subscription tier |
Rate Limit Exceeded
When you exceed the rate limit, you'll receive a 429 response:
json
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please wait before making more requests.",
"retry_after": 45
}
}The retry_after field indicates seconds until you can retry.
Best Practices
1. Cache Responses
Bible content doesn't change frequently. Cache responses to reduce API calls:
javascript
const cache = new Map();
async function getVerse(ref) {
const cacheKey = `verse:${ref}`;
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const response = await fetch(`/v1/passage?ref=${ref}`);
const data = await response.json();
cache.set(cacheKey, data);
return data;
}2. Batch Requests
Instead of fetching verses one by one, use ranges:
bash
# Bad: Multiple requests
curl "/v1/passage?ref=Romans 8:28"
curl "/v1/passage?ref=Romans 8:29"
curl "/v1/passage?ref=Romans 8:30"
# Good: Single request
curl "/v1/passage?ref=Romans 8:28-30"3. Implement Exponential Backoff
When rate limited, use exponential backoff:
javascript
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}4. Monitor Usage
Check your remaining quota before making requests:
javascript
const response = await fetch('/v1/versions', { headers });
const remaining = response.headers.get('X-RateLimit-Remaining');
if (remaining < 5) {
console.warn('Rate limit nearly exhausted');
}Need Higher Limits?
Upgrade your plan for higher rate limits:
| Plan | Requests/Minute | Requests/Day | Best For |
|---|---|---|---|
| Basic | 30 | 5,000 | Personal projects, small apps |
| Pro | 100 | 50,000 | Production apps, medium traffic |
| Enterprise | 500 | 500,000 | High-traffic apps, organizations |