Skip to main content
Rate limits protect the platform and ensure fair resource allocation. This page covers request and sending limits enforced by the Email API, and how to request increases.

Request and message size limits

Three different ceilings apply at three different layers. They are frequently confused — only the first two reject a message.
The edge caps are not the request body limit. They are the Edge gateway’s replay caps for idempotency-keyed requests. A keyed request over the cap is rejected at the Edge with 413 Payload Too Large — it never reaches the Email API. Unkeyed requests bypass these caps entirely. The limits that actually reject a message are the 1 MB decoded body and 25 MB total message, enforced by the Email API, which return 422. The batch endpoint’s edge cap is 20 MB (single sends: 8 MB) — so a keyed batch must satisfy both the 1,000-item ceiling and the 20 MB encoded-request ceiling; chunk by whichever limit is reached first. See the Batch Sending guide.
Attachments are base64-encoded in the request, so a 25 MB message occupies roughly 33 MB on the wire. The Email API measures decoded bytes, so budget against the decoded size, not the encoded payload. A batch send with more than 1,000 messages is rejected with 400:

Request rate limits

API requests are rate-limited at the Telnyx API edge. Exact per-endpoint rates depend on your account tier and are not fixed platform-wide constants — if you need a specific sustained request rate, contact support to confirm or raise your account’s limits. When you exceed the limit, you’ll receive 429 Too Many Requests.
Not every Email API 429 carries a Retry-After header. The sender-domain ramp rejection (domain_graduation_limit_exceeded) is the one Email API 429 that sets Retry-After — in seconds, to the domain’s midnight UTC reset. The account daily limit (10011) and reputation suspension (reputation_suspended) never set it, and edge-level request-rate 429s return the Envoy draft-03 x-ratelimit-* header family instead (x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset in seconds). Honor Retry-After or x-ratelimit-reset when present, branch the API’s own 429s by error code as described below, and otherwise fall back to exponential backoff with jitter. Never block on parsing a header that is not there.

Not every 429 is a rate limit

Three distinct conditions return 429, and they need different handling. Branch on the error code, never on the status alone. All three API-level rejections happen before message creation — no message record, no recipients, no events, no billing, no MTA injection.

Reputation-based suspension

Separate from request rate limiting, sending can be suspended when a domain’s reputation band drops to poor. This returns 429 with code reputation_suspended:
See Deliverability and Domain Warm-up for reputation guidance and recovery steps.

Daily send limit

When an account exceeds its daily send quota, the send is rejected with 429 and code 10011:
The quota is counted in recipients, not API requests — a single request to five addresses consumes five slots. Suppressed recipients are filtered out before the count, so they don’t consume quota. Sandbox sends are exempt.

Sender-domain warm-up ramp

Separate from the account quota, a verified custom sending domain on shared egress is subject to a per-domain warm-up ramp: a daily recipient limit that opens low and steps up as the domain accumulates volume days, until the domain graduates to unrestricted sending. Dedicated-IP routes and Telnyx-managed shared domains bypass the ramp. The current ramp schedule and its enforcement status are covered in Deliverability and Domain Warm-up. The ramp applies after the account daily quota, and both are recipient-count limits:
  • Account quota is checked first. If the account daily limit is exceeded, you get 10011 and the domain ramp is never consulted.
  • Both limits count the same recipients — total to/cc/bcc after suppressed recipients are filtered out. Whichever headroom is lower wins: a send that fits the account quota but exceeds the ramp’s remaining daily allowance is rejected with 429 and code domain_graduation_limit_exceeded.
  • The rejection happens before message creation — no message record, no recipients, no events, no billing, no MTA injection.
  • The response carries the Retry-After header in seconds (to the midnight UTC reset), and the error meta may include retry_after_seconds and remaining_today. Both fields are omitted when unknown.
  • Sandbox sends and sends scheduled with scheduled_at bypass admission at request time — a scheduled send is evaluated against the ramp when it fires, not when it is accepted.
The ramp identity is the registrable organizational domain, so sibling subdomains (for example mail.example.com and news.example.com) share one daily allowance. Days with no admitted volume do not advance the ramp, and a reputation warning pauses advancement without changing the current cap.

Destination provider throttling

Beyond the limits above (which protect the Telnyx platform), receiving providers like Gmail, Outlook, and Yahoo impose their own rate limits on incoming mail. The Telnyx outbound MTA handles destination-side pacing automatically — you do not need to build client-side throttling for provider rate limits. When you send faster than a destination provider accepts, the MTA automatically queues the overflow in its local queue and delivers it as the rate window opens. Queued messages are not returned as failures — they remain in the queue and deliver once the receiving provider accepts them.
Destination throttling is automatic, but it is not a substitute for good sending practices. You still need to warm up new domains, monitor your reputation, and stay within your account sending quota and API request rate limits. A sustained burst that exceeds the 72-hour queue lifetime will cause messages to expire undelivered.

Per-provider delivery rates

