Email Messages

Create or send an email message

Queues, schedules, or sandbox-sends an email message. The legacy /v2/emails POST route is a backward-compatible alias for this operation.

subject is required unless template_id is supplied. When using template_id, do not also provide subject, html_body, or text_body; the template is rendered with template_variables.

Note: template lookup failures (not found, wrong account) return 400, not 404.

post/email_messages

Headers

Idempotency-Keystring

Optional opaque, unquoted key for safely retrying the same logical request. Keys must contain 1 to 255 letters, numbers, hyphens, or underscores. Generate a unique UUID v4 for each operation and reuse it only when retrying that operation with the same request. Invalid headers—including duplicate, empty, malformed, or overlong values—return 400 with error code 10015. A request already in progress with the same key returns 409; reusing the key with a different request returns 422. Only successful responses are replayed, for up to 24 hours. Do not include sensitive data in the key.

Request body

from_namestring

Optional display name for string from; overrides from.name when provided.

subjectstring

Required unless template_id is supplied. When using a template, the template's subject is rendered; if the template has no subject or renders empty, the request returns 400.

html_bodystring

HTML email body. Returned only by GET /email_messages/{id}; omitted from create and list responses.

text_bodystring

Plain text email body. Returned only by GET /email_messages/{id}; omitted from create and list responses.

headersobject

Custom email headers. Write-only; not returned in responses.

tagsstring[]

Tags for categorization and filtering. Stored on the message, returned on message responses, and propagated to Email Detail Records. Usable in filter[tags] when listing messages.

group_idstring uuid nullable

Optional unsubscribe-group UUID used for group-scoped suppression checks and unsubscribe handling.

ignore_suppressionboolean

When true, allows delivery to recipients whose suppressions explicitly permit an override. Hard bounces, spam complaints, and invalid-address suppressions cannot be overridden. Requires the email:override API scope.

metadataobject

Custom metadata key/value pairs. Stored on the message, returned on message responses, and propagated to Email Detail Records. Usable in filter[metadata] when listing messages.

template_idstring uuid
template_variablesobject

Variables for Liquid template rendering. Non-object values may cause a 422 validation error on message creation, but are silently treated as an empty object for template rendering. When the template enables strict_variables, a missing required variable fails the request with 422 (single send) or a per-item unprocessable_entity error (batch) naming the variable; no message is persisted for the failed item.

scheduled_atstring date-time nullable

Future ISO 8601 delivery time. Invalid or non-future timestamps are rejected. Single sends return HTTP 422; in batch sends the invalid item is reported in the 207 per-item errors while other items continue. send_at remains a deprecated request alias. A non-null scheduled_at takes precedence over send_at; when scheduled_at is omitted or null, send_at is used.

send_atstring date-time

Deprecated alias for scheduled_at.

inline_cssboolean
sandbox_modeboolean

Validates and accepts the message without injecting it into the MTA or outbound Kafka path. Nothing is delivered: sandbox records are non-billable, consume no daily-send-limit quota, and feed no delivery-reputation signals.

The reserved sandbox test-recipient domain is test.telnyx.com. In sandbox mode, these addresses produce deterministic recipient-scoped lifecycle events:

  • delivered@test.telnyx.com: queued -> sending -> sent -> delivered
  • hard-bounce@test.telnyx.com: queued -> sending -> sent -> bounced (permanent)
  • soft-bounce@test.telnyx.com: queued -> sending -> sent -> bounced (transient)
  • complaint@test.telnyx.com: queued -> sending -> sent -> complained
  • suppressed@test.telnyx.com: queued -> suppressed
  • invalid@test.telnyx.com: queued -> sending -> failed (invalid recipient)
  • dkim-fail@test.telnyx.com: queued -> sending -> failed (DKIM unavailable)
  • rate-limit@test.telnyx.com: queued -> sending -> failed (rate limit exceeded)

Matching is case-insensitive for both the local part and the domain and requires the exact domain test.telnyx.com — subdomains and other domains do not match. Mixed sandbox sends simulate only reserved test recipients; other recipients retain ordinary sandbox behavior (accepted, no delivery attempted). Hard-bounce and complaint outcomes also use the normal automatic-suppression pipeline. Non-sandbox sends to these addresses use the normal delivery path.

in_reply_to_message_idstring uuid nullable

Telnyx message UUID of the message this send replies to. When provided, the API sets RFC 5322 In-Reply-To and References headers on the outbound MIME so the recipient's mailbox (Gmail/Outlook) threads it correctly. The parent is looked up under the caller's account scope; a UUID belonging to another account yields a non-enumerating 404.

Wire-only (Phase 1): the API sets the headers and does NOT resolve or mutate thread_id on the server side. Messages sent without this parameter are standalone (no threading headers injected).

Cannot be combined with forward_of_message_id (422).

reply_to_allboolean nullable

Indicates a reply-all intent. In Phase 1 (wire-only) this does not change the threading headers — recipient selection is customer- controlled (to/cc), and a thread is not defined by its audience. When the referenced message has no thread context, reply-all degrades to a plain reply (parent ID only in References). The resolution engine (separate work) will expand the ancestor chain at a later phase with no API change.

Only meaningful alongside in_reply_to_message_id.

forward_of_message_idstring uuid nullable

Telnyx message UUID of the message this send forwards. Forwarded messages start a NEW thread per RFC 5322 — NO In-Reply-To or References headers are set on the outbound MIME. The id is recorded in the message's metadata for EDR provenance only.

