Sign inGet started

Rate limits

Rate limits bound how many requests your organization can make in a time window. Use the response headers to pace traffic and the retry delay to recover from a rejected request.

How limits are keyed

Your organization shares one regional limit for each policy, across its API keys and workspaces. Creating another key does not add capacity. Different organizations have separate limits.
Each request consumes one customer policy. Product policies have independent capacity: retrieving message status does not consume the general resource-retrieval limit, and sending an email does not consume the resource-creation limit.
Login, password reset, and other security-sensitive operations have additional abuse protections. Supplier checks and connection limits can also reject requests independently of your plan's rate limits.

Groups

Ordinary API operations use these policies:
PolicyOperations
api_getRetrieve one resource
api_listList or search a collection
api_createCreate a resource
api_updateUpdate or upsert a resource
api_deleteDelete a resource
Product operations use a named policy in place of the ordinary API policy. Examples include email_send, email_batch, sms_send, whatsapp_send, lookup, and message_status_read. Batch policies count submission requests; the batch's recipient count does not consume extra policy units. See email batch sending and SMS batch sending for batch-size limits.
REST email and SMTP submission share email_send capacity. An SMTP DATA submission consumes one unit; SMTP authentication does not. If the policy denies a submission, the server returns temporary 452 4.3.1 with a retry delay and does not accept the message. Keep the message queued and retry after that delay.
Creating a broadcast uses api_create; starting an existing broadcast uses api_update. Background delivery to its recipients does not consume email_send. Sending allowances and delivery pacing remain separate controls.
The voice_call policy limits inbound and outbound call admission. An exhausted policy refuses the call and records calls_per_second_exceeded; no HTTP response is involved. See Rejected calls.

How your limit is resolved

An active organization override sets your effective rate. Without an override, your active plan's value applies; if the plan has no value for that policy, the default applies. A plan or override can raise or lower the rate. The policy's time window stays fixed.
Call GET /v1/organization/rate-limits to read your effective policies, rates, and windows. The response's group field contains the policy key. You can also read the effective quota in the RateLimit-Policy response header. If you need additional capacity, contact support with the policy key and expected traffic.

Response headers

Rate-limit evaluations supply two headers in the IETF Structured Fields format (RFC 9651):
Esempio di codice
RateLimit-Policy: "email_send";q=1000;w=60
RateLimit: "email_send";r=842;t=35
HeaderMeaning
RateLimit-PolicyThe policy that applies: q is the quota (maximum units) and w is the window in seconds.
RateLimitYour current state: r is the number of units remaining and t is the seconds until the window resets.
The quoted string names the policy. In this example, the organization has an effective email_send limit of 1000 submissions per 60 seconds, with 842 remaining and 35 seconds until reset.
Use r and t to slow requests before receiving a 429. The t value is a relative delay in seconds, rather than a Unix timestamp.

When you hit a limit

Your integration must handle 429 responses as part of normal operation. At minimum, honor Retry-After and retry with backoff. A client that also paces itself against the live RateLimit headers (see Response headers) avoids reaching the limit.
An exhausted customer policy returns 429 Too Many Requests with Retry-After in seconds and rate-limit headers showing r=0. An independent abuse or supplier protection can return 429 even when your customer policy has remaining capacity. Follow Retry-After to decide when to retry; it can differ from the policy's t value.
The body uses the standard error envelope:
Esempio di codice
{
  "error": {
    "type": "rate_limit_error",
    "code": "E01003",
    "name": "RateLimited",
    "message": "Too many requests. Please retry after the period indicated in the Retry-After header.",
    "doc_url": "https://bird.com/docs/api/errors/E01003",
    "request_id": "req_01ky7qavkff7qr88vadv6bv948"
  }
}
Branch on type: rate_limit_error. The human-readable message can change. Read the policy key and retry timing from the headers:
async function sendWithBackoff(url, headers, payload, maxAttempts = 5) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const response = await fetch(url, {
      method: "POST",
      headers,
      body: JSON.stringify(payload),
    });
    if (response.status !== 429) return response;
    const retryAfter = Number(response.headers.get("Retry-After") ?? 2 ** attempt);
    await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
  }
  throw new Error("rate limited after max retries");
}
For retries of the same operation, reuse its idempotency key. Keep the request body unchanged.
See SDK concepts for automatic retry and backoff behavior.

Failure mode

The rate limiter fails open: if Bird cannot evaluate a limit, the request proceeds rather than receiving a spurious refusal. Rate limiting protects service capacity. Authentication and authorization remain the security boundaries. A Bird-side limiter outage does not cause a 429.

Next steps

  • Errors: the error envelope and how to branch on error types
  • Idempotency: safe retries for mutating requests
  • SDK concepts: automatic retry and backoff behavior