> ## Documentation Index
> Fetch the complete documentation index at: https://apidoc.mailercloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Personalized Email

> Send transactional or marketing emails with **per-recipient personalization** (mail merge). Same request structure as `POST /email`, plus an optional `merge_vars` object on each `recipients.to[]` entry.

**Personalization:**
- `{{variable}}` placeholders in `subject`, `text`, `html`, `amp_html` and `fromName` are replaced with that recipient's `merge_vars` values.
- In `html`, `{{var}}` is HTML-escaped; use `{{{var}}}` (triple brace) to inject raw HTML (pre-trusted content only).
- Dot-notation walks nested objects: `{{order.id}}`, `{{order.shipping.city}}`.
- A missing key renders as an empty string (never blocks the send).
- Rendering activates only when at least one recipient carries a non-empty `merge_vars`; otherwise `{{...}}` is delivered literally (identical to `/email`).

**CC / BCC:** cc and bcc recipients receive an audit copy rendered against the **first** `to` recipient's `merge_vars` scope.

**Notes:**
- `merge_vars` must be a JSON object — a non-object value returns `400`.
- The combined size of all recipients' `merge_vars` must be ≤ 100 KB, else `413`.
- `replyTo` must be a verified sender address; it does **not** support `{{var}}` templates.
- Mail merge is supported only on this HTTP endpoint (not on SMTP relay).

**Custom headers**

Pass additional headers in `email.headers` as name–value pairs, for example `X-Order-Reference` for your own correlation id.

- `List-Unsubscribe` must be one or more comma-separated values in angle brackets, each starting with `https://` or `mailto:` (plain `http://` is rejected). A value you supply replaces the one Mailercloud adds by default.
- `List-Unsubscribe-Post` must be exactly `List-Unsubscribe=One-Click` and requires `List-Unsubscribe` in the same request.
- Headers Mailercloud sets itself cannot be overridden and return `400`: `From`, `Sender`, `Reply-To`, `Return-Path`, `To`, `Cc`, `Bcc`, `Subject`, `Message-ID`, `Date`, `In-Reply-To`, `References`, `MIME-Version`, any `Content-*`, `DKIM-Signature`, `ARC-*`, `Authentication-Results`, `Received`, `List-Id`, `List-Help`, `List-Subscribe`, `List-Archive`, `List-Owner`, `List-Post`, `Feedback-ID`, `CFBL-Address`, `CFBL-Feedback-ID`, `Errors-To`, `Precedence`, `Auto-Submitted`, `X-Mailer`, `X-Tracking-Id`, and any `mld-track-*` header. Use `from` / `fromName`, `replyTo`, `subject` and `metadata.messageId` instead.
- Limits: 50 headers, 8 KB per value, 64 KB in total.

**Tracking**

- **Opens** are tracked automatically whenever your sending domain has a tracking domain configured. The Email API has no per-message open-tracking parameter.
- **Clicks** are not tracked.
- **Inbox placement** is enabled with `metadata.custom.inbox_tracking` and `metadata.custom.campaign_id`.

The domain-level **Open Tracking** switch and the `mld-track-opens` header apply to [SMTP relay](/guides/smtp-relay) sending only; they do not affect Email API sends.



## OpenAPI

````yaml /openapi-emailapi.json post /email-api
openapi: 3.1.0
info:
  title: Mailercloud Email API
  version: 1.0.0
  description: Transactional and personalized email sending — the Mailercloud API Platform.
servers:
  - url: https://email-api.mailercloud.com
security:
  - apiKey: []
tags:
  - name: Email
