Rate limits | Brixus365 Docs
Docs Errors Rate limits

Rate limits

Brixus365 enforces two kinds of limits: per-minute request limits (preview accounts only) and monthly send quotas (all accounts). Both return HTTP 429 with a Retry-After header. See Errors for the full error envelope shape.


Response headers

On preview-account requests, every API response includes rate-limit headers:

HeaderTypeDescription
X-RateLimit-LimitintegerMaximum requests allowed in the current window.
X-RateLimit-RemainingintegerRequests remaining before you hit the limit.
X-RateLimit-Resetunix timestampUTC timestamp when the current window resets.
X-RateLimit-WindowintegerWindow duration in seconds.

These headers reflect the per-minute window. Full accounts do not enforce per-minute limits and do not receive these headers.


Send limits

Account typePer-minuteDailyMonthly
Preview account (bx_test_* key)10 requests50 emails1,500 emails
Free account9,000 emails
Paid plansSee Pricing

Preview accounts are created via the sign-up API for quick evaluation. Create a free account to lift the per-minute and daily limits.


Per-minute rate limit

Preview accounts are limited to 10 requests per minute per API key. When exceeded:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 47
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1746458820
X-RateLimit-Window: 60
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Try again in up to 1 minute.",
    "type": "rate_limit_error",
    "retry_after_seconds": 47,
    "details": {
      "limit": 10,
      "window_seconds": 60
    }
  }
}

Wait the value of Retry-After (or error.retry_after_seconds) before retrying. The window is 60 seconds; retrying immediately returns another 429.


Daily send limit

Preview accounts are limited to 50 emails per day. Once the daily limit is reached, wait for the daily reset or create a free account to lift the limit.

{
  "error": {
    "code": "daily_limit_exceeded",
    "message": "Daily limit of 50 emails reached. Upgrade to send more.",
    "type": "rate_limit_error",
    "upgrade_url": "https://brixus365.com/pricing",
    "details": {
      "limit": 50,
      "used": 50
    }
  }
}

Monthly send quotas

When the monthly limit is reached, the API returns 429 regardless of account type:

{
  "error": {
    "code": "monthly_limit_exceeded",
    "message": "Monthly limit of 9000 emails reached.",
    "type": "rate_limit_error",
    "upgrade_url": "https://brixus365.com/pricing",
    "details": {
      "limit": 9000,
      "used": 9000
    }
  }
}

Monthly quotas reset on the first day of each calendar month.


Handling rate limits in code

Honour Retry-After for per-minute limits; distinguish quota exhaustion (which requires a plan upgrade, not a wait):

import time
import requests

def send_with_retry(api_key, payload, max_retries=3):
    for attempt in range(max_retries):
        resp = requests.post(
            "https://app.brixus365.com/api/v1/emails/send",
            headers={"X-API-Key": api_key},
            json=payload,
        )
        if resp.status_code != 429:
            resp.raise_for_status()
            return resp.json()

        err = resp.json().get("error", {})
        code = err.get("code")

        if code in ("daily_limit_exceeded", "monthly_limit_exceeded"):
            raise RuntimeError(
                f"Send limit reached — upgrade at {err.get('upgrade_url')}"
            )

        wait = int(resp.headers.get("Retry-After", 60))
        if attempt < max_retries - 1:
            time.sleep(wait)
            continue

    raise RuntimeError("Rate limit retries exhausted")

What’s next

You want to…Go to
See every error code with description and suggested actionError codes
Understand the error envelopeErrors
Upgrade your accountPricing
Start sending

9,000 transactional emails a month, free.

No credit card. No commitment. Knowing the limits means you’ll never hit them unexpectedly.