Rate Limiting
OutScope implements fair usage rate limiting to ensure platform stability and prevent abuse.
Rate Limit Tiers
| Tier | Per-Minute | Concurrent | Monthly Quota |
|---|---|---|---|
| Free | 30 req/min | 5 inflight | 1,000 checks |
| Pro | 60 req/min | 15 inflight | 10,000 checks |
| Enterprise | 120 req/min | 30 inflight | Unlimited |
How Rate Limits Work
Per-Minute Limits
You can make N requests per minute. Once exceeded, you’ll receive a 429 response.
Concurrent Limits
Maximum number of checks running simultaneously. Additional requests are queued.
Monthly Quotas
Total number of checks per billing cycle. Resets on the 1st of each month.
Rate Limit Headers
Every API response includes rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640000000
Retry-After: 30
Handling Rate Limits
Manual Handling
import requests
import time
response = requests.post("https://api.outscope.es/v1/check", ...)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
# Retry request
Automatic with SDK
The Python SDK handles rate limits automatically:
from outscope_sdk import Client
client = Client(api_key="svc_your_key")
# SDK automatically waits on rate limits
result = client.checks.create_batch(
domains=["example1.com", "example2.com", ...],
wait_on_limits=True # ← Automatically handles 429 responses
)
Best Practices
1. Batch Operations
Instead of:
# ❌ Bad: Individual requests
for domain in domains:
client.checks.create(fqdn=domain)
Do this:
# ✅ Good: Batch request
client.checks.create_batch(domains=domains)
2. Respect Retry-After
Always honor the Retry-After header value.
3. Implement Backoff
Use exponential backoff for retries:
import time
def create_check_with_retry(client, fqdn, max_retries=3):
for attempt in range(max_retries):
try:
return client.checks.create(fqdn=fqdn)
except RateLimitError as e:
if attempt == max_retries - 1:
raise
wait = 2 ** attempt # 1s, 2s, 4s
time.sleep(wait)
4. Monitor Your Usage
Check remaining quota:
info = client.account.info()
print(f"Monthly quota used: {info['quota_used']}/{info['quota_limit']}")
Upgrade Your Limits
Need higher limits? Contact sales for Enterprise plans with:
- 120+ requests/minute
- 30+ concurrent checks
- Unlimited monthly quota
- Priority support