---
title: "Send a custom email"
method: POST
path: "/v1/emails/send"
tags: ["emails"]
---

# Send a custom email

`POST /v1/emails/send`

Send an email from your publication to a list of recipient addresses.

**Eligibility:**
- Publications must be approved by Paragraph before they can send custom emails. Ineligible publications receive a 403. Eligibility is managed by Paragraph and is not user-configurable.

**Per-recipient filtering:**
- Malformed addresses and known disposable domains are skipped.
- Addresses that previously unsubscribed from this publication are skipped as `suppressed`.
- Skipped recipients are returned in the response; nothing else is delivered to them.

**Delivery:**
- `body` is treated as Markdown and rendered to HTML server-side.
- Each recipient receives the email individually (not as a BCC blast) with a mandatory unsubscribe footer.
- Sends are queued asynchronously; a 200 response means recipients were accepted, not delivered.

**Caps:**
- Maximum of 10,000 addresses per call (request-level sanity check).

## Request body

- object
  - `subject` string, required — Subject line of the email
  - `body` string, required — Email body. Markdown; rendered to HTML server-side. Max 100KB.
  - `emails` string[], required — Recipient email addresses (max 10,000). Malformed addresses are returned in `skipped` with `reason: "invalid"` rather than rejecting the whole request.
  - `dryRun` boolean — If true, run filtering and return the accepted/skipped split without scheduling delivery

## Response `200`

Send request accepted

- object
  - `accepted` integer, required — Number of recipients queued for delivery (or that would be queued when dryRun is true)
  - `skipped` object[], required — Recipients that were rejected, with the reason each one was skipped. `scheduling_failed` means filtering passed but the delivery task could not be queued — retry these addresses.
    - `email` string, required
    - `reason` 'suppressed' | 'invalid' | 'scheduling_failed', required

## Other responses

- `400` — Invalid request
- `401` — Invalid or missing API key
- `403` — Publication is not eligible to send custom emails
- `404` — Publication not found
- `500` — Internal server error
- `503` — Publication temporarily can't send through this endpoint. Contact support.

---

[API](https://skmtc.net/paragraph-xyz/apis/paragraph-api.md) · [All operations](https://skmtc.net/paragraph-xyz/apis/paragraph-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/paragraph-xyz/paragraph-api/versions/7bbf1b62c1a0/schema)
