---
title: "Send an email"
method: POST
path: "/transactional/emails"
tags: ["Transactional"]
---

# Send an email

`POST /transactional/emails`

## Request

- Base URL: `https://api.sendfox.com`
- URL: `https://api.sendfox.com/transactional/emails`
- Auth: OAuth 2
  - Authorization code: `https://sendfox.com/oauth/authorize`
  - Token URL: `https://sendfox.com/oauth/token`

Queues one email. The response is immediate; delivery happens in the
background and is reported through `GET /transactional/emails/{id}`
and your webhook.

**Idempotency.** Send an `Idempotency-Key` header (1 to 256 characters)
to make retries safe. Within 24 hours, the same key with the same body
returns the original message (with an `idempotent-replayed: true`
header); the same key with a different body is a `409
invalid_idempotent_request`.

**Sandbox.** Send from `onboarding@sendfoxmail.com` with no DNS setup.
It delivers only to your own account email and to the four test
addresses. Test addresses never reach a mailbox and never count toward
your limits; each one synthesizes an outcome so you can exercise your
integration: `delivered@sendfoxmail.com`, `bounced@sendfoxmail.com`,
`complained@sendfoxmail.com`, `suppressed@sendfoxmail.com`.

**Limits.** Transactional email has no quota of its own: every
address in `to`, `cc` and `bcc` counts as one send against your
SendFox plan, the same monthly sends your campaigns use, with no
daily cap. When the plan has a cap, every response carries
`x-sendfox-sends-remaining`, the sends left across campaigns and
transactional email; a plan without an enforced cap sends no header.
Past the cap, sends are refused with `429 monthly_quota_exceeded`
carrying `remaining` and `requested`. Each message holds at most 10
addresses across `to`, `cc` and `bcc`, at most 2 in `bcc`. Requests
are limited to 5 per second and 300 per minute per key.

**Custom headers.** Pass `headers` to add list-management and
threading headers. For one-click unsubscribe (RFC 8058, which Gmail
and Yahoo require of bulk senders) send `List-Unsubscribe` with an
`https:` URL in angle brackets and `List-Unsubscribe-Post` set to
`List-Unsubscribe=One-Click`; the URL must accept a `POST` whose body
is `List-Unsubscribe=One-Click` and unsubscribe the recipient without
any further click. See the `headers` field for what is allowed.

## Headers

- `Idempotency-Key` string

## Request body

- TransactionalSendRequest
  - `from` string, required: Sender. Either an address or a display name followed by one in angle brackets. The domain must be plain ASCII (for an internationalized domain, use its punycode form, starting xn--) and verified under Account > Domains (a subdomain of a verified domain also works), or be the sandbox sender `onboarding@sendfoxmail.com`, which needs no DNS but only delivers to your own account email and the test addresses (sandbox mail always shows the SendFox Onboarding display name).
  - `to` string[], required: 1 to 10 addresses. to, cc and bcc together may hold at most 10, and every address counts as one email against your plan's sends, so a message to three people uses three.
  - `cc` string[]
  - `bcc` string[]: At most 2 addresses; counts toward the 10-address total.
  - `reply_to` string, email, nullable
  - `subject` string, required
  - `html` string: HTML body, at most 500 KB (UTF-8 bytes). Send html, text, or both.
  - `text` string: Plain-text body, at most 100 KB (UTF-8 bytes). Send html, text, or both.
  - `tag` string, nullable: A label for grouping in the dashboard, for per-tag open/click tracking switches, and for per-tag alerts. Lowercase letters, digits, dots, dashes and underscores. Messages without a tag are grouped by subject. Tags that look like authentication mail (`login_code`, `password_reset`, `otp`, ...) can never have tracking turned on. An account may hold at most 200 distinct tags, so tag by kind of email (`receipt`), not per customer or order.
  - `headers` object, nullable: Custom headers, at most 20, as `{"Name": "value"}`. Allowed: `List-Unsubscribe`, `List-Unsubscribe-Post`, `List-Id`, `X-Entity-Ref-ID`, `References`, `In-Reply-To`, and any other `X-*` header except `X-SendFox-*` and `X-SG-*`. Headers SendFox or SendGrid set (`From`, `To`, `Cc`, `Bcc`, `Reply-To`, `Subject`, `Content-*`, `MIME-Version`, `Date`, `Message-ID`, `Return-Path`, `DKIM-Signature`, `Received`) are refused with a 422. Names may hold letters, digits and dashes; values may hold up to 998 characters and no line breaks. `List-Unsubscribe` must be one or more `mailto:` or `https:` URLs in angle brackets, and `List-Unsubscribe-Post` must be exactly `List-Unsubscribe=One-Click` with an `https:` URL in `List-Unsubscribe`, as RFC 8058 requires.
  - `attachments` object[], nullable: Files to attach, at most 10 and 5 MB in total once decoded. Each is `{filename, content, content_type?}` with `content` the file in base64 (line breaks are fine). `content_type` is guessed from the extension when omitted and may carry parameters, like `text/calendar; method=REQUEST` for a calendar invite. Executable and script files (`.exe`, `.js`, `.bat`, `.scr`, ...) are refused, as are URLs (`path`): send the file itself. Not accepted on the batch endpoint. The file is kept only until the email is sent or fails; `GET /transactional/emails/{id}` shows its name, type and size.
    - `filename` string, required
    - `content` string, byte, required: The file, base64-encoded.
    - `content_type` string

## Response `202`

Accepted and queued

- object
  - `id` string
  - `status` string

## Other responses

- `401`: missing_api_key or invalid_api_key
- `403`: insufficient_scope, feature_not_available, domain_not_verified, sandbox_recipient_not_allowed, recipient_suppressed, account_paused, account_restricted
- `409`: invalid_idempotent_request
- `422`: validation_error, with field errors in `errors`
- `429`: rate_limit_exceeded or monthly_quota_exceeded

## Changes

- **2026-10-15** `f62c3f4840f1`: 2 warning
  - the optional response header `x-sendfox-daily-quota-remaining` removed for the status `202`
  - the optional response header `x-sendfox-monthly-quota-remaining` removed for the status `202`
- **2026-10-14** `82cbee9ea496`: 1 info
  - added the new optional request property `attachments`
- **2026-10-13** `066d2e37ee10`: 1 info
  - added the new optional request property `headers`
- **2026-10-10** `113bf2f04aad`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/sendfox/apis/sendfox-api/changes/transactional/emails/post.md)

---

[API](https://skmtc.dev/sendfox/apis/sendfox-api.md) - [All operations](https://skmtc.dev/sendfox/apis/sendfox-api/llms.txt) - [OpenAPI document](https://skmtc.dev/sendfox/apis/sendfox-api/revisions/e45b66045d53?raw)
