Skip to documentation

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.

POST/emails/batchSending or full access

Request parameters

ParameterTypeDescription
Idempotency-Key
header · optional
string
1–256 characters
Makes the request safe to retry. See Idempotency.
x-batch-validation
header · optional
"strict" | "permissive"
Default: strict
Validation mode: strict rejects the entire batch on error, while permissive returns successful IDs and indexed errors.
body
body · required
(object)[]
1–100 items
JSON array.
[].from
body · optional
string | nullVerified sender address, optionally formatted as Name <sender@example.com>, or omitted when supplied by a published template.
[].to
body · 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.
[].subject
body · optional
string | nullEmail subject, required unless supplied by a published template.
[].cc
body · optional
string | (string)[] | nullCc address or array of addresses, counted toward the 50-recipient total.
[].bcc
body · optional
string | (string)[] | nullBcc address or array of addresses, counted toward the 50-recipient total.
[].reply_to
body · optional
string | (string)[] | nullReply-to address or array of up to 50 addresses.
[].html
body · optional
string | nullHTML content, sharing a 900000-byte UTF-8 limit with text and headers; provide HTML or text unless using a template.
[].text
body · optional
string | nullPlain text content, sharing a 900000-byte UTF-8 limit with HTML and headers; provide text or HTML unless using a template.
[].headers
body · optional
object | nullUp to 50 custom headers, counted toward the combined 900000-byte content limit.
[].scheduled_at
body · optional
string | nullSend 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.
[].attachments
body · optional
(object)[] | null
Up to 0 items
See operation behavior.
[].attachments[].content
body · optional
stringBase64 file content with whitespace ignored, limited to 40 MiB of encoded content across all attachments.
[].attachments[].filename
body · optional
string
1–255 characters
Attachment filename, inferred from the URL path when omitted.
[].attachments[].path
body · optional
stringPublic HTTPS URL with up to three redirects to public HTTPS destinations; private addresses are rejected.
[].attachments[].content_type
body · optional
string | nullAttachment MIME type, inferred from the filename when omitted.
[].attachments[].content_id
body · optional
string | null
1–78 characters
Content ID for embedding inline images using cid references (e.g., cid:image001).
[].tags
body · optional
(object)[] | nullUp to 48 tags to associate with the email.
[].tags[].name
body · required
stringTag name of 1–256 ASCII letters, numbers, underscores, or hyphens.
[].tags[].value
body · required
stringTag value of 1–256 ASCII letters, numbers, underscores, or hyphens.
[].template
body · optional
object | nullPublished template to render instead of HTML or text; non-null html or text cannot be combined with a template.
[].template.id
body · required
stringPublished template id or alias.
[].template.variables
body · optional
object | nullTemplate variable values, each a string or number matching the variable’s definition.
[].topic_id
body · optional
string | nullTopic 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.

bash
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.

json
{
  "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.