Simple Agent
Docsapi

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

API Errors → · Authentication → · Webhooks →