SendComms
Email API

Batch Send

POST/api/v1/email/batch

Send up to 100 separate emails in a single API request. Every item in the batch is its own message with its own sender, recipients, subject and body — so this is not a mailing list blast, it is 100 individually addressed sends. Perfect for newsletters, campaign fan-out and bulk notifications.

Maximum 100 emails per request — over that the call is rejected with 400 BATCH_LIMIT_EXCEEDED. Each individual message in the batch is still capped at 50 recipients, the same per-message limit that applies on POST /email/send.
💡

Batch items support a subset of the send fields

Each item accepts to, subject, html, text, from, replyTo and tags. cc, bcc, attachments, custom headers and idempotency keys are only honoured on POST /email/send — send those messages one at a time.

Select Language

REQUEST
curl -X POST \
  https://api.sendcomms.com/api/v1/email/batch \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "emails": [
      {
        "to": "user1@example.com",
        "subject": "Welcome!",
        "html": "<h1>Welcome User 1!</h1>",
        "from": "Your App <hello@yourdomain.com>"
      },
      {
        "to": "user2@example.com",
        "subject": "Your receipt",
        "text": "Thanks for your order.",
        "from": "Billing <billing@yourdomain.com>",
        "replyTo": "support@yourdomain.com"
      },
      {
        "to": ["user3@example.com", "user4@example.com"],
        "subject": "Team Update",
        "html": "<p>Important team update...</p>",
        "tags": [{ "name": "campaign", "value": "august" }]
      }
    ]
  }'

Request Body

ParameterTypeRequiredDescription
emailsarrayRequiredNon-empty array of email objects, maximum 100 per request
emails[].tostring | string[]RequiredRecipient email(s) for this message, up to 50
emails[].subjectstringRequiredEmail subject line
emails[].htmlstringConditionalHTML content (required if no text)
emails[].textstringConditionalPlain text content (required if no html)
emails[].fromstringOptionalSender for this message. Must be on a domain verified for your account, otherwise the whole batch is rejected with 400 UNVERIFIED_SENDER_DOMAIN. Display names are supported: "Acme <hello@acme.com>". If omitted, your primary verified domain is used
emails[].replyTostringOptionalReply-To address for this message
emails[].tagsobject[]OptionalPer-message labels, each { name, value }

Response Codes

200Success400Bad request401Unauthorized402No balance429Rate limit exceeded

Common Errors

CodeStatusWhen it happens
BATCH_LIMIT_EXCEEDED400More than 100 emails in one request
INVALID_INPUT400emails is missing, not an array, or empty
MISSING_FIELD400An item is missing to or subject. The message names the offending index
MISSING_CONTENT400An item has neither html nor text
UNVERIFIED_SENDER_DOMAIN400A from address is not on a domain verified for your account

Validation runs across the whole array before anything is sent, so a single bad item rejects the entire request and nothing is charged.

Response

Success Response

results comes back in the same order you submitted, each entry carrying its original index and the email_id you can match against webhook events.

{
  "success": true,
  "data": {
    "batch_id": "batch_mjgc0ejr_3ca715bfb7a0",
    "status": "sent",
    "total_emails": 3,
    "total_recipients": 4,
    "from": "Your App <hello@yourdomain.com>",
    "price": { "amount": 0.03, "currency": "USD" },
    "results": [
      {
        "index": 0,
        "email_id": "msg_8f21c0d4a97b",
        "to": "user1@example.com",
        "subject": "Welcome!"
      },
      {
        "index": 1,
        "email_id": "msg_1b7ee3390c42",
        "to": "user2@example.com",
        "subject": "Your receipt"
      },
      {
        "index": 2,
        "email_id": "msg_44de90ab1f05",
        "to": ["user3@example.com", "user4@example.com"],
        "subject": "Team Update"
      }
    ],
    "created_at": "2026-08-23T10:30:00.000000+00:00"
  }
}