---
title: "Send an email (alias)"
method: POST
path: "/emails/send"
tags: ["Emails"]
---

# Send an email (alias)

`POST /emails/send`

## Request

- Base URL: `https://api.poststack.dev`
- URL: `https://api.poststack.dev/emails/send`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Authorization code: `https://poststack.dev/oauth/authorize`
    - Token URL: `https://poststack.dev/oauth/token`
- TypeScript: <https://skmtc.dev/poststack/apis/poststack-api/docs/emails/send/post.ts> (a function with typed inputs; its response is checked against the schema)

Identical to `POST /emails`; kept for clients that expect this path.

## Headers

- `Idempotency-Key` string

## Request body

- SendEmailInput
  - `from` string, required
  - `to` string[], required
  - `cc` string[]
  - `bcc` string[]
  - `reply_to` string, email
  - `subject` string
  - `html` string
  - `text` string
  - `headers` object
  - `tags` string[]
  - `attachments` object[]
    - `filename` string, required
    - `content` string, required
    - `content_type` string
    - `content_id` string
  - `idempotency_key` string
  - `scheduled_at` union
    - string, date-time
    - string
  - `template_id` string
  - `variables` object
  - `unsubscribe` boolean
  - `signature` 'auto' | 'none'
  - `tracking` object
    - `opens` boolean
    - `clicks` boolean
  - `idempotency_window_hours` integer

## Response `202`

Accepted and queued.

- SendEmailResponse
  - `id` string, required: Public email id (`em_…`). Every email endpoint is addressed by this id.
  - `replayed` boolean: Present and `true` when `idempotency_key` (or the `Idempotency-Key` header) matched an earlier send: `id` is that email and nothing was sent. The response also carries `X-Idempotent-Replay: true`.
  - `test_mode` true: Present only when authenticated with an `sk_test_` key: the email was recorded and marked delivered but never handed to a mail server.
  - `spam_score` number: rspamd score of the rendered message (omitted when the spam check was skipped).
  - `spam_warnings` SpamSymbol[]
    - `name` string, required
    - `score` number, required
    - `description` string

## Other responses

- `400`: Body missing, not JSON, or failed validation (the JSON error for a missing field lists `missingFields`).
- `401`: Missing, malformed or unknown credentials (`WWW-Authenticate: Bearer …` is set).
- `403`: Missing `email:send` scope; team suspended or sending paused; or the API key is restricted to a different domain.
- `404`: template_id does not exist.
- `422`: Semantically invalid: unverified/unknown `from` domain, all recipients suppressed, template not published, attachment too large, or `idempotency_key` reused with a different payload.
- `429`: Branch on `code`. `rate_limit_exceeded`: request rate limited (60 req/min per key; halved on the free plan) — retry after `Retry-After`. Not retryable: `monthly_limit_exceeded` (monthly plan limit reached), `daily_limit_exceeded` (rolling 24h cap on external recipients for new/free accounts), `send_limit_exceeded` (sending from new accounts paused platform-wide).

## Changes

- **2026-11-12** `0d3971e3a670`: 5 warning
  - the `bcc/items/` request property's maxLength was set to `320`
  - the `cc/items/` request property's maxLength was set to `320`
  - the `from` request property's maxLength was set to `998`
  - the `reply_to` request property's maxLength was set to `320`
  - …1 more
- **2026-10-27** `52b7a6be08b3`: 1 breaking, 2 info
  - the `scheduled_at` request property type changed from `string` to no type, and format from `date-time` to no format
  - added `subschema #1, subschema #2` to the `scheduled_at` request property `anyOf` list
  - removed the pattern `^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$` from the request property `scheduled_at`
- **2026-09-30** `4dc1e20989c8`: 18 warning
  - added the new `daily_limit_exceeded` enum value to the `anyOf[#/components/schemas/Error]/code` response property for the response status `403`
  - added the new `daily_limit_exceeded` enum value to the `code` response property for the response status `400`
  - added the new `daily_limit_exceeded` enum value to the `code` response property for the response status `401`
  - added the new `daily_limit_exceeded` enum value to the `code` response property for the response status `404`
  - …14 more
- …earlier changes not shown

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

---

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