The MTA paces outbound delivery based on the recipient’s domain: The retry interval is the delay between delivery attempts when a transient failure occurs. The max interval between retries is the upper bound for exponential backoff — the delay grows between retries up to this cap. Messages remain in the queue for up to 72 hours total; only messages that exceed this lifetime are expired.
These caps match recipient domains, not the email provider behind them. A company that uses Google Workspace on their own domain (e.g., user@company.com) is paced at the default rate (1,000/hour), not the Gmail rate — because the recipient domain is company.com, not gmail.com.

What this means for senders

The API accepts messages that pass validation and applicable limits (single sends return 202 Accepted; batch sends return 207 Multi-Status with per-message results). The actual delivery pace is managed downstream by the MTA — you can submit messages without worrying about exceeding destination-side rate limits. Rate-cap overflow is silent — the MTA holds excess messages in its local queue and delivers them as the rate window opens, following the normal email.queued → email.sending → email.sent → email.delivered event sequence. No separate event is emitted for queue pacing. If a receiving server returns a transient failure (e.g., a 4xx SMTP response), the MTA retries automatically using exponential backoff (up to the max interval between retries in the table above) and emits an email.deferred event. Successful retry then emits email.delivered. If the message ultimately cannot be delivered within the 72-hour queue lifetime, it expires and emits an email.bounced event (the recipient status is expired, but the webhook event type is bounced). Do not resubmit deferred messages — the MTA handles retries automatically.
Destination throttling and your account sending quota operate on different time scales. The per-provider caps above are hourly delivery rates; the daily send limit is a 24-hour recipient count. Both apply independently — a provider cap doesn’t reduce your daily quota, and your daily quota doesn’t raise the provider cap. See Sending quotas for account-level limits.
Reputation-based throttling stacks on top of provider caps. If your sending domain’s reputation band drops to warn, the MTA halves the delivery rate for queues carrying that domain’s mail. At poor, new sends are rejected at the API with 429 reputation_suspended before reaching the MTA. See Reputation-based suspension above and Deliverability & Warm-up for reputation guidance.

Sending quotas

Sending quotas vary by account tier. Contact your account manager for your current quota.
Sandbox mode (sandbox_mode: true) lets you test the full send flow — validation, event creation, webhook firing — without actually delivering the message. Sandbox sends do not consume daily quota and are not billed.

Billing

Outbound messages are billed per recipient accepted into the outbound MTA queue. A message addressed to five recipients is therefore up to five billable sends — one for each recipient the MTA accepts. Recipients that fail before reaching the queue are not billable:
  • Suppressed recipients (filtered before the send).
  • Gateway rejections — the MTA refused the recipient at injection.
  • Sandbox sends — nothing is delivered.
  • System failures and cancellations that occur while the recipient is still pre-queue.
So a five-recipient send where two addresses are suppressed and one is rejected at injection bills for two, not five. Recipient-level outcomes are visible in the recipient_statuses counts on the message resource and in per-recipient webhooks. See your rate card or contact your account manager for pricing details.

High-volume sending patterns

Batch sending

For high-volume sending, use the batch endpoint to reduce API calls:
curl
  • Up to 1,000 messages per batch request.
  • The Idempotency-Key header applies to the entire batch — reuse it only for exact retries of the same batch body.
  • After request-wide admission gates pass, per-message outcomes return 207 Multi-Status; see Batch Sending and Error Codes.

Scheduled sending

Spread load over time using scheduled_at:
The message is saved with status: "scheduled" and dispatched at the specified time.
scheduled_at must be a future ISO 8601 timestamp. A value in the past, or one that fails to parse, is rejected with HTTP 422 — it is never converted into an immediate send. In batch sends, the invalid item is reported in the 207 per-item errors array while the other items continue. The legacy field name send_at is still accepted as a fallback, but scheduled_at is the canonical name.
Scheduled sends do not consume daily quota at request time. Quota is reserved when the scheduled worker actually fires, not when you submit the request. This means a scheduled send can be accepted today and still be rejected at fire time if the daily limit is exhausted then — in which case the message is marked failed and a message-scoped daily_limit_exceeded event is recorded instead of returning a 429; detect that outcome through GET /email_events. The sender-domain warm-up ramp is also evaluated at fire time, with no HTTP 429 because no request is in flight. A ramp rejection terminalizes each recipient as failed with reason sender_domain_graduation_rejected; a fail-closed graduation dependency failure that exhausts its retries uses reason sender_domain_graduation_unavailable. Both create recipient-scoped email.failed events, the parent can roll up to completed, and no MTA injection occurs. Detect those outcomes through polling or recipient-scoped email.failed webhooks. Sandbox sends remain exempt from request-time quota reservation.

Requesting limit increases

To increase your sending quotas or request rates:
  1. Contact your account manager or Telnyx support.
  2. Provide your expected sending volume (messages/day, messages/second).
  3. Have your domain(s) verified and warmed up (see Deliverability).
Contact your account manager for current quotas, pricing, and increase timelines.