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.
8 MB is not the request body limit. It is the Edge gateway’s replay cap for idempotency-keyed requests. A keyed request over 8 MB is rejected at the Edge with 413 Payload Too Large — it never reaches the Email API. Unkeyed requests bypass this cap 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.
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 50 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.
Do not assume a Retry-After header is present. The Email API’s own 429 responses — daily send limit and reputation suspension — do not set Retry-After. Honor the header when it is present (edge-level rate limiting may supply it) and fall back to exponential backoff with jitter when it is absent. Never block on parsing a header that may not be there.

Not every 429 is a rate limit

Two very different conditions return 429, and they need opposite handling. Branch on the error code, never on the status alone. Both 10011 and reputation_suspended are rejected before message creation — no message record, 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.

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 50 messages per batch request.
  • The Idempotency-Key header applies to the entire batch — reuse it only for exact retries of the same batch body.
  • Partial success returns 207 Multi-Status with per-message results. See 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 silently ignored — the message is sent immediately as a normal send, with no error and no scheduled status. There is no validation error to catch, so validate the timestamp client-side before submitting. 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 daily_limit_exceeded event is recorded rather than a 429 being returned to you. Poll for that event type via GET /email_events to detect it; it is not available as a webhook subscription. Sandbox sends are likewise 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.