Send a message
POST
/v1/email/messages
Sends an email to the recipients you list explicitly in to/cc/bcc. Use this for transactional sends (receipts, password resets, alerts) and for marketing sends where you have the recipient addresses on hand. For sends targeting a stored audience by reference, use POST /v1/email/broadcasts. The category field controls suppression policy independently — set it to marketing when sending marketing content from this endpoint. The 202 response is returned only after the message is safely accepted for delivery. If the sender domain is not verified, or all recipients are suppressed, the request fails immediately with a 422 — it is never accepted and then silently dropped. Other field-level validation failures also return 422.
Recipient addresses on reserved testing domains are rejected with a 422 RecipientDomainNotAllowed error. This covers @example.com, @example.net, @example.org, @example.edu, @test.com, and any address under the reserved .test, .example, .invalid, or .localhost top-level domains. These placeholder domains cannot receive mail, and the resulting bounces would hurt your sender reputation — use a real recipient address instead.
During onboarding, you can send without verifying a domain: use any sender address on the shared onboarding domain (for example onboarding@messagebird.dev). Such sends skip the sender-domain verification check, can only go to verified members of your workspace (other recipients are rejected with a 422 OnboardingRecipientNotAllowed error), and are subject to a daily recipient limit per organization (429 OnboardingSendLimitExceeded once exhausted).
Anfrage-Nutzlast
from
string or object
required
Sender address, as a plain email string, an RFC 5322 mailbox string (Jane <jane@example.com>), or an object with an optional display name. Must be from a verified domain in this workspace.
to
array of string or object
required
Primary recipients. Each entry is a plain email string, an RFC 5322 mailbox string (Jane <jane@example.com>), or an object with an optional display name.
cc
array of string or object
CC recipients. Each entry is a plain email string, an RFC 5322 mailbox string (Jane <jane@example.com>), or an object with an optional display name.
bcc
array of string or object
BCC recipients. Each entry is a plain email string, an RFC 5322 mailbox string (Jane <jane@example.com>), or an object with an optional display name.
subject
string
required
Message subject line.
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 runaway header sizes that some MTAs reject.
headers
object
Custom email headers as key-value pairs.
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, and 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.
Show child parameters
name
string
required
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
value
string
required
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 (e.g. 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.
track_opens
boolean
Whether to track open events for this message.
track_clicks
boolean
Whether to track click events for this message.
ip_pool
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 — independent of which endpoint you use. Controls suppression policy: marketing blocks on all suppression reasons (use for marketing content); transactional allows delivery through complaint and unsubscribe suppressions (use for receipts, password resets, and similar operational messages). Default: transactional.
in_reply_to_message_id
string
Preview feature — threaded replies. Currently unavailable; supplying this field returns 422 unsupported_feature. When generally available, sets In-Reply-To and References headers automatically.
attachments
array of object
File attachments. Total message size (body + inline images + all attachments) capped at 20 MB post-base64. Raw file content should stay under ~15 MB to leave room after encoding. Sends with attachments cannot use POST /v1/emails/batch; use the single-send endpoint. See the EmailAttachment schema for the full field contract.
Show child parameters
filename
string
required
Filename shown to the recipient. Required.
content
string
required
Base64-encoded attachment bytes. Required. Counts against the 20 MB per-send wire cap.
path
string
Preview feature — provide a URL and Bird fetches the attachment for you. Currently unavailable. Use content instead. The schema currently requires content, so a request with only path is rejected with 422 for missing content; a request supplying both content and path is rejected with 422 unsupported_feature until this preview ships. When generally available: HTTPS-only, single redirect followed and re-validated, private IP ranges blocked, request timeout enforced, fetched content counts against the 20 MB per-send wire cap.
content_type
string
MIME type. Inferred from filename extension when omitted. Used to enforce the blocklist of disallowed executable / script types.
content_id
string
RFC 2392 Content-ID. When set, the attachment is rendered inline and can be referenced from the HTML body as <img src="cid:{content_id}"/>. When omitted, the attachment is rendered as a regular file attachment.
scheduled_at
string
Preview feature — send-later scheduling. Currently unavailable; supplying this field returns 422 unsupported_feature.
contact_id
string
Preview feature — contact-targeted sends. Currently unavailable; supplying this field returns 422 unsupported_feature.
topic_id
string
Preview feature — topic-gated sends. Currently unavailable; supplying this field returns 422 unsupported_feature. When generally available, a non-empty topic_id gates delivery on the recipient's opt-in state for that topic — if the recipient is opt_out, the send is silently suppressed and an email.suppressed event fires with reason: topic_opt_out.
Response Payload
id
string
required
Message ID.
from
object
required
Sender address. name is present when a display name was provided on the send.
Show child attributes
email
string
required
Email address.
name
string
Display name shown alongside the address in mail clients.
to
array of object
required
Primary recipients. Length is the recipient count; use the broadcasts endpoint for audience-targeted sends. Each entry's name is present when a display name was provided on the send.
Show child attributes
email
string
required
Email address.
name
string
Display name shown alongside the address in mail clients.
cc
array of object
CC recipients.
Show child attributes
email
string
required
Email address.
name
string
Display name shown alongside the address in mail clients.
bcc
array of object
BCC recipients.
Show child attributes
email
string
required
Email address.
name
string
Display name shown alongside the address in mail clients.
subject
string
required
Message subject line.
category
string
required
Content classification. Controls suppression policy — marketing blocks on all suppression reasons; transactional allows delivery through complaint and unsubscribe suppressions.
reply_to
nullable array
Reply-To addresses, if set on the send. Empty/null when no Reply-To was provided.
status
string
required
Aggregate delivery status derived from recipient states. accepted means Bird has the send and is preparing to deliver. processed means Bird has processed the message and queued it for delivery to the recipient's mail server.
accepted_count
integer
required
Number of recipients currently in the accepted state — Bird has the send and is preparing to deliver.
processed_count
integer
required
Number of recipients for whom Bird has processed the message and queued it for delivery.
delivered_count
integer
required
Number of recipients whose messages were accepted by the remote MTA.
bounced_count
integer
required
Number of recipients that resulted in a permanent delivery failure.
complained_count
integer
required
Number of recipients that reported spam.
deferred_count
integer
required
Number of recipients in transient delivery deferral; the provider is retrying.
rejected_count
integer
required
Number of recipients rejected before delivery. See the per-recipient rejection_reason field on GET /v1/emails/{id}/recipients for the specific cause (suppression match, transmission failure, generation failure, or policy refusal).
processing_latency_ms
nullable integer
Time between Bird accepting the send and the message being processed for delivery, in milliseconds, for the fastest recipient. Null until the first recipient reaches processed.
delivery_latency_ms
nullable integer
Time between the message being processed and the receiving mail server accepting it, in milliseconds, for the fastest delivered recipient. Null until the first recipient is delivered.
total_latency_ms
nullable integer
End-to-end accept → delivered time for the fastest delivered recipient, in milliseconds. Null until the first recipient is delivered.
open_count
integer
required
Total open events across all recipients.
click_count
integer
required
Total click events across all recipients.
tags
array of object
Structured {name, value} filter labels applied to this send. See EmailMessageSendRequest for the tags vs metadata distinction.
Show child attributes
name
string
required
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
value
string
required
Tag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters.
metadata
object
Arbitrary JSON metadata stored on the message object and echoed in webhook payloads. See EmailMessageSendRequest for the tags vs metadata distinction.
attachments
array of object
Attachment metadata for the send. Empty when no attachments were included. Raw content is not echoed; use the future content-retrieval endpoint when storage is enabled.
Show child attributes
id
string
Attachment ID, stable per email send.
filename
string
required
Filename as shown to the recipient.
content_type
string
Resolved MIME type at send time.
size
integer
required
Decoded size in bytes.
inline
boolean
True when the attachment was sent inline via a content_id reference in the HTML body, false for regular file attachments.
content_id
nullable string
The Content-ID set at send time, when the attachment was inline.
track_opens
boolean
required
Whether open tracking is enabled for this send.
track_clicks
boolean
required
Whether click tracking is enabled for this send.
created_at
string
required
When the send request was accepted.
thread_id
nullable string
Thread this message belongs to. Null until threading is enabled.
in_reply_to_message_id
nullable string
The message this one is a reply to, if any.
delivered_at
nullable string
When all recipients reached a terminal delivered state, or null if not yet fully delivered.
cURL
curl -X POST "https://us1.platform.bird.com/v1/email/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <noreply@acme.com>",
"to": [
"jane@example.com"
],
"subject": "Your receipt for order #1234",
"text": "Thanks for your purchase! Your receipt is attached."
}'