Send an email message
Sending is outbound and irreversible. It reports "accepted", not "delivered".
Read the message back with "bird email get" to confirm delivery. Send inline
content with --subject and --html/--text, or a stored template with --template.
Build the request from flags, a JSON EmailMessageSendRequest body via --body-file ("-" reads
stdin), or both — a flag overrides the matching body field. Run --example to
print a ready-to-edit body, or --dry-run to print the resolved request without
sending it.
# print the body shape (no credentials needed)
bird email send --example
# the body it prints:
{
"category": "transactional",
"cc": ["manager@acme.com"],
"from": {
"email": "noreply@acme.com",
"name": "Acme Support"
},
"headers": {
"X-Campaign": "spring-2026"
},
"html": "<h1>Hi there 👋</h1>",
"metadata": {
"user_id": "usr_12345"
},
"reply_to": ["support@acme.com"],
"subject": "Welcome aboard",
"tags": [
{
"name": "category",
"value": "welcome"
}
],
"text": "Hi there",
"to": [
{
"email": "delivered@messagebird.dev",
"name": "Jane Doe"
}
],
"track_clicks": false
}
# send a stored template with variable values
bird email send --from hello@bird.com --to alice@bird.com --template welcome-email --parameters '{"first_name":"Alice"}'
# send a stored template in a specific language
bird email send --from hello@bird.com --to alice@bird.com --template welcome-email --language pt-BR
# preview the resolved request without sending
bird email send --body-file body.json --dry-run
| Name | Description |
|---|
| --from | Sender address. Has to be on a domain this workspace has verified |
| --to <v1,v2,…> | Recipient address; repeatable. Accepts bare addresses or RFC 5322 "Name <addr>" form |
| --cc <v1,v2,…> | CC address; repeatable. Accepts bare addresses or RFC 5322 "Name <addr>" form |
| --bcc <v1,v2,…> | BCC address; repeatable. Accepts bare addresses or RFC 5322 "Name <addr>" form |
| --reply-to <v1,v2,…> | Reply-To address; repeatable. Accepts bare addresses or RFC 5322 "Name <addr>" form |
| Name | Description |
|---|
| --subject | Subject line |
| --html | HTML body |
| --html-file | Read the HTML body from a file |
| --text | Plain-text body |
| --text-file | Read the plain-text body from a file |
| --attach <v1,v2,…> | Attach a file by path; repeatable |
| Name | Description |
|---|
| --template | Send by a stored template: its id (emt_…) or slug (mutually exclusive with --subject/--html/--text) |
| --language | Which of the template's languages to send, as a BCP-47 tag such as en or pt-BR. Template sends only. Leave it out for the template's default, unless the template requires every send to name one. If the template does not have the language you ask for, its on_missing_language decides whether a close match is sent or the send is refused |
| --parameters | Values for the template's variables, as a JSON object keyed by variable name. Applied to the stored template on a template send, or to the inline subject and body otherwise |
| Name | Description |
|---|
| --header <key=value> | Custom header as Key=Value; repeatable |
| --tag <key=value> | Tag as name=value; repeatable |
| --metadata | Arbitrary JSON metadata object |
| Name | Description |
|---|
| --category | What kind of email this is, marketing or transactional, which decides how suppressions apply. Defaults to the template's category on a --template send, otherwise marketing |
| --ip-pool-id | IP pool id (ipp_…) to send from |
| --track-opens | Track opens (default true) |
| --track-clicks | Track link clicks (default true) |
| --scheduled-at | Send at a future time (RFC 3339, for example 2026-07-10T09:00:00Z). Between 30 seconds and 30 days ahead |
| Name | Description |
|---|
| --body-file | Read the JSON request body from this file; "-" reads stdin |
| --example | Print a complete example request body, then exit |
| --dry-run | Print the resolved request without sending it, then exit |
| --idempotency-key | Deduplication key; a retry with the same key won't act twice |
| Name | Description |
|---|
| --response-schema | Print the fields this command returns, then exit |