Rate Limits
CTWiseAPI enforces rate limits to ensure fair usage and service stability.
Rate Limit by Tier
| Tier | Requests/Second | Monthly Calls |
|---|---|---|
| Free | 2 | 1,000 |
| Starter | 10 | 10,000 |
Response Headers
Every API response includes rate limit information:
HTTP/1.1 200 OK
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 8
X-RateLimit-Reset: 1704067200
X-RateLimit-Monthly-Limit: 10000
X-RateLimit-Monthly-Remaining: 7500
| Header | Description |
|---|---|
X-RateLimit-Limit | Max requests per second |
X-RateLimit-Remaining | Remaining requests in current second |
X-RateLimit-Reset | Unix timestamp when limit resets |
X-RateLimit-Monthly-Limit | Monthly call limit |
X-RateLimit-Monthly-Remaining | Remaining calls this month |
Rate Limit Exceeded
When you exceed the rate limit:
HTTP/1.1 429 Too Many Requests
Retry-After: 1
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Maximum 10 requests per second.",
"retryAfter": 1
}
}
Monthly Quota Exceeded
When you exceed monthly quota:
HTTP/1.1 429 Too Many Requests
{
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Monthly API call limit reached. Upgrade your plan for more calls.",
"upgradeUrl": "https://app.orchestraprime.ai/ctwise/billing/upgrade"
}
}
Best Practices
Implement Exponential Backoff
import time
import requests
from requests.exceptions import RequestException
def make_request_with_backoff(url, headers, data, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.post(url, headers=headers, json=data)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 1))
wait_time = retry_after * (2 ** attempt) # Exponential backoff
print(f"Rate limited. Waiting {wait_time} seconds...")
time.sleep(wait_time)
continue
response.raise_for_status()
return response.json()
except RequestException as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
raise Exception("Max retries exceeded")
Use Rate Limit Headers Proactively
async function makeRequest(url, options) {
const response = await fetch(url, options);
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
if (remaining < 2) {
// Slow down when approaching limit
await new Promise(resolve => setTimeout(resolve, 500));
}
return response.json();
}
Batch Requests When Possible
Instead of multiple single requests:
# ❌ Multiple requests
curl .../search -d '{"query": "informed consent"}'
curl .../search -d '{"query": "adverse events"}'
curl .../search -d '{"query": "data management"}'
Design your application to minimize API calls:
# ✅ Cache results
from functools import lru_cache
@lru_cache(maxsize=100)
def search_rules(query):
return api.search(query)
Monitor Usage
Check your usage regularly:
curl https://api.ctwise.ai/v1/usage \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"data": {
"tier": "starter",
"monthlyLimit": 10000,
"currentUsage": 2500,
"usagePercentage": 25,
"periodStart": "2025-01-01T00:00:00Z",
"periodEnd": "2025-01-31T23:59:59Z"
}
}
Set Up Usage Alerts
Configure alerts in your Dashboard:
- 80% usage warning email
- 90% usage warning email
- 100% usage notification
FAQ
Why am I being rate limited?
Common causes:
- Too many concurrent requests
- No delay between requests
- Missing backoff logic on errors
Can I request higher limits?
For usage beyond 10,000 calls/month, contact sales@ctwise.ai for custom enterprise plans.
Do rate limits apply to test keys?
Yes, test keys have the same rate limits as live keys to ensure realistic testing.
Is there a burst allowance?
No burst allowance currently. Requests are measured on a per-second basis.