API · Emails
Send Batch Emails
Send up to 100 emails in one request, without attachments (requires sending or full access). Requests are limited to 1 MiB; strict validation rejects the whole batch, while permissive validation returns successful IDs and errors by input index.
/emails/batchSending or full accessRequest parameters
| Parameter | Type | Description |
|---|---|---|
Idempotency-Keyheader · optional | string1–256 characters | Makes the request safe to retry. See Idempotency. |
x-batch-validationheader · optional | "strict" | "permissive"Default: strict | Validation mode: strict rejects the entire batch on error, while permissive returns successful IDs and indexed errors. |
bodybody · required | (object)[]1–100 items | JSON array. |
[].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. |
[].bccbody · optional | string | (string)[] | null | Bcc address or array of addresses, counted toward the 50-recipient total. |
[].reply_tobody · optional | string | (string)[] | null | Reply-to 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)[] | nullUp to 0 items | See operation behavior. |
[].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/batch" \
-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.
{
"data": [
{
"id": "YOUR_ID"
}
],
"errors": [
{
"index": 0,
"message": "example"
}
]
}Behavior and errors
Send email describes each message field. Strict validation rolls back the whole batch on failure. Set x-batch-validation to permissive to return successful IDs plus errors with index and message; a fully successful permissive batch has an empty errors array. Scheduling, topics, and templates are allowed. Attachments are rejected. The default 1 MiB body limit applies.
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.