Batch Send

Send up to 100 emails in a single API call with per-message validation and partial success support. Drains to AWS SES at ~12 emails/sec.

The batch endpoint queues multiple emails in a single request. Each message is validated independently — invalid messages are skipped and reported in the response without affecting valid ones.

Key features:

• Up to 100 messages per batch
• Per-message validation and error reporting
• Template resolution per message
• Idempotency support via X-Idempotency-Key header
• Rate limits are consumed atomically for the batch size
• Scheduled emails (scheduledFor) are NOT supported in batch mode

---

## Throughput & SES rate limit

AWS SES enforces a per-account **maximum send rate** — currently **14 emails per second** for the Posthawk Cloud account. Exceeding this rate triggers `ThrottlingException` errors from SES, and repeated throttling can affect your sending reputation.

To stay safely under the SES ceiling, the Posthawk worker rate-limits SES dispatch to **12 emails per second** across all queue workers (configured via BullMQ `limiter: { max: 12, duration: 1000 }`). This leaves a small headroom for retries and avoids brushing against the SES limit.

What this means for batch sends:

• A 100-message batch is **accepted instantly** (validated and queued in BullMQ) but **drains to SES over ~8 seconds** (100 ÷ 12 ≈ 8.3s).
• The API responds with `success: true, queued: N` as soon as messages are queued, not when they hit SES.
• Status tracking via `GET /v1/send/:jobId` lets you observe the drain in real time.
• If you need higher throughput, contact AWS to request an SES sending-rate increase. After approval, the Posthawk worker limit can be raised to match (the ceiling is configurable per deployment).

The same 12/sec ceiling applies to **all** outbound paths combined — API `/v1/send`, batch `/v1/batch`, scheduled emails firing, broadcast fan-out, newsletter issue sends, and SMTP relay all share the queue.
POST/v1/batchAPI Key

Send a batch of up to 100 emails. Each message is validated independently. Returns per-message results with success/failure status.

ParameterTypeInDescription
messagesrequiredarraybodyArray of email objects (1-100). Each object has the same fields as POST /v1/send (from, to, subject, html, text, templateId, variables, headers, metadata, tags).

Request

bash
{
  "messages": [
    {
      "from": "hello@yourdomain.com",
      "to": ["user1@example.com"],
      "subject": "Welcome!",
      "html": "<h1>Hello User 1</h1>"
    },
    {
      "from": "hello@yourdomain.com",
      "to": ["user2@example.com"],
      "subject": "Welcome!",
      "templateId": "welcome-template",
      "variables": { "name": "User 2" }
    }
  ]
}

Response

json
{
  "success": true,
  "results": [
    { "index": 0, "success": true, "jobId": "abc123" },
    { "index": 1, "success": true, "jobId": "def456" }
  ],
  "total": 2,
  "queued": 2,
  "failed": 0
}