Documentation
Sign inGet started

Send a batch of messages

POST
/v1/email/batches
const batch = await bird.email.sendBatch([
  {
    from: { email: "onboarding@messagebird.dev", name: "Bird" },
    to: ["alice@example.com"],
    subject: "Your receipt",
    html: "<p>Thanks, Alice.</p>",
  },
  {
    from: { email: "onboarding@messagebird.dev", name: "Bird" },
    to: ["bob@example.com"],
    subject: "Your receipt",
    html: "<p>Thanks, Bob.</p>",
  },
]);
for (const item of batch.data) console.log(item.id, item.status);
Accepts up to 100 independent email messages and queues them for delivery. All items are validated before any are queued: if one fails validation, the entire batch is rejected. Field-level validation failures and business-rule failures (such as domain_not_verified) both return 422. Suppression is evaluated per recipient after acceptance, never as a synchronous error. The 202 response returns one entry per message in submission order, each with its own id you can use to fetch that message or match it against webhook events. Attachments are allowed per message. Each message must stay within the 20 MB estimated generated message-size cap, and the serialized JSON request body for the whole batch has a hard 20 MB cap.
Request Payload
ऑब्जेक्ट्स की array, हर एक के साथ:
from
string or object
आवश्यक
Sender address, as a plain email string, an RFC 5322 mailbox string (Jane <jane@acme.com>), or an object with an optional display name. Must be from a verified domain in this workspace.
चाइल्ड पैरामीटर दिखाएँ
from.email
string
आवश्यक
Email address.
from.name
string
Display name shown alongside the address in mail clients.
to
array of string or object
आवश्यक
Primary recipients. Each entry is a plain email string, an RFC 5322 mailbox string (Jane <jane@acme.com>), or an object with an optional display name.
चाइल्ड पैरामीटर दिखाएँ
to.email
string
आवश्यक
Email address.
to.name
string
Display name shown alongside the address in mail clients.
cc
array of string or object
CC recipients. Each entry is a plain email string, an RFC 5322 mailbox string (Jane <jane@acme.com>), or an object with an optional display name.
चाइल्ड पैरामीटर दिखाएँ
cc.email
string
आवश्यक
Email address.
cc.name
string
Display name shown alongside the address in mail clients.
bcc
array of string or object
BCC recipients. Each entry is a plain email string, an RFC 5322 mailbox string (Jane <jane@acme.com>), or an object with an optional display name.
चाइल्ड पैरामीटर दिखाएँ
bcc.email
string
आवश्यक
Email address.
bcc.name
string
Display name shown alongside the address in mail clients.
subject
string
Message subject line. Required for inline sends. Omit it when sending a template (the template supplies the subject).
html
string
HTML body. At least one of html or text must be provided.
text
string
Plain-text body. At least one of html or text must be provided.
reply_to
array of string or object
Reply-To addresses, each a plain email string, an RFC 5322 mailbox string, or an object with an optional display name. RFC 5322 allows multiple. Every recipient reply hits all listed addresses, so 1-2 is typical. The 25 cap exists to prevent header sizes that some receiving mail servers reject.
चाइल्ड पैरामीटर दिखाएँ
reply_to.email
string
आवश्यक
Email address.
reply_to.name
string
Display name shown alongside the address in mail clients.
headers
object
Custom email headers as key-value pairs (for example References, In-Reply-To, or your own X-* headers). Reserved headers are rejected with a 422. Set the message's addressing and subject through the dedicated fields (from, to, cc, bcc, reply_to, subject) rather than here, and the headers generated for you automatically (Content-Type, Content-Transfer-Encoding, DKIM-Signature, Received, and Return-Path) cannot be overridden. List-Unsubscribe and List-Unsubscribe-Post are honored as-is on transactional sends. On a marketing send a compliant unsubscribe header is set for you, so supplying either one there is rejected with a 422. Header values may not contain carriage-return or line-feed characters. Up to 25 headers per send, each value up to 998 characters.
tags
array of object
Structured {name, value} labels for filtering and analytics. Tags become first-class query dimensions:
  • Filter the list endpoint by tag name.
  • Slice analytics rollups by tag.
  • Surface in webhook payloads.