paths:
  /email-api:
    post:
      tags:
        - Email
      summary: Send Personalized Email
      description: >-
        Send transactional or marketing emails with **per-recipient
        personalization** (mail merge). Same request structure as `POST /email`,
        plus an optional `merge_vars` object on each `recipients.to[]` entry.


        **Personalization:**

        - `{{variable}}` placeholders in `subject`, `text`, `html`, `amp_html`
        and `fromName` are replaced with that recipient's `merge_vars` values.

        - In `html`, `{{var}}` is HTML-escaped; use `{{{var}}}` (triple brace)
        to inject raw HTML (pre-trusted content only).

        - Dot-notation walks nested objects: `{{order.id}}`,
        `{{order.shipping.city}}`.

        - A missing key renders as an empty string (never blocks the send).

        - Rendering activates only when at least one recipient carries a
        non-empty `merge_vars`; otherwise `{{...}}` is delivered literally
        (identical to `/email`).


        **CC / BCC:** cc and bcc recipients receive an audit copy rendered
        against the **first** `to` recipient's `merge_vars` scope.


        **Notes:**

        - `merge_vars` must be a JSON object — a non-object value returns `400`.

        - The combined size of all recipients' `merge_vars` must be ≤ 100 KB,
        else `413`.

        - `replyTo` must be a verified sender address; it does **not** support
        `{{var}}` templates.

        - Mail merge is supported only on this HTTP endpoint (not on SMTP
        relay).


        **Custom headers**


        Pass additional headers in `email.headers` as name–value pairs, for
        example `X-Order-Reference` for your own correlation id.


        - `List-Unsubscribe` must be one or more comma-separated values in angle
        brackets, each starting with `https://` or `mailto:` (plain `http://` is
        rejected). A value you supply replaces the one Mailercloud adds by
        default.

        - `List-Unsubscribe-Post` must be exactly `List-Unsubscribe=One-Click`
        and requires `List-Unsubscribe` in the same request.

        - Headers Mailercloud sets itself cannot be overridden and return `400`:
        `From`, `Sender`, `Reply-To`, `Return-Path`, `To`, `Cc`, `Bcc`,
        `Subject`, `Message-ID`, `Date`, `In-Reply-To`, `References`,
        `MIME-Version`, any `Content-*`, `DKIM-Signature`, `ARC-*`,
        `Authentication-Results`, `Received`, `List-Id`, `List-Help`,
        `List-Subscribe`, `List-Archive`, `List-Owner`, `List-Post`,
        `Feedback-ID`, `CFBL-Address`, `CFBL-Feedback-ID`, `Errors-To`,
        `Precedence`, `Auto-Submitted`, `X-Mailer`, `X-Tracking-Id`, and any
        `mld-track-*` header. Use `from` / `fromName`, `replyTo`, `subject` and
        `metadata.messageId` instead.

        - Limits: 50 headers, 8 KB per value, 64 KB in total.


        **Tracking**


        - **Opens** are tracked automatically whenever your sending domain has a
        tracking domain configured. The Email API has no per-message
        open-tracking parameter.

        - **Clicks** are not tracked.

        - **Inbox placement** is enabled with `metadata.custom.inbox_tracking`
        and `metadata.custom.campaign_id`.


        The domain-level **Open Tracking** switch and the `mld-track-opens`
        header apply to [SMTP relay](/guides/smtp-relay) sending only; they do
        not affect Email API sends.
      operationId: send-personalized-email-mail-merge
      parameters:
        - name: Content-Type
          in: header
          required: true
          description: Request body type
          schema:
            type: string
            default: application/json
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - version
              properties:
                email:
                  type: object
                  required:
                    - from
                    - subject
                    - recipients
                  properties:
                    from:
                      type: string
                      description: >-
                        Sender email address. Must belong to a verified sender
                        on your Mailercloud account.
                    fromName:
                      type: string
                      description: >-
                        Sender display name shown in the recipient’s inbox.
                        Supports `{{var}}` substitution.
                    replyTo:
                      type: array
                      items:
                        type: string
                      description: >-
                        Address(es) replies are sent to. Must be a verified
                        sender address; does **not** support `{{var}}`
                        templates.
                    subject:
                      type: string
                      description: Email subject line. Supports `{{var}}` substitution.
                    text:
                      type: string
                      description: >-
                        Plain-text version of the message. Supports `{{var}}`
                        substitution. Recommended alongside `html` for
                        deliverability.
                    amp_html:
                      type: string
                      description: >-
                        AMP for Email body. Requires `version: "2.0"`. Supports
                        `{{var}}` substitution (not HTML-escaped).
                    html:
                      type: string
                      description: >-
                        HTML body. Supports `{{var}}` (HTML-escaped) and
                        `{{{var}}}` (raw, unescaped — pre-trusted content only).
                    recipients:
                      type: object
                      properties:
                        to:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                                description: Recipient display name.
                              email:
                                type: string
                                description: Recipient email address.
                              merge_vars:
                                type: object
                                additionalProperties: true
                                description: >-
                                  Per-recipient personalization values,
                                  referenced as `{{key}}` in the subject and
                                  body. Nested objects are addressed with dot
                                  notation (`{{order.id}}`). Must be a JSON
                                  object; combined size across all recipients ≤
                                  100 KB.
                                examples:
                                  - first_name: Alice
                                    order:
                                      city: Berlin
                          description: >-
                            Primary recipients. Each entry may carry its own
                            `merge_vars` object for per-recipient
                            personalization.
                        cc:
                          type: array
                          items:
                            type: string
                          description: >-
                            Email addresses to receive a carbon copy, as plain
                            strings. CC copies are rendered against the first
                            `to` recipient’s `merge_vars`.
                        bcc:
                          type: array
                          items:
                            type: string
                          description: >-
                            Email addresses to receive a blind carbon copy, as
                            plain strings. Rendered like CC against the first
                            `to` recipient’s scope.
                      description: Recipients of this message.
                    attachments:
                      type: array
                      items:
                        type: object
                        properties:
                          name:
                            type: string
                            description: >-
                              File name shown to the recipient, including the
                              extension.
                          url:
                            type: string
                            description: >-
                              Publicly accessible URL the file is fetched from
                              at send time.
                      description: Files to attach to the message.
                    headers:
                      type: object
                      additionalProperties:
                        type: string
                      description: >-
                        Custom email headers added to every message in this
                        request, as name–value pairs. Names are case-insensitive
                        and must not repeat. Limits: 50 headers, 8 KB per value,
                        64 KB in total. Headers Mailercloud owns are rejected
                        with `400`. Header values are the same for all
                        recipients — `{{var}}` placeholders are not substituted
                        in headers.
                      examples:
                        - X-Order-Reference: '10482'
                          List-Unsubscribe: >-
                            <https://example.com/unsubscribe?u=10482>,
                            <mailto:unsubscribe@example.com>
                          List-Unsubscribe-Post: List-Unsubscribe=One-Click
                  description: The message payload.
                metadata:
                  type: object
                  properties:
                    campaignType:
                      type: string
                      description: >-
                        Campaign type accepts only two values: "TRANSACTIONAL"
                        or "PROMOTIONAL".
                    timestamp:
                      type: string
                    messageId:
                      type: string
                      description: >-
                        Your unique identifier for this request. Use a UUID,
                        unique across your account. If omitted, the server
                        generates one. Duplicate detection is per recipient on
                        this endpoint: reusing a `messageId` within 24 hours
                        does not re-send to a recipient who already received
                        that message, so a timed-out request can be safely
                        retried with the same id. The value is also the basis of
                        each message's `Message-ID` header and is shown in the
                        Activity list. Duplicate detection applies to the Email
                        API only — SMTP relay has none.
                    custom:
                      type: object
                      properties:
                        inbox_tracking:
                          type: string
                        campaign_id:
                          type: string
                        store_content:
                          type: boolean
                          default: true
                          description: >-
                            Set to `false` to skip storing this message's
                            content (for example OTP or password-reset emails).
                            Delivery and tracking are unaffected; only the
                            message preview is unavailable in Activity.
                        tags:
                          type: array
                          maxItems: 10
                          items:
                            type: string
                            maxLength: 100
                          description: >-
                            Labels used to filter these messages in the Activity
                            list. Blank, duplicate and over-long tags are
                            dropped; up to 10 tags of 100 characters each are
                            kept.
                          examples:
                            - - order-confirmation
                      additionalProperties:
                        type: string
                        maxLength: 256
                        description: >-
                          Any key other than the reserved ones is passthrough
                          custom data. Values ≤ 256 characters; numbers and
                          booleans are accepted and returned as strings.
                      description: >-
                        Custom key–value metadata.


                        **Reserved keys** — `inbox_tracking` and `campaign_id`
                        connect a send to inbox-placement tracking (see [List
                        Email API Inbox-Tracking
                        Campaigns](/api-reference/email/list-inbox-tracking-campaigns));
                        `store_content` and `tags` control content storage and
                        Activity filtering.


                        **Passthrough keys** — any other key is your own data,
                        returned unchanged on every [transactional
                        webhook](/guides/webhooks) event for the message inside
                        a `custom` object, so you can match an event to your own
                        records (order id, case id, user ref) with no lookup. Up
                        to 10 passthrough keys; key names ≤ 50 characters using
                        `A–Z a–z 0–9 - _`; values ≤ 256 characters, returned as
                        strings. A key that breaks a rule is dropped and named
                        in the webhook's `custom_dropped` array — the send
                        always succeeds. Passthrough data is stripped before
                        delivery and never reaches the recipient.
                  description: Optional metadata recorded with the message.
                version:
                  type: string
                  enum:
                    - '1.0'
                    - '2.0'
                  description: >-
                    Use `1.0` when only `html` is sent. Use `2.0` when
                    `amp_html` is included.
            examples:
              example-merge-vars:
                value:
                  email:
                    from: from@example.com
                    fromName: John Doe
                    replyTo:
                      - from@example.com
                    subject: Hi {{first_name}}, your order {{order.id}} shipped
                    text: >-
                      Hi {{first_name}}, order {{order.id}} ships to
                      {{order.city}}.
                    html: >-
                      <html><body><p>Hi {{first_name}} from
                      {{company}},</p><p>Order <b>{{order.id}}</b> ships to
                      {{order.city}}.</p></body></html>
                    recipients:
                      to:
                        - name: Recipient One
                          email: recipient1@example.com
                          merge_vars:
                            first_name: Alice
                            company: Acme
                            order:
                              id: A-100
                              city: Berlin
                        - name: Recipient Two
                          email: recipient2@example.com
                          merge_vars:
                            first_name: Bob
                            company: Acme
                            order:
                              id: A-101
                              city: Paris
                      cc:
                        - cc1@example.com
                      bcc:
                        - bcc1@example.com
                  metadata:
                    campaignType: TRANSACTIONAL
                    timestamp: '2026-04-15T10:00:00Z'
                    custom:
                      inbox_tracking: 'false'
                      campaign_id: ''
                  version: '1.0'
                summary: Per-recipient merge vars
              example-raw-html-and-dot-notation:
                value:
                  email:
                    from: from@example.com
                    fromName: Jane Smith
                    subject: '{{first_name}}, your {{plan.name}} is ready'
                    html: >-
                      <html><body><p>Hi
                      {{first_name}},</p><div>{{{banner_html}}}</div><p>Plan:
                      {{plan.name}} ({{plan.price}})</p></body></html>
                    recipients:
                      to:
                        - name: Recipient AMP
                          email: recipient-amp@example.com
                          merge_vars:
                            first_name: Carol
                            banner_html: <a href='https://example.com'>View</a>
                            plan:
                              name: Pro
                              price: $49
                  metadata:
                    campaignType: PROMOTIONAL
                    custom:
                      inbox_tracking: 'true'
                      campaign_id: CAMP-123
                  version: '1.0'
                summary: Raw HTML + dot notation
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  statusCode:
                    type: integer
                  message:
                    type: string
              examples:
                success:
                  value:
                    status: SUCCESS
                    statusCode: 1000
                    message: NA
        '400':
          description: >-
            Validation error (invalid merge_vars shape, invalid recipient,
            unsupported version, etc.)
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  statusCode:
                    type: integer
                  message:
                    type: string
              examples:
                invalid-merge-vars:
                  value:
                    status: ERROR
                    statusCode: 9999
                    message: merge_vars must be an object
        '413':
          description: >-
            Payload Too Large — combined merge_vars across all recipients
            exceeds 100 KB
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  statusCode:
                    type: integer
                  message:
                    type: string
              examples:
                merge-vars-too-large:
                  value:
                    status: ERROR
                    statusCode: 9999
                    message: merge_vars exceeds 100 KB limit
      servers:
        - url: https://email-api.mailercloud.com
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Your Mailercloud API key (plain text, no Bearer prefix). Create keys in
        Settings → API.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.