bird whatsapp send [flags]
Send a WhatsApp message to one recipient or one group
Sending is outbound and irreversible: it reports "accepted", not "delivered".
Read the message back with "bird whatsapp get" to confirm delivery. Carry exactly
one kind of content: a template, or free-form text, image, video, audio, sticker,
document, location, contact cards, or interactive buttons, a list, a link button
or cards.
Free-form content, interactive content included, is deliverable only inside an
open 24-hour customer service window. A Bird-managed template picks its own
sender and omits --from; every other send, free-form content or a template your
workspace authored, requires it.
A group id (wag_…) in --to sends to that group on the group's own number, so omit
--from there too. A group takes text, media, or a template your workspace
authored in any category but authentication: no interactive content, and no
Bird-managed template, which sends from a number no group is scoped to.
Build the request from flags, a JSON WhatsAppMessageSendRequest 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 whatsapp send --example
# the body it prints:
{
"template": {
"components": [
{
"parameters": [
{
"text": "1234",
"type": "text"
}
],
"type": "body"
},
{
"parameters": [
{
"text": "1234",
"type": "text"
}
],
"type": "button"
}
],
"language": "en",
"slug": "bird_otp"
},
"to": "+31612345678"
}
# print the exact list-message shape
bird whatsapp send --example interactive-list
# send a template with body placeholders
bird whatsapp send --to +15551234567 --template bird_order_confirmation --language en --components '[{"type":"body","parameters":[{"type":"text","name":"ref","text":"ORD-1042"},{"type":"text","name":"amount","text":"US$ 99.99"}]}]'
# reply with free text inside an open customer service window
bird whatsapp send --to +15551234567 --from +31612340001 --text 'Your driver is 2 minutes away.'
# send a document with a caption
bird whatsapp send --to +15551234567 --from +31612340001 --document https://cdn.example.com/invoices/a1b2c3.pdf --filename invoice-a1b2c3.pdf --caption 'Your invoice'
# ask a yes/no question with reply buttons
bird whatsapp send --to +15551234567 --from +31612340001 --interactive '{"type":"button","body_text":"Your workshop is at 9am tomorrow. Need to change it?","buttons":[{"type":"quick_reply","quick_reply":{"slug":"change","text":"Change"}},{"type":"quick_reply","quick_reply":{"slug":"cancel","text":"Cancel"}}]}'
# share a colleague's contact card
bird whatsapp send --to +15551234567 --from +31612340001 --contact-cards '[{"name":{"formatted_name":"Barbara J. Johnson","first_name":"Barbara","last_name":"Johnson"},"phone_numbers":[{"phone_number":"+16505551234","type":"Mobile"}]}]'
# quote the message you are answering
bird whatsapp send --to +15551234567 --from +31612340001 --text 'Your driver is 2 minutes away.' --in-reply-to wam_01kya19eknftrs2s6p82asmvnh
# preview the resolved request without sending
bird whatsapp send --body-file body.json --dry-run
| Name | Description |
|---|
--to | Recipient phone number in E.164 format (e.g. +15551234567), their business-scoped user ID (e.g. US.13491208655302741918), or a group id (wag_…) to send to a WhatsApp group |
--from | Sender in E.164 format. Required for free-form content and a template your workspace authored; omit it for a Bird-managed template, which picks its own sender, and for a group send, which uses the group's own number |
| Name | Description |
|---|
--template | The template to send, by its slug (e.g. bird_otp) |
--template-id | The template to send, by its id (wat_…); alternative to --template |
--language | Language code of the template variant to send (e.g. en or pt-BR); omit to send the template's default language |
--components | The values that fill the template's placeholders, as a JSON array (e.g. body/header/button component objects) |
| Name | Description |
|---|
--text | Free-text message body, up to 4096 characters |
--preview-url | Render a link preview for the first URL in --text |
--image | Public https URL of an image to send |
--video | Public https URL of a video to send |
--audio | Public https URL of an audio file to send |
--sticker | Public https URL of a sticker to send |
--document | Public https URL of a document to send |
--caption | Caption shown with --image, --video or --document |
--filename | Filename shown for --document |
--voice | Render --audio as a voice note rather than an audio file |
--latitude | Latitude in decimal degrees; send a location with --longitude |
--longitude | Longitude in decimal degrees; send a location with --latitude |
--location-name | Place name shown on the location |
--location-address | Street address shown beneath --location-name; ignored without it |
| Name | Description |
|---|
--interactive | Interactive content as a JSON object: reply buttons, a list menu, a link button, media cards, or a request for the recipient's location or contact details |
--contact-cards | Contact cards as a JSON array, up to five. Each card needs a name with formatted_name plus one other part; a phone number in E.164 earns the card a button that opens a chat |
| Name | Description |
|---|
--in-reply-to | Quote an earlier message from the same conversation, by its id (wam_…) |
| Name | Description |
|---|
--tag <key=value> | Tag as name=value; repeatable |
--metadata | Arbitrary JSON metadata object |
| Name | Description |
|---|
--body-file | Read the JSON request body from this file; "-" reads stdin |
--example | Print an example body; optionally name a content kind, e.g. --example interactive-list |
--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 |