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

# Send Transactional Email

> Send a transactional email

Send a transactional email. You can either use a saved template (by slug) or send custom content directly.

<Note>
  A successful response means the email was accepted for background processing.
  Transactional emails are not blocked by subscriber unsubscribe or double
  opt-in status. If a recipient is suppressed because of a hard bounce or spam
  complaint, the worker records the send as `suppressed` instead of delivering
  it. Use the returned `emailSendId` with the email-send details endpoint to
  inspect the final status and any provider failure reason.
</Note>

## Request Body

### Recipients

<ParamField body="to" type="string | string[]" required>
  Recipient email address(es). Can be a single email string or an array of up to
  50 emails. All recipients will receive the same email and can see each other
  in the To header.
</ParamField>

### Option 1: Send via template

<ParamField body="slug" type="string">
  Canonical transactional template slug (use this OR direct content).
</ParamField>

<ParamField body="templateId" type="string">
  Compatibility alias for `slug`. Despite the field name, pass the saved
  transactional email's API slug, not its database ID.
</ParamField>

### Option 2: Send direct content

<ParamField body="subject" type="string">
  Email subject (required if no slug)
</ParamField>

<ParamField body="body" type="string">
  Canonical email HTML body (required if no template slug).
</ParamField>

<ParamField body="html" type="string">
  Compatibility alias for `body`, accepted with `subject` for direct sends.
</ParamField>

<ParamField body="preview" type="string">
  Preview text
</ParamField>

<Note>
  `slug`/`body` remain canonical. If you provide both `slug` and `templateId`,
  or both `body` and `html`, the paired values must match. A differing pair is
  rejected with `400` instead of silently choosing one.
</Note>

### Common fields

<ParamField body="variables" type="object">
  Template variables for personalization. Values can be scalars, nested objects,
  or arrays. Repeat blocks read arrays from paths such as `items`. Raw HTML
  templates can also use subscriber/custom-attribute conditionals like
  `{{#if subscriber.plan}}...{{else}}...{{/if}}` and
  `{{#unless subscriber.plan}}...{{/unless}}`. If Sequenzy detects likely
  variable issues before queueing, the successful response includes
  `diagnostics` warnings. Missing required values do not block queueing; the
  worker renders values without defaults as empty strings and continues sending.
</ParamField>

<ParamField body="subscriberExternalId" type="string">
  Customer-owned subscriber ID for single-recipient sends. If it matches an
  existing subscriber, analytics, localization, and engagement attach to that
  subscriber even if the delivery email changed. Sequenzy also stores this value
  on the send, so outbound email webhooks include it as `external_id` even when
  no subscriber record exists. Maximum length: 255 characters.
</ParamField>

<ParamField body="from" type="string">
  Custom from address. Format: `"Name <email>"` or just `"email"`. The domain
  must be verified for your account. If not verified, this field is silently
  ignored and the default sender profile is used.
</ParamField>

<ParamField body="replyTo" type="string">
  Reply-to address. Format: `"Name <email>"` or just `"email"`. Can be any valid
  email address.

  When reply tracking is disabled, this is sent as the email's `Reply-To` header.
  When reply tracking is enabled, Sequenzy sends a unique trackable `Reply-To`
  address instead and stores this value as the forwarding destination for replies.
</ParamField>

<Note>
  With reply tracking and reply forwarding enabled, direct-content sends that
  omit `replyTo` forward replies to the company's default reply profile. If no
  default reply profile is set, Sequenzy uses the first reply profile in the
  company as a fallback. If no reply profile exists, replies are still captured
  in Sequenzy but are not forwarded externally. Template sends use the
  template's reply profile unless the API request provides `replyTo`.
</Note>

<ParamField body="attachments" type="array">
  File attachments to include with the email. Maximum total size: 40MB.

  Each attachment object has:

  * `filename` (required): The name of the file as it will appear to the recipient
  * `content`: Base64-encoded file content (use this OR `path`)
  * `path`: URL to fetch the file from (use this OR `content`)

  You must provide either `content` or `path`, but not both.
</ParamField>

## Example: Send via template

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@sequenzy.com",
    "subscriberExternalId": "user_123",
    "slug": "welcome",
    "variables": {
      "NAME": "John",
      "LOGIN_URL": "https://sequenzy.com/sign-in"
    }
  }'
```

## Example: Send array data to a repeat block

If a template contains a repeat block with source `items` and item alias
`item`, child blocks can use merge tags like `{{item.title}}` and
`{{item.description}}`.

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "slug": "order-confirmation",
    "variables": {
      "NAME": "John",
      "items": [
        {
          "title": "Pro plan",
          "description": "Monthly subscription"
        },
        {
          "title": "Priority support",
          "description": "Added to your account"
        }
      ]
    }
  }'
```

## Example: Send to multiple recipients

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": ["user1@example.com", "user2@example.com"],
    "slug": "invoice",
    "variables": {
      "INVOICE_NUMBER": "INV-2024-001",
      "AMOUNT": "$500.00"
    }
  }'
```

## Example: Send direct content

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@sequenzy.com",
    "subject": "Your order is confirmed",
    "body": "<h1>Thank you, {{NAME}}!</h1><p>Order #{{ORDER_ID}} confirmed.</p>",
    "variables": {
      "NAME": "John",
      "ORDER_ID": "12345"
    }
  }'
```

The same direct send can use the `html` compatibility alias:

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@sequenzy.com",
    "subject": "Connection test",
    "html": "<p>Connected.</p>"
  }'
