Skip to main content

Rate Limits

Optropic enforces rate limits to ensure fair usage and platform stability. Limits vary by subscription tier and endpoint.

Rate Limit Tiers

TierGenerateVerifyKeys
Free100/day1,000/day5 total
Starter1,000/day10,000/day10 total
Professional10,000/day100,000/day50 total
EnterpriseUnlimitedUnlimitedUnlimited

How Rate Limits Work

Rate limits are calculated on a sliding window basis per API key:

  • Daily limits reset at midnight UTC
  • Per-minute limits apply to burst protection (60 requests/minute)
  • Each API key has independent limits

Response Headers

Every API response includes rate limit information:

HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1708300800
X-RateLimit-Window: daily
HeaderDescription
X-RateLimit-LimitTotal requests allowed in window
X-RateLimit-RemainingRequests remaining in window
X-RateLimit-ResetUnix timestamp when window resets
X-RateLimit-WindowWindow type: daily or minute

Rate Limit Exceeded (429)

When you exceed rate limits, you'll receive:

HTTP/1.1 429 Too Many Requests
Retry-After: 3600
Content-Type: application/json
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 3600 seconds.",
"details": {
"limit": 1000,
"window": "daily",
"retryAfter": 3600
}
}
}

Handling Rate Limits

Exponential Backoff

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 = response.headers.get('Retry-After') || 60;
const delay = Math.min(retryAfter * 1000, 60000) * Math.pow(2, i);
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}

return response;
}

throw new Error('Max retries exceeded');
}

Python with Backoff

import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def create_session():
session = requests.Session()
retry = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
respect_retry_after_header=True
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('https://', adapter)
return session

session = create_session()
response = session.post(
'https://api.optropic.com/api/v1/code/verify',
headers={'x-api-key': 'your_key'},
json={'url': '...'}
)

Best Practices

1. Monitor Your Usage

Check remaining requests before critical operations:

const response = await fetch(url, options);
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));

if (remaining < 100) {
console.warn('Low rate limit remaining:', remaining);
// Send alert to operations team
}

2. Batch Where Possible

For bulk operations, use batch endpoints (coming soon) instead of individual requests.

3. Cache Verification Results

If the same code is scanned multiple times in quick succession, cache the result:

const verificationCache = new Map();

async function verifyWithCache(url) {
const cached = verificationCache.get(url);
if (cached && Date.now() - cached.timestamp < 60000) {
return cached.result; // Return cached result if < 1 minute old
}

const result = await verifyCode(url);
verificationCache.set(url, { result, timestamp: Date.now() });
return result;
}

4. Use Test Keys for Development

optr_test_ keys have separate rate limits from production keys. Use them during development to preserve production quota.

Increasing Limits

To increase your rate limits:

  1. Upgrade your plan — Higher tiers have higher limits
  2. Contact sales — For enterprise needs, contact us
  3. Request temporary increase — For product launches or events

Endpoint-Specific Limits

Some endpoints have additional restrictions:

EndpointAdditional Limit
/keys (POST)10/hour (key registration)
/keys (DELETE)5/hour (key revocation)
/code/generateBurst: 10/second
/code/verifyBurst: 100/second