REST API 4 min read

Errors, Rate Limits & Pagination

Error response shape

All errors use the same envelope:

{
  "error": {
    "code": "validation_error",
    "message": "site_id is required"
  }
}

The HTTP status code complements the code field — the code is stable for programmatic handling; the message is human-readable and may change.


Error codes

HTTP Code When
400 validation_error Required field missing or invalid (e.g. unknown status value, no body fields to update)
401 unauthorized Missing/malformed Authorization header, key not found, key deactivated, or workspace api_enabled=false
404 not_found Resource doesn't exist or belongs to another workspace. No endpoint matches the URL
429 rate_limit_exceeded More than 60 requests/min on this key. See headers below
500 internal_error Unhandled server error — report to [email protected] with the request ID
502/504 upstream_error Downstream service (idea generator, experiment engine) failed. Safe to retry with backoff

Rate limits

Budget: 60 requests per minute per API key (sliding window).

Response headers (always present):

Header Meaning
X-RateLimit-Limit 60 (your per-minute budget)
X-RateLimit-Remaining Requests left in the current window
X-RateLimit-Reset Unix timestamp (seconds) when the window resets

On 429:

HTTP/1.1 429 Too Many Requests
Retry-After: 37
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1714147237

{"error":{"code":"rate_limit_exceeded","message":"Rate limit exceeded"}}

Recovery: sleep for Retry-After seconds, then resume. If you need sustained higher throughput, contact support about a custom limit.


Retry strategy

Treat these as retryable with exponential backoff + jitter:

  • 429 — respect Retry-After
  • 500, 502, 503, 504 — retry up to 3 times, starting at 1s, doubling each attempt
  • Connection errors (timeouts, TCP resets)

Treat as not retryable:

  • 400, 401, 404 — fix the request, don't retry
  • 402 — not used by the REST API (it's reserved for the agent gateway's insufficient-credits case)

Pagination

List endpoints (/v1/ideas, /v1/experiments) use offset pagination:

Param Type Default Max
limit integer 20 100
offset integer 0

Results are always sorted created_at DESC. To paginate:

# Page 1
curl "https://api.abtestbot.com/v1/ideas?site_id=<uuid>&limit=50&offset=0"

# Page 2
curl "https://api.abtestbot.com/v1/ideas?site_id=<uuid>&limit=50&offset=50"

When data.length < limit, you've reached the end.


CORS

The API is CORS-enabled for browser usage:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type

Warning: this means raw API keys can technically be used from a browser, but you should never ship sk_live_ keys to client-side code. Proxy through your own backend.