Docs/Sending email

Headers & custom headers

The headers field carries application-specific headers on a message, such as a reference ID your own systems read back. Headers that carry transport, authentication, or routing meaning are managed by Anypost and cannot be set this way.

Set a header

headers is a name-to-value object on POST /v1/email:

curl https://api.anypost.com/v1/email \
  -H "Authorization: Bearer $ANYPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <[email protected]>",
    "to": ["[email protected]"],
    "subject": "Order confirmed",
    "html": "<p>Your order is on its way.</p>",
    "headers": {
      "X-Order-Id": "1190",
      "X-Entity-Ref": "customer-4471"
    }
  }'

Each pair becomes one header on the delivered message.

Names and values

A header name must be alphanumeric and hyphens only, start with a letter or digit, and be at most 78 characters. A name that breaks those rules is dropped from the map.

A message may carry at most 25 custom headers.

Headers Anypost manages

Some headers are set by Anypost itself, or carry trust signals that a sender cannot legitimately originate. If you include one in headers, it is dropped rather than applied. Use the headers map for your own application headers, not to override transport, identity, authentication, or trace headers.

CategoryExamplesWhy it is managed
Addressing and identityFrom, To, Cc, Bcc, Subject, Reply-To, SenderSet from the request's own fields.
Message metadataDate, Message-ID, MIME-Version, Content-Type, Content-Transfer-Encoding, Content-DispositionSet by Anypost or generated when the message is encoded.
AuthenticationDKIM-Signature, Authentication-Results, Received-SPFOwned by the platform; forging them would misrepresent the message.
TraceReceived, Return-Path, Delivered-To, X-Original-To, and the Resent-* and ARC-* familiesAdded by receiving servers. A sender cannot legitimately originate them.
Loop controlAuto-Submitted, PrecedenceAffect vacation responders and bounce handling.
Anypost-managedX-Campaign and the X-Anypost-* namespaceSet from dedicated request fields that apply their own validation.

For a campaign label, use the top-level campaign field rather than a header: the field is validated, and a header of the same name is dropped. The one carve-out in the X-Anypost-* namespace is X-Anypost-Track-Opens / X-Anypost-Track-Clicks; tracking is covered in Open & click tracking.

What errors, and what is dropped

Header handling is forgiving by design. A malformed name, an over-long or empty value, and a managed header are all dropped silently, so a small mistake never blocks a send.

Exceeding the 25-header cap is the one condition that fails the request: it returns 400 with a validation_error. See API conventions for the error shape.

The trade-off is that a dropped header is not reported back. If a custom header does not arrive, check it against the name and value rules above.

Headers in a batch

In a batch send, a headers map in defaults is shallow-merged with each entry's own map. On a name collision the entry's value wins. The 25-header cap applies to the merged result.

Where to go next