API · Emails
Send Email
Send an email from a verified sender (requires sending or full access). Suppressed recipients are excluded, and unsubscribe headers are not added automatically.
/emailsSending or full accessRequest parameters
| Parameter | Type | Description |
|---|---|---|
Idempotency-Keyheader · optional | string1–256 characters | Makes the request safe to retry. See Idempotency. |
frombody · optional | string | null | Verified sender address, optionally formatted as Name <sender@example.com>, or omitted when supplied by a published template. |
tobody · required | string | (string)[]For string: At least 1 character For (string)[]: At least 1 item | Recipient address or array of addresses, with up to 50 recipients across to, cc, and bcc. |
subjectbody · optional | string | null | Email subject, required unless supplied by a published template. |
ccbody · optional | string | (string)[] | null | Cc address or array of addresses, counted toward the 50-recipient total. Email address or array of up to 50 addresses. |
bccbody · optional | string | (string)[] | null | Bcc address or array of addresses, counted toward the 50-recipient total. Email address or array of up to 50 addresses. |
reply_tobody · optional | string | (string)[] | null | Reply-to address or array of up to 50 addresses. Email address or array of up to 50 addresses. |
htmlbody · optional | string | null | HTML content, sharing a 900000-byte UTF-8 limit with text and headers; provide HTML or text unless using a template. |
textbody · optional | string | null | Plain text content, sharing a 900000-byte UTF-8 limit with HTML and headers; provide text or HTML unless using a template. |
headersbody · optional | object | null | Up to 50 custom headers, counted toward the combined 900000-byte content limit. |
scheduled_atbody · optional | string | null | Send time in ISO 8601 or natural language, up to 30 days ahead, using UTC when unzoned and sending immediately for past times. Send time in ISO 8601 or natural language, up to 30 days ahead, using UTC when unzoned; past times send immediately and rescheduling requires a future time. |
attachmentsbody · optional | (object)[] | null | Attachments with a combined encoded size of at most 40 MiB, within the 42 MiB JSON request limit and your installation’s proxy limits. |
attachments[].contentbody · optional | string | Base64 file content with whitespace ignored, limited to 40 MiB of encoded content across all attachments. |
attachments[].filenamebody · optional | string1–255 characters | Attachment filename, inferred from the URL path when omitted. |
attachments[].pathbody · optional | string | Public HTTPS URL with up to three redirects to public HTTPS destinations; private addresses are rejected. |
attachments[].content_typebody · optional | string | null | Attachment MIME type, inferred from the filename when omitted. |
attachments[].content_idbody · optional | string | null1–78 characters | Content ID for embedding inline images using cid references (e.g., cid:image001). |
tagsbody · optional | (object)[] | null | Up to 48 tags to associate with the email. |
tags[].namebody · required | string | Tag name of 1–256 ASCII letters, numbers, underscores, or hyphens. |
tags[].valuebody · required | string | Tag value of 1–256 ASCII letters, numbers, underscores, or hyphens. |
templatebody · optional | object | null | Published template to render instead of HTML or text; non-null html or text cannot be combined with a template. |
template.idbody · required | string | Published template id or alias. |
template.variablesbody · optional | object | null | Template variable values, each a string or number matching the variable’s definition. |
topic_idbody · optional | string | null | Topic ID used to check each recipient’s subscription before delivery; explicit choices override defaults and unsubscribed recipients fail. |
Request example
Set OPENSEND_BASE_URL=https://api.example.com and OPENSEND_API_KEY=os_replace_me on your server.
curl -X POST "$OPENSEND_BASE_URL/emails" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"from":"Acme <hello@example.com>","to":["you@example.net"],"subject":"Welcome","html":"<p>Hello.</p>"}'Response
200 · application/json. Example IDs stand for IDs returned by your installation.
{
"id": "YOUR_ID"
}Behavior and errors
A returned ID means queued, not delivered. Content and custom headers total at most 900,000 UTF-8 bytes. Actual request-size limits also depend on your Convex/proxy deployment. Use topic_id for per-address preference checks at delivery. Transactional sends do not automatically add unsubscribe headers.
Use a sending or full-access credential. Resource IDs belong to your team; an unknown or foreign resource returns 404. See authentication, errors, rate limits, and compatibility for the shared contract.