Cap: 20 tags per send. Use tags for low-cardinality dimensions (category, experiment_variant, template_id). For arbitrary structured context that you do not need as a filter dimension, use metadata instead.
चाइल्ड पैरामीटर दिखाएँ
tags.name
string
आवश्यक
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
tags.value
string
आवश्यक
Tag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters.
metadata
object
Arbitrary JSON object stored, returned on API reads, and echoed in webhook payloads. Path-queryable in analytics (for example, filter on metadata.order_id) but not surfaced as a first-class dashboard filter dimension. Cap: 2 KB serialized. Use metadata for per-send context like internal IDs, foreign keys, and structured payloads you want round-tripped through events. For low-cardinality filterable labels, use tags instead.
parameters
object
Parameter values used to personalize inline content. A parameter is a single word, and a token in the subject or body (for example {{ animal }}) is replaced with the value of that name at send time. Shared across all recipients of this send. A token with no matching key renders empty. Cap: 16 KB serialized. When sending a stored template, put the values in template.parameters instead.
template
object
Send a stored template instead of inline content. When set, omit subject, html and text, because the template supplies them. Personalize with template.parameters. A template send goes out immediately: template and scheduled_at are mutually exclusive, and combining them is rejected with a 422.
चाइल्ड पैरामीटर दिखाएँ
template.id
string
आवश्यक
The template to send, by its id.
template.slug
string
आवश्यक
The template to send, by its slug handle. A workspace template (for example welcome-email) or a built-in system template (for example bird_welcome).
template.language
string
Which of the template's languages to send. Omit it to send the template's default language, unless the template sets language_source_required, in which case a send naming no language is rejected. When the template does not have the language you ask for, its own on_missing_language setting decides whether the closest available language is sent instead or the send is rejected.
template.parameters
object
Values for the template's variables, keyed by the variable name. A variable name is a single word.
Every variable the template's variables lists needs a value here. A send that leaves one out is rejected rather than delivered with a blank in it. Send values for everything in that list rather than only what you expect the language you are sending to use, because languages do not have to use the same variables and a value no language uses is simply ignored.
bird is reserved for the values we fill in ourselves, so a send that sets it is rejected. parameters is capped at 16 KB once serialized.
track_opens
boolean
Whether to track open events for this message.
track_clicks
boolean
Whether to track click events for this message.
ip_pool_id
string
ID of the IP pool to send from (ipp_ prefix), or ipp_shared to route through the shared pool explicitly. Omit to use your organization's default pool. An unknown pool, or a pool with no dedicated IPs available to send from, is rejected with a 422.
category
string
Content classification, which controls suppression policy:
  • marketing: Blocks on all suppression reasons.
  • transactional: Allows delivery through complaint and unsubscribe suppressions, for receipts, password resets, and similar operational mail.
When you send with template and omit this field, the message takes the template's own classification, so a template created as transactional sends as transactional. Set this field to classify a single send differently from its template. It always takes precedence. A send with no template and no category defaults to marketing.
Possible values: marketing, transactional
attachments
array of object
Files to attach, up to 20 per message. A message can be at most 20 MB once it has been generated, and we refuse a send that would go over. That figure covers the HTML body, the text body and every attachment and inline image, all measured after base64 encoding, which adds roughly a third. So 15 MB of raw files already accounts for most of the budget, and the body competes for the same space. A batch send is held to the same 20 MB per message, and the whole request body is capped at 20 MB as well.
चाइल्ड पैरामीटर दिखाएँ
attachments.filename
string
आवश्यक
The name the recipient sees on the attachment.
attachments.content
string
आवश्यक
The file's bytes, base64-encoded. What you send here counts toward the message's 20 MB limit after encoding and MIME wrapping, not at its raw size.
attachments.content_type
string
The file's MIME type. Leave it out and we work it out from the extension on filename. This is what we check against the list of executable and script types we refuse.
attachments.content_id
string
An RFC 2392 Content-ID for the file. Set it and the attachment is shown inline, so your HTML body can point at it with <img src="cid:{content_id}"/>. Leave it out and the file arrives as an ordinary attachment the recipient downloads.
scheduled_at
string
Schedule the message to send at a future time instead of immediately. Must be at least 30 seconds and at most 30 days ahead. Outside that range the request is rejected with 422. The message returns with status accepted and shows as scheduled on reads until it sends. Cancel it before then with the message cancel endpoint. Scheduled sends count against your plan's monthly scheduled-email allowance. Exceeding it is rejected with a 422. A scheduled message has inline content: scheduled_at and template are mutually exclusive, and combining them is rejected with a 422. This field is only accepted on a single send, not on a batch item.
Response Payload
data
array of object
आवश्यक
One entry per message in the batch, in submission order.
चाइल्ड एट्रिब्यूट दिखाएँ
data.id
string
आवश्यक
Message ID assigned to this batch item.
data.status
string
आवश्यक
Initial status of this message in the batch.
Possible values: accepted
data.category
string
आवश्यक
Resolved category for this batch item.
Possible values: marketing, transactional
data.requested_language
nullable string
The template language this item asked for, in canonical form. Null when the item named no language or used no template. Every item in a batch resolves its own template reference, so this and resolved_language can differ from item to item.
data.resolved_language
nullable string
The template language this item was actually delivered in, in canonical form. Null when the item used no template. A value here differing from requested_language means the template did not have the language asked for and its on_missing_language policy chose this one.
data.template_id
nullable string
The template this item rendered from, or null for an item that supplied its content inline.
data.template_version_id
nullable string
The exact template version this item rendered from, or null for an inline item. Record it if you need to reproduce what was sent: a template's live version changes every time you submit it.