The id is validated as a UUID but is NOT looked up against the message store — existence is the caller's responsibility (the forward is pure metadata; it does not affect delivery). Cannot be combined with in_reply_to_message_id (422).

Response

Message queued, scheduled, or sandbox-created.

Example response

{
  "data": {
    "recipient_statuses": {
      "delivered": 998,
      "bounced": 2
    }
  }
}

Changes

Changed in 10 of the 99 revisions of this API.86033

  • 16bfa298dc71102See the full diff
    • ●

      added the new expired enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new gw_reject enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new injection_timeout enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new quarantine_expired enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new quarantine_rejected enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new quarantine_release_dispatched enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new quarantine_released enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new quarantined enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new scan_deferred enum value to the /// response property for the response status

      response-property-enum-value-added

    • ●

      added the new suppressed enum value to the /// response property for the response status

      response-property-enum-value-added

    • ○

      added the required property / to the response with the status

      response-required-property-added

    • ○

      added the required property / to the response with the status

      response-required-property-added

    This revision also has 1 change that name no endpoint, such as unreferenced schemas being removed. See the revision's changelog

  • 9621f6123ebc217See the full diff
    • ▲

      added to the response body oneOf list for the response status

      response-body-one-of-added

    • ▲

      the response's body type changed from object to no type for status

      response-body-type-changed

    • ●

      removed the optional property from the response with the status

      response-optional-property-removed

    • ●

      added the new 10011 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10011 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10011 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10011 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10011 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10011 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10011 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10011 enum value to the ////// response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new domain_graduation_limit_exceeded enum value to the ////// response property for the response status

      response-property-enum-value-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    This revision also has 34 changes that name no endpoint, such as unreferenced schemas being removed. See the revision's changelog

  • b1bf96d8391e1317See the full diff
    • ▲

      removed the required property / from the response with the status

      response-required-property-removed

    • ●

      removed the optional property / from the response with the status

      response-optional-property-removed

    • ●

      removed the optional property / from the response with the status

      response-optional-property-removed

    • ●

      added the new daily_limit_exceeded enum value to the /// response property for the response status

      response-property-enum-value-added

    • ○

      added the new optional request property //

      new-optional-request-property

    • ○

      added the new optional request property //

      new-optional-request-property

    • ○

      added the new optional request property

      new-optional-request-property

    • ○

      added the new optional request property

      new-optional-request-property

    • ○

      added the new optional request property

      new-optional-request-property

    • ○

      added the new optional request property

      new-optional-request-property

    • ○

      added the new optional request property

      new-optional-request-property

    • ○

      the request property became nullable

      request-property-became-nullable

    • ○

      request property deprecated

      request-property-deprecated

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the optional property / to the response with the status

      response-optional-property-added

    • ○

      added the required property /// to the response with the status

      response-required-property-added

    • ○

      added the required property /// to the response with the status

      response-required-property-added

    • ○

      added the required property /// to the response with the status

      response-required-property-added

    • ○

      added the required property /// to the response with the status

      response-required-property-added

    • ○

      added the required property /// to the response with the status

      response-required-property-added

    • ○

      added the required property / to the response with the status

      response-required-property-added

    • ▲

      added to the response body oneOf list for the response status

      response-body-one-of-added

  • 2fb3b617430a169See the full diff
    • ●

      added the new recipient_suppressed enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new recipient_suppressed enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new recipient_suppressed enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new recipient_suppressed enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new recipient_suppressed enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new recipient_suppressed enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new recipient_suppressed enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new recipient_suppressed enum value to the ////// response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new reputation_suspended enum value to the ////// response property for the response status

      response-property-enum-value-added

    • ○

      added the optional property //// to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

    • ○

      added the optional property to the response with the status

      response-optional-property-added

  • 021f0faf96df11See the full diff
    • ▲

      for the header request parameter Idempotency-Key, the maxLength was decreased from 512 to 255

      request-parameter-max-length-decreased

    • ●

      changed the pattern of the header request parameter Idempotency-Key from ^(?:[A-Za-z0-9_-]{1,255}|"(?:[\x20-\x21\x23-\x5B\x5D-\x7E]|\\["\\]){1,255}")$ to ^[A-Za-z0-9_-]{1,255}$

      request-parameter-pattern-changed

  • b3c5aebde44c2133See the full diff
    • ▲

      removed the required property / from the response with the status

      response-required-property-removed

    • ▲

      removed the success response with the status

      response-success-status-removed

    • ●

      removed the request property

      request-property-removed

    • ●

      added the new 10027 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10027 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10027 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10027 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10027 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10027 enum value to the ////// response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10036 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10036 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10036 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10036 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10036 enum value to the // response property for the response status

      response-property-enum-value-added

    • ●

      added the new 10036 enum value to the ////// response property for the response status

      response-property-enum-value-added

    • ○

      added the new optional header request parameter Idempotency-Key

      new-optional-request-parameter

    • ○

      added the non-success response with the status

      response-non-success-status-added

    • ○

      added the non-success response with the status

      response-non-success-status-added

    This revision also has 1 change that name no endpoint, such as unreferenced schemas being removed. See the revision's changelog

    • ○

      endpoint added

      endpoint-added

    This revision also has 1 change that name no endpoint, such as unreferenced schemas being removed. See the revision's changelog

    • ▲

      api path removed without deprecation

      api-path-removed-without-deprecation

    This revision also has 111 changes that name no endpoint, such as unreferenced schemas being removed. See the revision's changelog

Of the 99 revisions, 1 has no diff computed.