Rate Limiting

OutScope implements fair usage rate limiting to ensure platform stability and prevent abuse.

Rate Limit Tiers

TierPer-MinuteConcurrentMonthly Quota
Free30 req/min5 inflight1,000 checks
Pro60 req/min15 inflight10,000 checks
Enterprise120 req/min30 inflightUnlimited

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

Need Help?

Can't find what you're looking for? We're here to help.