Reference

Rate limits

Every response tells you exactly how much capacity you have left. Read the headers, back off on 429, and your integration never trips the limiter.

Sendara meters requests with a sliding window. Each API key inherits your account's per-second budget, and every response — success or failure — carries X-RateLimit-* headers so you always know where you stand without guessing.

How it works

Limits are enforced per account over a rolling one-second window using a sliding-window log, so the budget refills continuously rather than resetting in a single burst at the top of each second. Requests authenticated with any of your keys — live or test — count against the same account budget.

  • Free — 10 requests / second
  • Pro — 100 requests / second
  • Scale — 500 requests / second
Need a higher ceiling for a launch or migration? These are soft defaults — reach out and we'll raise your account limit.

Rate limit headers

Read these from any response to track your remaining budget. The first three are present on every request; Retry-Afterappears only when you've been limited.

X-RateLimit-LimitintegerOptional
The maximum number of requests allowed in the current window for your account's plan.
X-RateLimit-RemainingintegerOptional
Requests left in the current window. When this reaches 0, the next request is rejected with 429 until the window slides forward.
X-RateLimit-ResetintegerOptional
Unix timestamp (seconds) at which the current window resets and capacity is restored.
Retry-AfterintegerOptional
Only on a 429 response. Seconds to wait before retrying. Honor this value before sending again.
The three X-RateLimit-* headers are CORS-exposed, so browser-side callers can read them directly from fetch responses — no proxy required.

Reading the headers

A normal response decrements X-RateLimit-Remaining. When it hits 0, the next request returns 429 Too Many Requests with a Retry-After telling you how long to wait.

Inspecting your remaining budget

You don't need to wait for a 429 to react — watch X-RateLimit-Remaining on the responses you already get and slow down as it approaches zero.

The 429 response

When you exceed the limit, Sendara returns the standard error envelope with code rate_limit_exceeded and HTTP status 429. The response includes a Retry-After header (in seconds) — always honor it before retrying.

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded",
    "status": 429
  }
}
A 429 means the request was not processed — no email was sent and nothing was billed. It is always safe to retry after waiting. Because each send carries an idempotency_key, retries can never double-send even if a response is lost.

Recommended: exponential backoff

Wrap your client in a retry loop that respects Retry-After and falls back to exponential backoff with jitter. Jitter spreads retries out so a fleet of workers doesn't all wake up and hammer the API in lockstep.

The official Node and Python SDKs already retry 429 (and transient 5xx) responses with backoff and jitter built in — if you use them, you get this for free.

Best practices

  • Prefer batch endpoints. Use POST /v1/send/batch to send many messages in a single request instead of one call per recipient — one request, one slot against your limit.
  • Watch the headers, don't race the limit. Throttle proactively as X-RateLimit-Remaining trends toward zero rather than waiting to be rejected.
  • Always honor Retry-After. It reflects exactly when capacity returns; retrying sooner just earns another 429.
  • Add jitter.Randomize backoff delays so concurrent workers don't synchronize their retries.
  • Keep idempotency keys on retries. Reuse the same idempotency_key when you retry a send so a lost response never turns into a duplicate email.