```

## Example: Send with custom from and reply-to

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "slug": "order-confirmation",
    "variables": {
      "NAME": "John",
      "ORDER_ID": "12345"
    },
    "from": "Notifications <notifications@example.com>",
    "replyTo": "Support <support@example.com>"
  }'
```

## Example: Send with URL-based attachment

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "slug": "invoice",
    "variables": {
      "INVOICE_NUMBER": "INV-2024-001"
    },
    "attachments": [
      {
        "filename": "invoice.pdf",
        "path": "https://example.com/invoices/INV-2024-001.pdf"
      }
    ]
  }'
```

## Example: Send with Base64 attachment

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/transactional/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "subject": "Your report is ready",
    "body": "<p>Please find your report attached.</p>",
    "attachments": [
      {
        "filename": "report.csv",
        "content": "TmFtZSxFbWFpbCxTdGF0dXMKSm9obixqb2huQGV4YW1wbGUuY29tLEFjdGl2ZQ=="
      }
    ]
  }'
```

## Responses

<ResponseExample>
  ```json 200 Template (single recipient) theme={null}
  {
    "success": true,
    "emailSendId": "send_abc123",
    "jobId": "job_xyz789",
    "to": "user@sequenzy.com",
    "transactional": {
      "id": "txn_abc123",
      "slug": "welcome",
      "name": "Welcome Email"
    }
  }
  ```

  ```json 200 Template with diagnostics theme={null}
  {
    "success": true,
    "emailSendId": "send_abc123",
    "jobId": "job_xyz789",
    "to": "user@sequenzy.com",
    "transactional": {
      "id": "txn_abc123",
      "slug": "password-reset",
      "name": "Password Reset"
    },
    "diagnostics": {
      "status": "warning",
      "message": "Email was queued. A required variable is missing and will render as an empty string.",
      "missingRequiredVariables": [
        {
          "name": "RESET_URL",
          "lookupName": "reset_url",
          "message": "Email was queued. Required variable \"RESET_URL\" is missing and will render as an empty string.",
          "usedIn": [
            {
              "surface": "block",
              "blockId": "reset-button",
              "blockType": "button",
              "field": "url"
            }
          ],
          "suggestions": ["resetpasswordlink"]
        }
      ],
      "unusedVariables": [
        {
          "name": "resetpasswordlink",
          "message": "Variable \"resetpasswordlink\" was provided but is not used by the email template.",
          "suggestions": ["reset_url"]
        }
      ]
    }
  }
  ```

  ```json 200 Template (multiple recipients) theme={null}
  {
    "success": true,
    "emailSendId": "send_abc123",
    "jobId": "job_xyz789",
    "to": ["user1@example.com", "user2@example.com"],
    "transactional": {
      "id": "txn_abc123",
      "slug": "invoice",
      "name": "Invoice Email"
    }
  }
  ```

  ```json 200 Direct theme={null}
  {
    "success": true,
    "emailSendId": "send_abc123",
    "jobId": "job_xyz789",
    "to": "user@sequenzy.com"
  }
  ```

  A successful response means Sequenzy accepted the send for background
  processing. Rendering or provider failures after acceptance are recorded on the
  email send as failed delivery attempts. Check
  `GET /api/v1/email-sends/{emailSendId}` for `status` and `errorMessage`. The
  legacy `jobId` response field remains for compatibility but is not the public
  delivery-status contract. If `diagnostics.status` is `warning`,
  the send is still queued. The warnings identify missing values that will render
  as empty strings or variables that look unused.

  ```json 400 Missing fields theme={null}
  {
    "success": false,
    "error": "Either 'slug'/'templateId' OR both 'subject' and 'body'/'html' are required"
  }
  ```

  ```json 400 Disabled theme={null}
  {
    "success": false,
    "error": "Transactional email \"welcome\" is disabled"
  }
  ```

  ```json 400 No sender theme={null}
  {
    "success": false,
    "error": "No sender profile configured. Please create a sender profile first."
  }
  ```

  ```json 400 Invalid attachment theme={null}
  {
    "success": false,
    "error": "Invalid attachments: Attachment[0]: Attachment must have either 'content' (Base64) or 'path' (URL)"
  }
  ```

  ```json 400 Attachment too large theme={null}
  {
    "success": false,
    "error": "Attachment \"large-file.pdf\" exceeds maximum size of 40MB"
  }
  ```

  ```json 400 Total size exceeded theme={null}
  {
    "success": false,
    "error": "Total attachment size exceeds 40MB limit"
  }
  ```

  ```json 404 theme={null}
  {
    "success": false,
    "error": "Transactional email with slug \"welcome\" not found"
  }
  ```

  ```json 401 theme={null}
  {
    "success": false,
    "error": "Unauthorized"
  }
  ```

  ```json 500 theme={null}
  {
    "success": false,
    "error": "Internal server error"
  }
  ```
</ResponseExample>

<Note>
  Emails are queued for background processing. Track the returned `emailSendId`
  with `GET /api/v1/email-sends/{emailSendId}`. For single-recipient sends
  without `cc` or `bcc`, `EMAIL` resolves from the recipient address. Pass
  `name`, `firstName`, `lastName`, `FIRST_NAME`, or `LAST_NAME` in `variables`
  when a REST API template needs recipient names.
</Note>

<Note>
  When using multiple `to` recipients, all recipient addresses are visible to
  each other. Use single-recipient sends when recipients should not see each
  other.
</Note>

<Note>
  Multi-recipient sends produce a single email send record. The full recipient
  list (to/cc/bcc) is stored on the record and returned as
  `additionalRecipients` from the email-sends API. Opens and clicks are tracked
  for the message as a whole, not per recipient.
</Note>
