DocsapiRead endpoints (
Write endpoints (
Chat endpoint (
Rate Limits
Request limits by plan, control headers, and strategies for handling 429s.
The Simple Agent API uses rate limiting per API key, with different limits by endpoint type and plan.
Limits by plan
Read endpoints (GET)
| Plan | Requests/min | Requests/day |
|---|---|---|
| Starter | 60 | 2,000 |
| Growth | 300 | 20,000 |
| Agency | 1,000 | Unlimited |
Write endpoints (POST, PUT, DELETE)
| Plan | Requests/min | Requests/day |
|---|---|---|
| Starter | 20 | 500 |
| Growth | 100 | 5,000 |
| Agency | 500 | Unlimited |
Chat endpoint (POST /v1/chat)
The chat endpoint has separate limits based on messages processed:
| Plan | Messages/month |
|---|---|
| Starter | 2,000 |
| Growth | 20,000 |
| Agency | 100,000+ (see plan) |
Rate limit headers
Every API response includes headers with your current limit status:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 247
X-RateLimit-Reset: 1715686800
X-RateLimit-Policy: sliding-window-60s
| Header | Description |
|---|---|
X-RateLimit-Limit |
Total limit in the current window |
X-RateLimit-Remaining |
Remaining requests |
X-RateLimit-Reset |
Unix timestamp when the limit resets |
X-RateLimit-Policy |
Algorithm: sliding-window-60s or token-bucket |
Response when the limit is reached
HTTP 429 Too Many Requests:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Try again in 18 seconds.",
"retry_after": 18,
"reset_at": "2026-05-14T10:30:18Z"
}
}
How to handle 429s
Retry with exponential backoff
import time
import requests
def call_with_retry(url, headers, payload, max_retries=3):
for attempt in range(max_retries):
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 429:
retry_after = int(response.json()["error"]["retry_after"])
wait = retry_after * (2 ** attempt) # exponential backoff
print(f"Rate limited. Waiting {wait}s...")
time.sleep(wait)
continue
return response
raise Exception("Max retries exceeded")
async function callWithRetry(url: string, options: RequestInit, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const res = await fetch(url, options);
if (res.status === 429) {
const data = await res.json();
const wait = data.error.retry_after * Math.pow(2, attempt);
await new Promise(r => setTimeout(r, wait * 1000));
continue;
}
return res;
}
throw new Error("Max retries exceeded");
}
Check the header before making the request
const remaining = parseInt(response.headers.get("X-RateLimit-Remaining") ?? "0");
const resetAt = parseInt(response.headers.get("X-RateLimit-Reset") ?? "0");
if (remaining < 5) {
const waitMs = (resetAt - Date.now() / 1000) * 1000;
await new Promise(r => setTimeout(r, waitMs));
}
Per-IP limits (abuse protection)
In addition to per-API-key limits, Simple Agent blocks IPs with anomalous behavior:
- More than 1,000 requests/min from a single IP → 5-minute temporary block
- Detected scraping pattern → 24-hour block with email notification
Increasing limits
For limits above the standard Agency plan (e.g., high message volume in a product), contact support@simple-agent.me with:
- Estimated messages/month volume
- Use case
- Peak usage time window