Send Email
Queue one transactional email. Provide exactly one of html, tiptap, or markdown.
/api/v2/emailsQueues one transactional email. Permission: emails.
Test-mode recipients. Fixture addresses such as
[email protected]never send real email. See Test-mode recipients.Recipient rate guards. The same real mailbox is capped at 5 sends / 10 minutes and 20 / 24 hours. A 429 with
code: RECIPIENT_RATE_LIMITEDis not the HTTP API rpm limit. See Recipient rate guards.
Exactly one of html, tiptap, or markdown. Markdown is rendered to HTML. Omit text to generate it from the rendered HTML. text: "" skips generation.
Unsupported: attachments, template, topic_id, scheduled_at, react, content, contentType.
Snippets
A tiptap body can embed your organization's saved snippets. Add a snippet node where the block should appear:
{
"type": "doc",
"content": [
{ "type": "paragraph", "content": [{ "type": "text", "text": "Hi {{firstName}}," }] },
{ "type": "snippet", "attrs": { "snippetId": "snp_abc123" } }
]
}- Snippets are expanded once, when the email is queued. Editing the snippet later does not change emails already queued.
- List ids with the
get_email_snippetstool (permissionsettings). Archived snippets still render. - Variables inside the snippet (
{{firstName}},{{unsubscribeUrl}}, …) are filled per recipient like the rest of the body. - An unknown id, or one that belongs to another organization, returns
400 validation_errorwithSnippet not found in this organization: …. Nothing is queued. htmlandmarkdownbodies have no snippet syntax; usetiptap.
Body Parameters
| Name | Type | Description |
|---|---|---|
from | string | Required. Sender. Display name is allowed: Acme <[email protected]>. Domain must be verified. |
to | string or [string] | Required. One recipient. A one-address array is accepted. |
subject | string | Required. Subject line. |
html | string | HTML body. Provide exactly one of html, tiptap, or markdown. |
tiptap | string or object | TipTap JSON. Rendered to HTML on send. Can embed saved snippets. |
markdown | string | Markdown body. Rendered to HTML on send. |
text | string | Plain-text body. Omit to generate from HTML. Empty string skips generation. |
reply_to | string or string[] | Reply-To addresses. Stored as an array. SES uses the first address. |
cc | string or string[] | Carbon copies. |
bcc | string or string[] | Blind carbon copies. |
headers | object | Extra MIME headers. |
tags | { name, value }[] | Metadata tags stored on the email. |
preview | string | Preview / preheader text. |
tracking | { links: boolean, open: boolean } | Open pixel and click wrapping. Both default to true. Set both to false for OTP / magic-link mail. |
Options
| Name | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional header. Repeat the same key to reuse the queued email id. |
SDK: pass { idempotencyKey } as the second argument to emails.send.
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Queued email id (eml_...). Fetch the body and last_event with Get Email. |
Errors
| Status | name | When |
|---|---|---|
| 401 | missing_api_key | Missing or invalid bearer token |
| 403 | missing_permission | Token lacks the emails permission |
| 400 | validation_error | A tiptap snippet id is unknown or belongs to another organization (Snippet not found in this organization: …). |
| 422 | validation_error | Missing required fields, more than one body format, or unsupported fields |
| 429 | RECIPIENT_RATE_LIMITED | This mailbox already hit 5/10 min or 20/24 h, or is on a bounce cooldown. Honor Retry-After. Recipient rate guards. |