Send
| Method | Path | Scope | SDK |
|---|---|---|---|
POST | /api/v1/send | send | mailroom.send |
Renders one template and sends one email. For many recipients use campaigns or sequences instead of looping.
Request
| Field | Type | Notes |
|---|---|---|
template | string | Required. Registry key; must be enabled for the project/brand. |
to | string | Recipient email. Required unless contactId is given. |
contactId | uuid | Send to an existing contact. Takes precedence over to. |
type | transactional | marketing | Defaults to the template's declared type. |
subject | string | Overrides the project default and the template default. |
data | object | Variables the template renders. See Templates. |
brand | string | Brand slug; falls back to the contact's brand, then the project default. |
from | object | { email, name? } — must sit on a verified sending domain. |
idempotencyKey | string | Also accepted as the Idempotency-Key header. |
curl -X POST https://mailroom.example.com/api/v1/send \
-H "Authorization: Bearer pk_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: receipt:ord_123" \
-d '{
"to": "ada@example.com",
"template": "receipt",
"type": "transactional",
"data": { "orderNumber": "1043", "lineItems": [{ "name": "Widget", "price": "12.00" }] }
}'
Response
{ "ok": true, "id": "3f8b1c0a-…" }
id is the delivery provider's message id — the same value that appears as
resend_id on the send log row. It is absent only if the provider
accepted the mail without returning one.
Marketing sends create contacts
With type: "marketing", Mailroom needs a contact to anchor the per-recipient
unsubscribe link, so an unknown to address is upserted into the contact list
before sending. List-Unsubscribe and List-Unsubscribe-Post headers are set and
unsubscribeUrl is injected into the template. Transactional sends get neither.
Errors
| Status | code | Cause |
|---|---|---|
| 422 | invalid_request | Payload failed validation, or neither to nor contactId was given |
| 404 | not_found | contactId does not exist in this project |
| 422 | no_brand | The project has no brand to send under |
| 422 | unknown_template | No such template for this project/brand |
| 422 | template_not_enabled | Template exists but is not enabled |
| 422 | invalid_content | Published content does not satisfy the template schema |
| 422 | send_failed | Provider rejected it, rendering failed, or the recipient is suppressed |
| 403 | email_unverified | The organization owner's email is not verified yet |
| 429 | — | Rate limited; honour Retry-After |
A suppressed recipient is a send_failed with "recipient is suppressed", and the
attempt is written to the send log with status: "failed" — check
suppressions before treating it as a delivery fault.