Overview

Integration

User guide

API reference

Webhooks

Send batch emails

We understand that developers with higher volumes or processing time constraints need to send their messages in batches. To facilitate this we provide a batching endpoint that permits you to send up to 500 well-formed Postmark messages in a single API call. If you are sending Broadcast (bulk) messages with the batch call, use the MessageStream field to set your sending Stream.

Please note that the batch endpoint accepts up to 500 messages per API call, and up to 50 MB payload size, including attachments.

The format of the batched message is a JSON array containing multiple message requests.

Batch request examples can be seen here.

Example request with curl

curl "https://api.postmarkapp.com/email/batch" \
  -X POST \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Postmark-Server-Token: server token" \
  -d '[{
    "From": "sender@example.com",
    "To": "receiver1@example.com",
    "Subject": "Postmark test #1",
    "TextBody": "Hello dear Postmark user.",
    "HtmlBody": "<html><body><strong>Hello</strong> dear Postmark user.</body></html>",
    "MessageStream": "outbound"
  },
  {
    "From": "sender@example.com",
    "To": "receiver2@example.com",
    "Subject": "Postmark test #2",
    "TextBody": "Hello dear Postmark user.",
    "HtmlBody": "<html><body><strong>Hello</strong> dear Postmark user.</body></html>",
    "MessageStream": "outbound"
  }
]'

Response

Similarly, you will receive a matching JSON array containing each response for the messages you sent in your batched call.

See a full list of API errors for more details.

Example JSON response

[
  {
    "ErrorCode": 0,
    "Message": "OK",
    "MessageID": "b7bc2f4a-e38e-4336-af7d-e6c392c2f817",
    "SubmittedAt": "2010-11-26T12:01:05.1794748-05:00",
    "To": "receiver1@example.com"
  },
  {
    "ErrorCode": 0,
    "Message": "OK",
    "MessageID": "e2ecbbfc-fe12-463d-b933-9fe22915106d",
    "SubmittedAt": "2010-11-26T12:01:05.1794748-05:00",
    "To": "receiver2@example.com"
  }
]

New! TypeScript: batch send with partial-failure handling

Use Promise.allSettled instead of Promise.all so a single failed recipient doesn't abort the entire batch. Each result includes the MessageID for successful sends and the error reason for failures — giving you the per-recipient visibility you need to act on partial failures without re-sending to everyone.

For template-based batch sends, see Send batch with templates →. For the full TypeScript setup including client configuration, see the TypeScript integration guide →.

Batch send

import { ServerClient } from "postmark";

const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN!);

export async function sendBatchNotifications(
  recipients: Array<{ email: string; name: string }>
) {
  const results = await Promise.allSettled(
    recipients.map((r) =>
      client.sendEmailWithTemplate({
        From: "notifications@acme.example",
        To: r.email,
        TemplateAlias: "notification",
        TemplateModel: { name: r.name },
        MessageStream: "outbound",
      })
    )
  );

  return results.map((result, index) => ({
    email: recipients[index].email,
    ok: result.status === "fulfilled",
    messageId:
      result.status === "fulfilled" ? result.value.MessageID : undefined,
    error:
      result.status === "rejected" ? String(result.reason) : undefined,
  }));
}

Log partial failures

const results = await sendBatchNotifications(recipients);

const succeeded = results.filter((r) => r.ok);
const failed = results.filter((r) => !r.ok);

console.log(`Sent: ${succeeded.length}, Failed: ${failed.length}`);
failed.forEach((r) => console.error(`Failed for ${r.email}: ${r.error}`));

Smoke test

const results = await sendBatchNotifications([
  { email: "ada@example.com", name: "Ada" },
  { email: "grace@example.com", name: "Grace" },
]);
console.log(results);
// [
//   { email: "ada@example.com", ok: true, messageId: "abc-123" },
//   { email: "grace@example.com", ok: true, messageId: "def-456" }
// ]