Skip to content

Rate Limits

ApiBiblia uses rate limiting to ensure fair usage and API stability.

Limits by Plan

PlanRequests/MinuteRequests/Day
Basic305,000
Pro10050,000
Enterprise500500,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
HeaderDescription
X-RateLimit-LimitYour daily request limit
X-RateLimit-RemainingRemaining requests today
X-RateLimit-ResetUnix timestamp when limit resets (midnight UTC)
X-RateLimit-TierYour 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:

PlanRequests/MinuteRequests/DayBest For
Basic305,000Personal projects, small apps
Pro10050,000Production apps, medium traffic
Enterprise500500,000High-traffic apps, organizations

View Pricing

Built on Cloudflare's global edge network.