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.

Built for AI agents. Skip the UI screenshots. This page covers everything an agent needs: auth, base URL, first call, errors, idempotency, pagination, polling, rate limits.
All examples use the live production API at https://api.bavlio.com. Replace bav_live_REPLACE_WITH_YOUR_KEY with your real key before running.

1. Get an API key

1

Sign in to bavlio.com

Open bavlio.com/login. Free-tier accounts cannot create keys — upgrade to a paid plan if you see a 403 on creation.
2

Generate a key from Settings → API keys

Click Create key, name it (e.g. production-agent), and copy the full value immediately. The full string is shown only once.
3

Store it as a secret

Set it as BAVLIO_API_KEY in your runtime environment. Never commit it to source. Keys start with bav_live_ followed by 43 URL-safe characters.
By design: API keys cannot mint API keys. Key creation requires a logged-in dashboard session — this prevents a leaked key from cloning itself. Agent provisioning always involves a human-in-the-loop initial setup.

2. Authenticate

Pass the key as a Bearer token in the Authorization header on every request. Base URL: https://api.bavlio.com.
curl -X GET https://api.bavlio.com/api/v1/auth/me \
  -H "Authorization: Bearer bav_live_REPLACE_WITH_YOUR_KEY"

3. Make your first call

List your campaigns. Most list endpoints accept ?offset=0&limit=100 — see Pagination for endpoint-specific patterns.
cURL
curl -X GET "https://api.bavlio.com/api/v1/campaigns/?offset=0&limit=100" \
  -H "Authorization: Bearer bav_live_REPLACE_WITH_YOUR_KEY"

4. Handle errors

Three error envelopes coexist today (a unification migration is on the roadmap). On 4xx, fix the request. On 429, wait Retry-After seconds. On 5xx, retry with exponential backoff. Full taxonomy at Errors.
Python
import time
import httpx

def call_with_backoff(client, method, path, *, max_retries=5, **kwargs):
    """Retry on 429 and 5xx with exponential backoff. Stop on 4xx others."""
    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()

5. Idempotency (current state)

Bavlio does not yet honor the Idempotency-Key header. Sending it has no effect server-side. A retried POST after a network failure will create a duplicate.
Workaround until the middleware ships: after a failed mutation, follow up with a read before retrying. For example, after a failed POST /api/v1/campaigns/, call GET /api/v1/campaigns/?name=<your-name> to check whether your campaign was already created. Match on a stable client-side correlation field. See Errors → Idempotency for the full pattern.

6. Drain a paginated list

Most list endpoints use offset+limit. Some return has_more. Some return the full collection. The helper below handles both common shapes.
Python
def drain_all(client, path, *, page_size=100, **params):
    """Drain a list endpoint that uses offset+limit pagination."""
    offset = 0
    while True:
        response = client.get(path, params={**params, "offset": offset, "limit": page_size})
        response.raise_for_status()
        items = response.json()
        if not isinstance(items, list):
            payload = items
            items = payload.get("items", [])
            yield from items
            if not payload.get("has_more"):
                return
        else:
            yield from items
            if len(items) < page_size:
                return
        offset += page_size

7. Webhooks (poll instead, for now)

Customer-registered outbound webhooks are not yet available. Use polling endpoints for the events agents care about (campaign status, replies, email events). See Webhooks (Polling) for the full guide.

8. Respect rate limits

Bavlio sets X-RateLimit-Limit and X-RateLimit-Reset headers on responses to API-key authenticated requests. On a 429, the Retry-After header tells you exactly how long to wait. There is no X-RateLimit-Remaining header. See Rate Limits.

Copy this for Claude / GPT / Codex

Paste this block into your AI coding assistant to bootstrap a Bavlio integration with the right context.
agent-context.py
# Bavlio API — Quickstart for AI Agents
# Docs: https://bavlio.com/docs/quickstart
# Reference: https://bavlio.com/docs/api-reference/introduction
# OpenAPI: https://api.bavlio.com/openapi.json
#
# Auth: Authorization: Bearer bav_live_...
# Base URL: https://api.bavlio.com
#
# Errors: three envelopes coexist — see /docs/errors for shapes.
# Pagination: endpoint-specific — see /docs/pagination.
# Idempotency-Key header is NOT yet honored — see /docs/errors#idempotency.
# Customer webhooks NOT yet available — poll endpoints listed at /docs/webhooks.
# Rate limits: X-RateLimit-Limit + X-RateLimit-Reset headers; Retry-After on 429.

import os
import httpx

api_key = os.environ["BAVLIO_API_KEY"]
client = httpx.Client(
    base_url="https://api.bavlio.com",
    headers={"Authorization": f"Bearer {api_key}"},
    timeout=30.0,
)

# Identity check
me = client.get("/api/v1/auth/me").raise_for_status().json()
print(f"Authenticated as user_id={me.get('user_id')}")

# List campaigns (offset+limit pagination)
campaigns = client.get("/api/v1/campaigns/", params={"offset": 0, "limit": 100}).json()
print(f"Got {len(campaigns)} campaigns")

FAQ

Pass your API key as a Bearer token: Authorization: Bearer bav_live_<your-key>. Generate keys in your Bavlio dashboard. Keys are scoped to the workspace that created them.
https://api.bavlio.com for the SaaS API. https://api.bavlio.com/api/x402 for x402 pay-per-call endpoints (no auth required).
Bavlio does not yet honor the Idempotency-Key header. For non-mutating reads (GET), retry freely. For mutating writes (POST/PUT/PATCH/DELETE), check the resulting state with a follow-up GET before retrying. The Idempotency-Key middleware is on the roadmap.
Pagination is endpoint-specific. Most list endpoints accept ?offset=0&limit=100. Some return { items, has_more }. Some return the full collection. See Pagination for per-endpoint guidance.
Customer-registered webhooks are not yet available. Poll the campaign stats and BaviMail email-events endpoints in the meantime. See Webhooks for the full polling guide and roadmap.
Rate limits apply only to API-key authenticated requests and depend on Redis availability. The X-RateLimit-Limit and X-RateLimit-Reset headers tell you the current limit window. On 429 the Retry-After header tells you how long to wait.

Next

API Reference

Full OpenAPI 3.1 spec, every endpoint.

Authentication

Key format, rotation, scoping.

MCP

Docs MCP live now; API-action MCP on the roadmap.