Skip to main content

Documentation Index

Fetch the complete documentation index at: https://bavlio.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Bavlio enforces per-key rate limits on requests authenticated with an API key. The limit varies by plan tier. Headers tell you the current state.

Headers

HeaderDescription
X-RateLimit-LimitYour current per-window limit (an integer).
X-RateLimit-ResetUnix epoch seconds at which the current window resets.
Retry-AfterPresent only on 429 responses. Seconds to wait before retrying.
There is no X-RateLimit-Remaining header. Compute remaining requests yourself by tracking your own send count within the current window if you need an in-flight estimate. The headers above are sent on every response (where available).

Caveats

  • API-key auth only. Requests authenticated with a Supabase JWT (dashboard sessions) do not get rate-limit headers and follow a different limit.
  • Redis-backed. Rate limiting depends on Redis. If Redis is unavailable, Bavlio fails open: requests proceed, but no headers are set. This is a deliberate tradeoff; reliability beats strict enforcement during infrastructure incidents.
  • Per-key, not per-IP. Limits are scoped to your API key. Two keys on the same workspace each have their own bucket.

Example 429 response

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Reset: 1746590160
Retry-After: 13
Content-Type: application/json

{
  "detail": "RATE_LIMITED",
  "message": "Too many requests; retry after 13s"
}

Backoff pattern

Honor Retry-After exactly on 429. On 5xx, exponential backoff capped at a few attempts.
Python
import time
import httpx

def call_with_backoff(client, method, path, *, max_retries=5, **kwargs):
    """Retry on 429 and 5xx with exponential backoff."""
    for attempt in range(max_retries):
        response = client.request(method, path, **kwargs)
        if response.status_code < 400:
            return response
        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", "1"))
            time.sleep(retry_after)
            continue
        if 500 <= response.status_code < 600:
            time.sleep(2 ** attempt)
            continue
        response.raise_for_status()
    response.raise_for_status()

See also

Errors & Idempotency

Full status code taxonomy, retry rules, and current idempotency state.

Quickstart

Minimal happy-path agent integration.