Send a WhatsApp message
POST
/v1/whatsapp/messages
const msg = await bird.whatsapp.send({
to: "+15551234567",
template: {
slug: "bird_otp",
components: [{ type: "body", parameters: [{ type: "text", text: "123456" }] }],
},
});
console.log(msg.id, msg.status);msg = client.whatsapp.send(
to="+31612345678",
template="bird_otp",
language="en",
components=[{"type": "body", "parameters": [{"type": "text", "text": "123456"}]}],
)
print(msg.id, msg.status)code := "123456"
msg, err := client.Whatsapp.Send(context.Background(), bird.WhatsappSendParams{
To: "+15551234567",
Template: "bird_otp",
Language: "en",
Components: []bird.WhatsAppMessageTemplateComponent{{
Type: "body",
Parameters: &[]bird.WhatsAppMessageTemplateComponentParameter{{Type: "text", Text: &code}},
}},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)$message = $bird->whatsapp->send(
to: '+15551234567',
template: 'bird_otp',
language: 'en',
components: [
(new WhatsAppMessageTemplateComponent())
->setType('body')
->setParameters([
(new WhatsAppMessageTemplateComponentParameter())->setType('text')->setText('123456'),
]),
],
);
echo $message->getId(), ' ', $message->getStatus();bird whatsapp send \
--components '[{"parameters":[{"text":"1234","type":"text"}],"type":"body"},{"parameters":[{"text":"1234","type":"text"}],"type":"button"}]' \
--language en \
--template bird_otp \
--to +31612345678curl -X POST "https://us1.platform.bird.com/v1/whatsapp/messages" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "+31612345678",
"template": {
"slug": "bird_otp",
"language": "en",
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "1234"
}
]
},
{
"type": "button",
"parameters": [
{
"type": "text",
"text": "1234"
}
]
}
]
}
}'Antwort202
{
"id": "wam_01kya19eknftrs2s6p82asmvnh",
"direction": "outbound",
"from": {
"phone_number": "+15550001111"
},
"to": {
"group_id": "wag_01krdgeqcxet5s7t44vh8rt9mg"
},
"text": {
"body": "The route sheet for Tuesday is up."
},
"status": "accepted",
"recipient_count": 2,
"delivered_count": 0,
"read_count": 0,
"created_at": "2026-09-15T14:03:10Z"
}
Sends one WhatsApp message to one recipient. The request carries exactly one
kind of content: a message template, or free-form text, image, video,
audio, sticker, document, location, contact_cards or
interactive. A request carrying none is rejected with a 422, and one
carrying more than one is too.
A template is the only content WhatsApp delivers outside an open
customer service window, so it is what starts a conversation. Name the
template, optionally pick its language variant, and fill its placeholders in
components. A Bird-managed template selects its sender number from its
category, so the request carries no from; a template your workspace
authored requires one. Browse your workspace's templates in the Bird
dashboard.
Free-form content is deliverable only inside an open 24-hour customer
service window, which the contact opens by messaging or calling you and
resets each time they do it again. Bird tracks that window, so a send into a
closed one is refused with a 422 WhatsAppServiceWindowClosed before
anything is created or charged;
send a template instead, which reopens the window once the contact replies.
A window that closes between accept and dispatch still fails
asynchronously, carrying service_window_expired on the message's
last_error. Every free-form send requires from.
Interactive content gives the recipient something to tap. interactive
names its kind in type and carries that kind's own field: reply buttons,
a list menu, a cta_url link button, or cards for a carousel;
location_request_message and request_contact_info are each a single
button asking the recipient for something, so body_text is the whole
message. A tap on a reply button or a list row comes back as an inbound
message carrying interactive_reply. The other kinds answer in their own
shape: a cta_url link opens in the recipient's browser and sends nothing
back, and the two request kinds come back as the thing they asked for, an
inbound location or contact_cards message.
Interactive content is free-form, so the customer service window and the
from requirement above both apply.
Contact cards share up to five contacts in one message. Each card's
name needs formatted_name plus at least one other part, and a
phone_number in E.164 earns that card a button opening a chat with it.
Contact cards are free-form too, so the same window and from rules apply.
A group send addresses a WhatsApp group ID in to and carries no
from: the group sends on its own number, and the response reports the
fan-out.
recipient_count is the group's membership when the send was accepted,
delivered_count and read_count count against it, and status turns
delivered only once every participant has it. WhatsApp delivers neither
interactive content nor an authentication template to a group, and a
Bird-managed template sends from a number no group is scoped to.
Set in_reply_to_message_id to quote a message the contact sees above this
one, the way replying in the WhatsApp client does. Any content quotes, and
the quoted message must be one from this same conversation.
The 202 response is the accepted message, echoing the resolved content; it
is not a delivery confirmation. Follow delivery with
Get a WhatsApp message, the
per-message timeline from
List events for a WhatsApp message,
or whatsapp.* webhook events.
Each of these returns a 422:
- A template slug or language the catalogue does not stock.
- Parameter values that do not match the template's declared placeholders.
- A from this workspace cannot send from.
- A recipient that is neither a valid phone number nor a business-scoped user ID.
- Free-form content sent into a closed customer service window (WhatsAppServiceWindowClosed).
- Interactive content or an authentication template addressed to a group (WhatsAppGroupContentNotSupported).
A group to naming no group this workspace holds fails with a 404
WhatsAppGroupNotFound, and one whose group is not active with a 409
WhatsAppGroupNotActive. A send from a workspace with no wallet balance
fails with a 402.
Anfrage-Nutzlast
to
string
erforderlich
The message recipient: a phone number in E.164 format (for example +31612345678), the recipient's business-scoped user ID (for example US.13491208655302741918), which addresses a WhatsApp user whose phone number you do not have, or a WhatsApp group ID (for example wag_01krdgeqcxet5s7t44vh8rt9mg), which sends to every participant of that group. A value that is none of these returns a 422 WhatsAppInvalidRecipient. One-time-passcode templates require a phone number and return a 422 WhatsAppRecipientNotSupportedForTemplate when sent to a business-scoped user ID. A group ID naming no group this workspace holds returns a 404 WhatsAppGroupNotFound, and one whose group is not active returns a 409 WhatsAppGroupNotActive. Content a group cannot take is refused ahead of both, so a group ID paired with interactive content returns the 422 below whether or not the group exists.
from
string
The business phone number to send from, in E.164 format. Omit it for a Bird-managed template, which selects its own number from its category: setting it there returns a 422 WhatsAppSenderNotAllowed. Every other send, whether free-form content of any kind or a template your workspace authored, requires it, and the number must be one this workspace owns. Omitting it returns a 422 WhatsAppSenderRequired, and naming a number this workspace cannot send from returns a 422 WhatsAppSenderNotFound. Naming a number this workspace owns but that sits on a different WhatsApp Business Account than an authored template returns a 422 WhatsAppSenderWABAMismatch. A number this workspace holds but has not finished connecting returns a 422 WhatsAppSenderNotConnected. Omit it for a group send too: the group sends on its own number, so naming one returns a 422 WhatsAppSenderNotAllowed.
template
object
The template to send. A Bird-managed template selects the sender number from the template's category, so from must be omitted. A template is the only content deliverable outside a customer service window. A group send takes a template your workspace authored in any category but authentication: WhatsApp does not deliver an authentication template to a group, which returns a 422 WhatsAppGroupContentNotSupported. A Bird-managed template sends from a Bird-owned number that no group is scoped to, so addressing one to a group returns a 422 WhatsAppInvalidRecipient.
Untergeordnete Parameter anzeigen
template.id
string
erforderlich
The template to send, by its id.
template.language
string
Which of the template's languages to send, as a BCP-47 tag (for example en or pt-BR); Meta's underscore form (pt_BR) is accepted and normalized. 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 carry 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. The accepted message echoes the canonical BCP-47 form of the language it resolved to, which is the language it is priced at: Meta categorizes each language separately, so a send served by a different language than the one you asked for is priced at that language's category.
template.components
array of object
The values that fill the template's placeholders: one entry per content block that has placeholders, each carrying its parameters. A positional template takes its parameters in {{n}} order; a template with named parameters requires each parameter's name to match one the template declares. Either way, sending parameters that do not match what the template declares returns a 422 WhatsAppTemplateParameterMismatch.
Untergeordnete Parameter anzeigen
template.components.type
string
erforderlich
Which part of the template this fills in.
- body: the main text.
- button: a button's variable.
- header: the header's text, media or location.
- carousel: the cards.
Possible values (may grow over time): header, body, button, carousel
template.components.parameters
array of object
The values that fill this part's placeholders. A positional template takes them in {{n}} placeholder order; a template with named parameters requires each parameter's name to match one the template declares, and order then carries no meaning. Send it on every part except carousel, which carries its values on cards. Send no button part at all for a button that takes no value, such as a quick_reply or request_contact_info button, or a url button whose address has no placeholder: a part the template has no slot for is refused here, before the message is sent and charged.
Untergeordnete Parameter anzeigen
template.components.parameters.type
string
erforderlich
The kind of value this parameter carries, which decides which of the fields below to send.
template.components.parameters.text
string
The value substituted into the placeholder, as a plain string. Send it on a text parameter.
template.components.parameters.url
string
Public https URL of the file a media header shows. Send it on an image, video, gif or document parameter. WhatsApp fetches it at send time, so it must still be reachable then, the same way a free-form media message's url must.
template.components.parameters.location
object
The point on the map a location header opens. Send it on a location parameter.
Untergeordnete Parameter anzeigen
template.components.parameters.location.latitude
number
erforderlich
Latitude in decimal degrees.
template.components.parameters.location.longitude
number
erforderlich
Longitude in decimal degrees.
template.components.parameters.location.name
string
Name of the place, shown above the address.
template.components.parameters.location.address
string
Street address of the place. Shown only when name is also set.
template.components.parameters.name
string
Required when the template declares named parameters: the placeholder this value fills (for example first_name), matching exactly one of the names the template declares. Name every parameter in that case; order does not matter once names are supplied. Omit this field for a positional template, which takes its values in {{n}} order instead. Sending the wrong set of names, or leaving one out that the template requires, returns a 422 WhatsAppTemplateParameterMismatch.
template.components.cards
array of object
The values that fill each card of a carousel. Send it only on a carousel part. A carousel sends exactly the number of cards its template was approved with, so every card needs an entry.
Untergeordnete Parameter anzeigen
template.components.cards.components
array of object
erforderlich
The values that fill this card's blocks.
Untergeordnete Parameter anzeigen
template.components.cards.components.type
string
erforderlich
Which part of the card this fills in.
- header: the card's image or video.
- body: its text.
- button: a button's variable.
Possible values (may grow over time): header, body, button
template.components.cards.components.parameters
array of object
The values that fill this part's placeholders, in placeholder order.
Untergeordnete Parameter anzeigen
template.components.cards.components.parameters.type
string
erforderlich
The kind of value this parameter carries, which decides which of the fields below to send.
template.components.cards.components.parameters.text
string
The value substituted into the placeholder, as a plain string. Send it on a text parameter.
template.components.cards.components.parameters.url
string
Public https URL of the file a media header shows. Send it on an image, video, gif or document parameter. WhatsApp fetches it at send time, so it must still be reachable then, the same way a free-form media message's url must.
template.components.cards.components.parameters.location
object
The point on the map a location header opens. Send it on a location parameter.
Untergeordnete Parameter anzeigen
template.components.cards.components.parameters.location.latitude
number
erforderlich
Latitude in decimal degrees.
template.components.cards.components.parameters.location.longitude
number
erforderlich
Longitude in decimal degrees.
template.components.cards.components.parameters.location.name
string
Name of the place, shown above the address.
template.components.cards.components.parameters.location.address
string
Street address of the place. Shown only when name is also set.
template.components.cards.components.parameters.name
string
Required when the template declares named parameters: the placeholder this value fills (for example first_name), matching exactly one of the names the template declares. Name every parameter in that case; order does not matter once names are supplied. Omit this field for a positional template, which takes its values in {{n}} order instead. Sending the wrong set of names, or leaving one out that the template requires, returns a 422 WhatsAppTemplateParameterMismatch.
template.slug
string
erforderlich
The template to send, by its slug handle (for example bird_otp).
template.language
string
Which of the template's languages to send, as a BCP-47 tag (for example en or pt-BR); Meta's underscore form (pt_BR) is accepted and normalized. 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 carry 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. The accepted message echoes the canonical BCP-47 form of the language it resolved to, which is the language it is priced at: Meta categorizes each language separately, so a send served by a different language than the one you asked for is priced at that language's category.
template.components
array of object
The values that fill the template's placeholders: one entry per content block that has placeholders, each carrying its parameters. A positional template takes its parameters in {{n}} order; a template with named parameters requires each parameter's name to match one the template declares. Either way, sending parameters that do not match what the template declares returns a 422 WhatsAppTemplateParameterMismatch.
Untergeordnete Parameter anzeigen
template.components.type
string
erforderlich
Which part of the template this fills in.
- body: the main text.
- button: a button's variable.
- header: the header's text, media or location.
- carousel: the cards.
Possible values (may grow over time): header, body, button, carousel
template.components.parameters
array of object
The values that fill this part's placeholders. A positional template takes them in {{n}} placeholder order; a template with named parameters requires each parameter's name to match one the template declares, and order then carries no meaning. Send it on every part except carousel, which carries its values on cards. Send no button part at all for a button that takes no value, such as a quick_reply or request_contact_info button, or a url button whose address has no placeholder: a part the template has no slot for is refused here, before the message is sent and charged.
Untergeordnete Parameter anzeigen
template.components.parameters.type
string
erforderlich
The kind of value this parameter carries, which decides which of the fields below to send.
template.components.parameters.text
string
The value substituted into the placeholder, as a plain string. Send it on a text parameter.
template.components.parameters.url
string
Public https URL of the file a media header shows. Send it on an image, video, gif or document parameter. WhatsApp fetches it at send time, so it must still be reachable then, the same way a free-form media message's url must.
template.components.parameters.location
object
The point on the map a location header opens. Send it on a location parameter.
Untergeordnete Parameter anzeigen
template.components.parameters.location.latitude
number
erforderlich
Latitude in decimal degrees.
template.components.parameters.location.longitude
number
erforderlich
Longitude in decimal degrees.
template.components.parameters.location.name
string
Name of the place, shown above the address.
template.components.parameters.location.address
string
Street address of the place. Shown only when name is also set.
template.components.parameters.name
string
Required when the template declares named parameters: the placeholder this value fills (for example first_name), matching exactly one of the names the template declares. Name every parameter in that case; order does not matter once names are supplied. Omit this field for a positional template, which takes its values in {{n}} order instead. Sending the wrong set of names, or leaving one out that the template requires, returns a 422 WhatsAppTemplateParameterMismatch.
template.components.cards
array of object
The values that fill each card of a carousel. Send it only on a carousel part. A carousel sends exactly the number of cards its template was approved with, so every card needs an entry.
Untergeordnete Parameter anzeigen
template.components.cards.components
array of object
erforderlich
The values that fill this card's blocks.
Untergeordnete Parameter anzeigen
template.components.cards.components.type
string
erforderlich
Which part of the card this fills in.
- header: the card's image or video.
- body: its text.
- button: a button's variable.
Possible values (may grow over time): header, body, button
template.components.cards.components.parameters
array of object
The values that fill this part's placeholders, in placeholder order.
Untergeordnete Parameter anzeigen
template.components.cards.components.parameters.type
string
erforderlich
The kind of value this parameter carries, which decides which of the fields below to send.
template.components.cards.components.parameters.text
string
The value substituted into the placeholder, as a plain string. Send it on a text parameter.
template.components.cards.components.parameters.url
string
Public https URL of the file a media header shows. Send it on an image, video, gif or document parameter. WhatsApp fetches it at send time, so it must still be reachable then, the same way a free-form media message's url must.
template.components.cards.components.parameters.location
object
The point on the map a location header opens. Send it on a location parameter.
Untergeordnete Parameter anzeigen
template.components.cards.components.parameters.location.latitude
number
erforderlich
Latitude in decimal degrees.
template.components.cards.components.parameters.location.longitude
number
erforderlich
Longitude in decimal degrees.
template.components.cards.components.parameters.location.name
string
Name of the place, shown above the address.
template.components.cards.components.parameters.location.address
string
Street address of the place. Shown only when name is also set.
template.components.cards.components.parameters.name
string
Required when the template declares named parameters: the placeholder this value fills (for example first_name), matching exactly one of the names the template declares. Name every parameter in that case; order does not matter once names are supplied. Omit this field for a positional template, which takes its values in {{n}} order instead. Sending the wrong set of names, or leaving one out that the template requires, returns a 422 WhatsAppTemplateParameterMismatch.
text
object
Free-form text to send instead of a template. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error.
Untergeordnete Parameter anzeigen
text.body
string
erforderlich
The message text. The WhatsApp client turns any URL it contains into a clickable link.
text.preview_url
boolean
Whether the WhatsApp client renders a preview of the first URL in body. A URL must begin with http:// or https://, only the first one is previewed, and the client falls back to a plain link when it cannot fetch a preview. Not returned when the message is read back, because WhatsApp does not report whether a preview rendered.
image
object
A free-form image to send instead of a template. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error.
Untergeordnete Parameter anzeigen
image.url
string
erforderlich
Public https URL of the image. WhatsApp fetches it at send time, so it must still be reachable then: a signed URL has to outlive the send. We do not store or proxy the file. WhatsApp caches a fetched URL for 10 minutes and re-serves that copy for an identical URL sent again within the window; vary the URL to force a re-fetch. JPEG and PNG only, up to 5 MB.
image.caption
string
Text shown beneath the image.
video
object
A free-form video to send instead of a template. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error.
Untergeordnete Parameter anzeigen
video.url
string
erforderlich
Public https URL of the video. WhatsApp fetches it at send time, so it must still be reachable then: a signed URL has to outlive the send. We do not store or proxy the file. WhatsApp caches a fetched URL for 10 minutes and re-serves that copy for an identical URL sent again within the window; vary the URL to force a re-fetch. MP4 with H.264 video and AAC audio, up to 16 MB.
video.caption
string
Text shown beneath the video.
audio
object
Free-form audio to send instead of a template. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error.
Untergeordnete Parameter anzeigen
audio.url
string
erforderlich
Public https URL of the audio file. WhatsApp fetches it at send time, so it must still be reachable then: a signed URL has to outlive the send. We do not store or proxy the file. WhatsApp caches a fetched URL for 10 minutes and re-serves that copy for an identical URL sent again within the window; vary the URL to force a re-fetch. AAC, AMR, MP3, M4A and OGG (OPUS codec, mono) are supported, up to 16 MB.
audio.voice
boolean
Whether to send this as a voice note rather than a basic audio message. A voice note auto-downloads, shows the sender's profile picture, and can be transcribed for the recipient. It requires an .ogg file encoded with the OPUS codec; any other format makes transcription fail. Leave it false for an ordinary audio attachment.
sticker
object
A free-form sticker to send instead of a template. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error.
Untergeordnete Parameter anzeigen
sticker.url
string
erforderlich
Public https URL of the sticker. WhatsApp fetches it at send time, so it must still be reachable then: a signed URL has to outlive the send. We do not store or proxy the file. WhatsApp caches a fetched URL for 10 minutes and re-serves that copy for an identical URL sent again within the window; vary the URL to force a re-fetch. WebP only: up to 100 KB for a static sticker and 500 KB for an animated one. A sticker carries no caption.
document
object
A free-form document to send instead of a template. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error.
Untergeordnete Parameter anzeigen
document.url
string
erforderlich
Public https URL of the document. WhatsApp fetches it at send time, so it must still be reachable then: a signed URL has to outlive the send. We do not store or proxy the file. WhatsApp caches a fetched URL for 10 minutes and re-serves that copy for an identical URL sent again within the window; vary the URL to force a re-fetch. Up to 100 MB. PDF, Word, Excel, PowerPoint and plain text render reliably in the WhatsApp client; other file types are transmitted but WhatsApp does not support them.
document.caption
string
Text shown beneath the document.
document.filename
string
Name the recipient sees, including the extension. WhatsApp derives one from the URL when you omit it.
location
object
A free-form location to send instead of a template. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error.
Untergeordnete Parameter anzeigen
location.latitude
number
erforderlich
Latitude in decimal degrees.
location.longitude
number
erforderlich
Longitude in decimal degrees.
location.name
string
Name of the place, shown above the address.
location.address
string
Street address of the place. Shown only when name is also set.
interactive
object
Free-form interactive content to send instead of a template: body text plus reply buttons, a menu, a link button, media cards, or a single button asking the recipient to share their location or their phone number. Deliverable only inside an open 24-hour customer service window, which the contact opens by messaging or calling you and resets each time they do it again. A send into a closed window is refused with a 422 WhatsAppServiceWindowClosed before anything is created or charged; one whose window closes between accept and dispatch fails asynchronously, with service_window_expired on the message's last_error. WhatsApp does not deliver interactive content to a group, so a group recipient returns a 422 WhatsAppGroupContentNotSupported.
Untergeordnete Parameter anzeigen
interactive.type
string
erforderlich
Which kind of interactive message this is, and which field carries it.
Value: button
interactive.header
object
Optional content above the body. A list accepts a text header only; button and cta_url also accept an image, video or document. A carousel accepts none: its cards carry their own media. Neither request kind accepts one.
Untergeordnete Parameter anzeigen
interactive.header.type
string
erforderlich
Which kind of header this is, and which field carries it.
Value: text
interactive.header.text
string
erforderlich
A single line of text above the body. Send it on a text header.
interactive.header.type
string
erforderlich
Which kind of header this is, and which field carries it.
Possible values: image, video, document
interactive.header.url
string
erforderlich
Public https URL of the file to show. Send it on an image, video or document header. An image must be JPEG or PNG, up to 5 MB; a video, MP4 with H.264 video and AAC audio, up to 16 MB; a document, up to 100 MB, and PDF, Word, Excel, PowerPoint and plain text render reliably in the WhatsApp client while other file types are transmitted but unsupported. WhatsApp fetches it at send time, so it must still be reachable then: a signed URL has to outlive the send. We do not store or proxy the file. WhatsApp caches a fetched URL for 10 minutes and re-serves that copy for an identical URL sent again within the window; vary the URL to force a re-fetch.
interactive.body_text
string
erforderlich
The message's main text, required on every kind, and the whole message on location_request_message and request_contact_info. The WhatsApp client turns any URL it contains into a clickable link. Only a list may use the full length; the other kinds cap it at 1024 characters.
interactive.footer_text
string
Optional small print below the body and above the buttons. A carousel and both request kinds take no footer.
interactive.buttons
array of object
erforderlich
The buttons to show, in the order given. Send this on a button message, where every button is a quick_reply. Every label must be unique within the message; a repeat returns a 422 WhatsAppInteractiveDuplicateLabel.
Untergeordnete Parameter anzeigen
interactive.buttons.type
string
erforderlich
Which kind of button this is, and which field carries it.
Value: quick_reply
interactive.buttons.quick_reply
object
erforderlich
The button's label and the handle it sends back. Send this on a quick_reply button.
Untergeordnete Parameter anzeigen
interactive.buttons.quick_reply.slug
string
erforderlich
Your own handle for this button, echoed back on the reply. You choose the value and it is never shown to the recipient, so it can carry whatever your application needs to route the answer. Any characters, up to 256.
interactive.buttons.quick_reply.text
string
erforderlich
The button's label. It must differ from every other button's label in the same message, because the recipient's reply is identified to them by the label they tapped.
interactive.type
string
erforderlich
Which kind of interactive message this is, and which field carries it.
Value: list
interactive.header
object
Optional content above the body. A list accepts a text header only; button and cta_url also accept an image, video or document. A carousel accepts none: its cards carry their own media. Neither request kind accepts one.
Untergeordnete Parameter anzeigen
interactive.header.type
string
erforderlich
Which kind of header this is, and which field carries it.
Value: text
interactive.header.text
string
erforderlich
A single line of text above the body. Send it on a text header.
interactive.body_text
string
erforderlich
The message's main text, required on every kind, and the whole message on location_request_message and request_contact_info. The WhatsApp client turns any URL it contains into a clickable link. Only a list may use the full length; the other kinds cap it at 1024 characters.
interactive.footer_text
string
Optional small print below the body and above the buttons. A carousel and both request kinds take no footer.
interactive.list
object
erforderlich
The menu to show. Send this on a list message.
Untergeordnete Parameter anzeigen
interactive.list.button_text
string
erforderlich
The label of the button that opens the menu.
interactive.list.sections
array of object
erforderlich
The groups of options in the menu, in the order shown. At most 10 rows across all groups combined, each carrying a label unique across the whole message.
Untergeordnete Parameter anzeigen
interactive.list.sections.title
string
erforderlich
The group's heading, shown above its rows.
interactive.list.sections.rows
array of object
erforderlich
The options in this group. A message carries at most 10 rows across all its groups combined, so this per-group maximum is not additive: more than 10 in total returns a 422 WhatsAppInteractiveLimitExceeded. Row labels must be unique across the whole message too, not just within a group.
Untergeordnete Parameter anzeigen
interactive.list.sections.rows.slug
string
erforderlich
Your own handle for this option, echoed back on the reply. You choose the value and it is never shown to the recipient. Any characters, up to 200.
interactive.list.sections.rows.text
string
erforderlich
The option's label, shown as the row's title in the menu. It must differ from every other row's label and from every button's label in the same message, not merely within its own group; a repeat returns a 422 WhatsAppInteractiveDuplicateLabel.
interactive.list.sections.rows.description
string
A second line under the label, for detail that will not fit in it.
interactive.type
string
erforderlich
Which kind of interactive message this is, and which field carries it.
Value: cta_url
interactive.header
object
Optional content above the body. A list accepts a text header only; button and cta_url also accept an image, video or document. A carousel accepts none: its cards carry their own media. Neither request kind accepts one.
Untergeordnete Parameter anzeigen
interactive.header.type
string
erforderlich
Which kind of header this is, and which field carries it.
Value: text
interactive.header.text
string
erforderlich
A single line of text above the body. Send it on a text header.
interactive.header.type
string
erforderlich
Which kind of header this is, and which field carries it.
Possible values: image, video, document
interactive.header.url
string
erforderlich
Public https URL of the file to show. Send it on an image, video or document header. An image must be JPEG or PNG, up to 5 MB; a video, MP4 with H.264 video and AAC audio, up to 16 MB; a document, up to 100 MB, and PDF, Word, Excel, PowerPoint and plain text render reliably in the WhatsApp client while other file types are transmitted but unsupported. WhatsApp fetches it at send time, so it must still be reachable then: a signed URL has to outlive the send. We do not store or proxy the file. WhatsApp caches a fetched URL for 10 minutes and re-serves that copy for an identical URL sent again within the window; vary the URL to force a re-fetch.
interactive.body_text
string
erforderlich
The message's main text, required on every kind, and the whole message on location_request_message and request_contact_info. The WhatsApp client turns any URL it contains into a clickable link. Only a list may use the full length; the other kinds cap it at 1024 characters.
interactive.footer_text
string
Optional small print below the body and above the buttons. A carousel and both request kinds take no footer.
interactive.cta_url
object
erforderlich
The link button to show. Send this on a cta_url message.
Untergeordnete Parameter anzeigen
interactive.cta_url.text
string
erforderlich
The button's label.
interactive.cta_url.url
string
erforderlich
The address the button opens. It is fixed for every recipient, so per recipient tracking belongs in the address you supply, for example as a query parameter you generate per send.
interactive.type
string
erforderlich
Which kind of interactive message this is, and which field carries it.
Value: carousel
interactive.body_text
string
erforderlich
The message's main text, required on every kind, and the whole message on location_request_message and request_contact_info. The WhatsApp client turns any URL it contains into a clickable link. Only a list may use the full length; the other kinds cap it at 1024 characters.
interactive.cards
array of object
erforderlich
The cards to show, in the order they appear, left to right. Send this on a carousel message, with between 2 and 10 cards. The message's own body_text introduces them; a carousel carries no header and no footer of its own.
Untergeordnete Parameter anzeigen
interactive.cards.header
object
erforderlich
The image or video at the top of the card.
Untergeordnete Parameter anzeigen
interactive.cards.header.type
string
erforderlich
Which kind of media this is. A card accepts image or video only.
Value: image
interactive.cards.header.url
string
erforderlich
Public https URL of the file to show at the top of the card. An image must be JPEG or PNG, up to 5 MB; a video, MP4 with H.264 video and AAC audio, up to 16 MB. WhatsApp fetches it at send time, on the same terms as a message header's url.
interactive.cards.header.type
string
erforderlich
Which kind of media this is. A card accepts image or video only.
Value: video
interactive.cards.header.url
string
erforderlich
Public https URL of the file to show at the top of the card. An image must be JPEG or PNG, up to 5 MB; a video, MP4 with H.264 video and AAC audio, up to 16 MB. WhatsApp fetches it at send time, on the same terms as a message header's url.
interactive.cards.body_text
string
The card's own text, below its media, with at most two line breaks. Optional: a card can carry media and buttons alone.
interactive.cards.buttons
array of object
erforderlich
The buttons under the card, in the order given. Either one cta_url button or up to three quick_reply buttons: the two kinds cannot be mixed on one card. Every card in the carousel must carry the same kinds in the same number, and a carousel whose cards disagree returns a 422 WhatsAppInteractiveCarouselButtonsMismatch.
Untergeordnete Parameter anzeigen
interactive.cards.buttons.type
string
erforderlich
Which kind of button this is, and which field carries it.
Value: quick_reply
interactive.cards.buttons.quick_reply
object
erforderlich
The button's label and the handle it sends back. Send this on a quick_reply button.
Untergeordnete Parameter anzeigen
interactive.cards.buttons.quick_reply.slug
string
erforderlich
Your own handle for this button, echoed back on the reply. You choose the value and it is never shown to the recipient, so it can carry whatever your application needs to route the answer. Any characters, up to 256.
interactive.cards.buttons.quick_reply.text
string
erforderlich
The button's label. It must differ from every other button's label in the same message, because the recipient's reply is identified to them by the label they tapped.
interactive.cards.buttons.type
string
erforderlich
Which kind of button this is, and which field carries it.
Value: cta_url
interactive.cards.buttons.cta_url
object
erforderlich
The button's label and the address it opens. Send this on a cta_url button.
Untergeordnete Parameter anzeigen
interactive.cards.buttons.cta_url.text
string
erforderlich
The button's label.
interactive.cards.buttons.cta_url.url
string
erforderlich
The address the button opens. It is fixed for every recipient, so per recipient tracking belongs in the address you supply, for example as a query parameter you generate per send.
interactive.type
string
erforderlich
Which kind of interactive message this is, and which field carries it.
Value: location_request_message
interactive.body_text
string
erforderlich
The message's main text, required on every kind, and the whole message on location_request_message and request_contact_info. The WhatsApp client turns any URL it contains into a clickable link. Only a list may use the full length; the other kinds cap it at 1024 characters.
interactive.type
string
erforderlich
Which kind of interactive message this is, and which field carries it.
Value: request_contact_info
interactive.body_text
string
erforderlich
The message's main text, required on every kind, and the whole message on location_request_message and request_contact_info. The WhatsApp client turns any URL it contains into a clickable link. Only a list may use the full length; the other kinds cap it at 1024 characters.
contact_cards
array of object
Contact cards to send instead of a template. Up to five: WhatsApp accepts far more, and a message that opens as one name plus a count of the rest is not a card the recipient will read.
Untergeordnete Parameter anzeigen
contact_cards.name
object
erforderlich
Untergeordnete Parameter anzeigen
contact_cards.name.formatted_name
string
erforderlich
The whole name, as the card should render it.
contact_cards.name.first_name
string
contact_cards.name.middle_name
string
contact_cards.name.last_name
string
contact_cards.name.prefix
string
contact_cards.name.suffix
string
contact_cards.org
object
Where the contact works.
Untergeordnete Parameter anzeigen
contact_cards.org.company
string
contact_cards.org.department
string
contact_cards.org.title
string
contact_cards.birthday
string
The contact's birthday, as YYYY-MM-DD. WhatsApp rejects any other shape, and a date no calendar holds is rejected too.
contact_cards.phone_numbers
array of object
The numbers on the card. A number in E.164 renders a button that opens a WhatsApp chat with it; one that is not renders an invite instead.
Untergeordnete Parameter anzeigen
contact_cards.phone_numbers.phone_number
string
erforderlich
The number to show. Send it in E.164 to get a card the recipient can message from; any other form still renders, with an invite button.
contact_cards.phone_numbers.type
string
A label for the number, shown beside it. Free text: WhatsApp defines no vocabulary, and the label is sent exactly as written.
contact_cards.emails
array of object
Untergeordnete Parameter anzeigen
contact_cards.emails.email
string
erforderlich
contact_cards.emails.type
string
A label for the address, shown beside it. Free text, sent exactly as written.
contact_cards.urls
array of object
Untergeordnete Parameter anzeigen
contact_cards.urls.url
string
erforderlich
The address to show. Not validated as a URL, because a card commonly carries a bare domain.
contact_cards.urls.type
string
A label for the website, shown beside it. Free text, sent exactly as written.
contact_cards.addresses
array of object
Untergeordnete Parameter anzeigen
contact_cards.addresses.street
string
contact_cards.addresses.city
string
contact_cards.addresses.state
string
contact_cards.addresses.zip
string
contact_cards.addresses.country
string
contact_cards.addresses.country_code
string
The country as it should appear on the address, commonly the ISO two-letter code.
contact_cards.addresses.type
string
A label for the address, shown beside it. Free text, sent exactly as written.
in_reply_to_message_id
string
Quote a message the contact will see above this one, the way replying in the WhatsApp client does. Name a message from the same conversation: one this workspace sent to this recipient, or received from them. Any content quotes, template or free-form. The quote is resolved before the send is accepted, so a quote WhatsApp cannot render fails this request rather than the message. An id naming no message this workspace holds, or one older than the 15 days we keep provider ids for, answers 404; a message that never reached WhatsApp, or one from a different conversation than this send's to and from, answers 422. Nothing is charged either way.
tags
array of object
Structured {name, value} labels for filtering. Tags become first-class query dimensions: filter the list endpoint by tag name. Maximum 20 tags per send. Use tags for low-cardinality dimensions (category, experiment_variant). For arbitrary structured context you do not need as a filter dimension, use metadata instead.
Untergeordnete Parameter anzeigen
tags.name
string
erforderlich
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
tags.value
string
erforderlich
Tag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters.
metadata
object
Arbitrary JSON object stored on the message and returned on API reads. Maximum 2 KB serialized. Use metadata for per-send context like internal IDs and foreign keys. For low-cardinality filterable labels, use tags instead.
Antwort-Payload
id
string
erforderlich
ID of the message, assigned when the send is accepted. Pass it as message_id to the get-message and list-events endpoints.
direction
string
erforderlich
Whether the message was sent by the business (outbound) or received from the contact (inbound).
Possible values: outbound, inbound
from
object
erforderlich
Sender of the message. On outbound messages, the business number it was sent from; on inbound, the WhatsApp contact.
Untergeordnete Attribute anzeigen
from.phone_number
string
Phone number in E.164 format, when known.
from.bsuid
string
Business-scoped user ID, Meta's identifier for the WhatsApp user. Present only on the WhatsApp-user side of the message.
from.group_id
string
The group this address was addressed as, or reached through. It appears on a message's to and nowhere else: never on from, and never on an event's recipient. Outbound, it stands in for the recipient, because a group send names no single phone number. Inbound, it qualifies one: to carries the business phone_number that received the message and the group it arrived through, while from stays the participant who wrote it. Its presence on to is what tells a group message from a one-to-one one, in either direction.
from.username
string
Present only on a message received from a WhatsApp user, on from; never on an outbound send's to, where the profile is not known. Absent when the contact has not adopted one, and on a message received before this workspace started recording them. Same form as a number's own username (WhatsAppNumberProfile.username), without a leading @; a message cannot be addressed by it.
from.display_name
string
Present only on a message received from a WhatsApp user, on from; never on an outbound send's to, where the profile is not known. Absent when the message carries no profile, and on a message received before this workspace started recording them.
to
object
erforderlich
Recipient of the message. On outbound messages, the WhatsApp contact; on inbound, the business number.
Untergeordnete Attribute anzeigen
to.phone_number
string
Phone number in E.164 format, when known.
to.bsuid
string
Business-scoped user ID, Meta's identifier for the WhatsApp user. Present only on the WhatsApp-user side of the message.
to.group_id
string
The group this address was addressed as, or reached through. It appears on a message's to and nowhere else: never on from, and never on an event's recipient. Outbound, it stands in for the recipient, because a group send names no single phone number. Inbound, it qualifies one: to carries the business phone_number that received the message and the group it arrived through, while from stays the participant who wrote it. Its presence on to is what tells a group message from a one-to-one one, in either direction.
to.username
string
Present only on a message received from a WhatsApp user, on from; never on an outbound send's to, where the profile is not known. Absent when the contact has not adopted one, and on a message received before this workspace started recording them. Same form as a number's own username (WhatsAppNumberProfile.username), without a leading @; a message cannot be addressed by it.
to.display_name
string
Present only on a message received from a WhatsApp user, on from; never on an outbound send's to, where the profile is not known. Absent when the message carries no profile, and on a message received before this workspace started recording them.
template
object
The template the message was sent from. For authentication templates the filled-in values are not returned.
Untergeordnete Attribute anzeigen
template.slug
string
erforderlich
The template's stable handle (for example bird_otp).
template.category
string
erforderlich
The category this message was priced at, recorded as it stood when the message was sent. For a template you authored this is the category Meta applies to the language the send resolved to, which can differ from the category declared on the template: Meta categorizes each language separately and may move one. A built-in bird_ template is priced at the single category the built-in declares, the same in every language.
template.language
string
erforderlich
The canonical BCP-47 tag of the template variant that was sent.
template.components
array of object
erforderlich
The values that filled the template's placeholders. Empty for an authentication template, whose content is never returned.
Untergeordnete Attribute anzeigen
template.components.type
string
erforderlich
Which part of the template this fills in.
- body: the main text.
- button: a button's variable.
- header: the header's text, media or location.
- carousel: the cards.
Possible values (may grow over time): header, body, button, carousel
template.components.parameters
array of object
The values that fill this part's placeholders. A positional template takes them in {{n}} placeholder order; a template with named parameters requires each parameter's name to match one the template declares, and order then carries no meaning. Send it on every part except carousel, which carries its values on cards. Send no button part at all for a button that takes no value, such as a quick_reply or request_contact_info button, or a url button whose address has no placeholder: a part the template has no slot for is refused here, before the message is sent and charged.
Untergeordnete Attribute anzeigen
template.components.parameters.type
string
erforderlich
The kind of value this parameter carries, which decides which of the fields below to send.
template.components.parameters.text
string
The value substituted into the placeholder, as a plain string. Send it on a text parameter.
template.components.parameters.url
string
Public https URL of the file a media header shows. Send it on an image, video, gif or document parameter. WhatsApp fetches it at send time, so it must still be reachable then, the same way a free-form media message's url must.
template.components.parameters.location
object
The point on the map a location header opens. Send it on a location parameter.
Untergeordnete Attribute anzeigen
template.components.parameters.location.latitude
number
erforderlich
Latitude in decimal degrees.
template.components.parameters.location.longitude
number
erforderlich
Longitude in decimal degrees.
template.components.parameters.location.name
string
Name of the place, shown above the address.
template.components.parameters.location.address
string
Street address of the place. Shown only when name is also set.
template.components.parameters.name
string
Required when the template declares named parameters: the placeholder this value fills (for example first_name), matching exactly one of the names the template declares. Name every parameter in that case; order does not matter once names are supplied. Omit this field for a positional template, which takes its values in {{n}} order instead. Sending the wrong set of names, or leaving one out that the template requires, returns a 422 WhatsAppTemplateParameterMismatch.
template.components.cards
array of object
The values that fill each card of a carousel. Send it only on a carousel part. A carousel sends exactly the number of cards its template was approved with, so every card needs an entry.
Untergeordnete Attribute anzeigen
template.components.cards.components
array of object
erforderlich
The values that fill this card's blocks.
Untergeordnete Attribute anzeigen
template.components.cards.components.type
string
erforderlich
Which part of the card this fills in.
- header: the card's image or video.
- body: its text.
- button: a button's variable.
Possible values (may grow over time): header, body, button
template.components.cards.components.parameters
array of object
The values that fill this part's placeholders, in placeholder order.
Untergeordnete Attribute anzeigen
template.components.cards.components.parameters.type
string
erforderlich
The kind of value this parameter carries, which decides which of the fields below to send.
template.components.cards.components.parameters.text
string
The value substituted into the placeholder, as a plain string. Send it on a text parameter.
template.components.cards.components.parameters.url
string
Public https URL of the file a media header shows. Send it on an image, video, gif or document parameter. WhatsApp fetches it at send time, so it must still be reachable then, the same way a free-form media message's url must.
template.components.cards.components.parameters.location
object
The point on the map a location header opens. Send it on a location parameter.
Untergeordnete Attribute anzeigen
template.components.cards.components.parameters.location.latitude
number
erforderlich
Latitude in decimal degrees.
template.components.cards.components.parameters.location.longitude
number
erforderlich
Longitude in decimal degrees.
template.components.cards.components.parameters.location.name
string
Name of the place, shown above the address.
template.components.cards.components.parameters.location.address
string
Street address of the place. Shown only when name is also set.
template.components.cards.components.parameters.name
string
Required when the template declares named parameters: the placeholder this value fills (for example first_name), matching exactly one of the names the template declares. Name every parameter in that case; order does not matter once names are supplied. Omit this field for a positional template, which takes its values in {{n}} order instead. Sending the wrong set of names, or leaving one out that the template requires, returns a 422 WhatsAppTemplateParameterMismatch.
text
object
Text the message carried.
Untergeordnete Attribute anzeigen
text.body
string
erforderlich
The message text.
image
object
Image the message carried.
Untergeordnete Attribute anzeigen
image.id
string
ID of the stored file, to pass as media_id when fetching it. Absent on an outbound message, whose file we never stored.
image.url
string
Where to fetch the media. On an inbound message this is a Bird URL you fetch with your API key; it is absent when the file could not be retrieved from WhatsApp. It stays populated after the stored bytes expire, and the link returns 410 from then on. On an outbound message it is the URL the sender supplied, whose availability is the sender's to guarantee.
image.mime_type
string
Media type WhatsApp reported for the file, for example image/jpeg. Absent on outbound messages.
image.caption
string
Text shown beneath the image. Absent when the sender wrote none.
video
object
Video the message carried.
Untergeordnete Attribute anzeigen
video.id
string
ID of the stored file, to pass as media_id when fetching it. Absent on an outbound message, whose file we never stored.
video.url
string
Where to fetch the media. On an inbound message this is a Bird URL you fetch with your API key; it is absent when the file could not be retrieved from WhatsApp. It stays populated after the stored bytes expire, and the link returns 410 from then on. On an outbound message it is the URL the sender supplied, whose availability is the sender's to guarantee.
video.mime_type
string
Media type WhatsApp reported for the file, for example image/jpeg. Absent on outbound messages.
video.caption
string
Text shown beneath the video. Absent when the sender wrote none.
audio
object
Audio the message carried.
Untergeordnete Attribute anzeigen
audio.id
string
ID of the stored file, to pass as media_id when fetching it. Absent on an outbound message, whose file we never stored.
audio.url
string
Where to fetch the media. On an inbound message this is a Bird URL you fetch with your API key; it is absent when the file could not be retrieved from WhatsApp. It stays populated after the stored bytes expire, and the link returns 410 from then on. On an outbound message it is the URL the sender supplied, whose availability is the sender's to guarantee.
audio.mime_type
string
Media type WhatsApp reported for the file, for example image/jpeg. Absent on outbound messages.
audio.voice
boolean
Whether this is a voice note rather than an attached audio file. A voice note auto-downloads in the WhatsApp client and can be transcribed for the recipient.
sticker
object
Sticker the message carried.
Untergeordnete Attribute anzeigen
sticker.id
string
ID of the stored file, to pass as media_id when fetching it. Absent on an outbound message, whose file we never stored.
sticker.url
string
Where to fetch the media. On an inbound message this is a Bird URL you fetch with your API key; it is absent when the file could not be retrieved from WhatsApp. It stays populated after the stored bytes expire, and the link returns 410 from then on. On an outbound message it is the URL the sender supplied, whose availability is the sender's to guarantee.
sticker.mime_type
string
Media type WhatsApp reported for the file, for example image/jpeg. Absent on outbound messages.
sticker.animated
boolean
Whether the sticker is animated. Absent on an outbound message.
document
object
Document the message carried.
Untergeordnete Attribute anzeigen
document.id
string
ID of the stored file, to pass as media_id when fetching it. Absent on an outbound message, whose file we never stored.
document.url
string
Where to fetch the media. On an inbound message this is a Bird URL you fetch with your API key; it is absent when the file could not be retrieved from WhatsApp. It stays populated after the stored bytes expire, and the link returns 410 from then on. On an outbound message it is the URL the sender supplied, whose availability is the sender's to guarantee.
document.mime_type
string
Media type WhatsApp reported for the file, for example image/jpeg. Absent on outbound messages.
document.caption
string
Text shown beneath the document. Absent when the sender wrote none.
document.filename
string
The sender's own name for the file.
location
object
Location the message carried.
Untergeordnete Attribute anzeigen
location.latitude
number
Latitude in decimal degrees.
location.longitude
number
Longitude in decimal degrees.
location.name
string
Name of the place. Absent when the sender shared a plain pin.
location.address
string
Street address of the place. Shown only when name is also set.
location.url
string
Link to the place, which WhatsApp includes mainly for business locations. Present on an inbound message when the sender's client supplied one, and absent on a message you sent, since sending a location does not support this field.
contact_cards
array of object
Contact cards on this message: cards the contact shared, either by tapping a button that asked for their number or by sending one from their address book, or the cards this workspace sent.
Untergeordnete Attribute anzeigen
contact_cards.origin
string
Why the card arrived. contact_request means the contact tapped a button this workspace sent asking for their number, which is the only signal that the message answers that ask; other means they shared a card in the chat. Open enum: treat an unrecognized value as a way of sharing added since. Set on a card the contact shared; absent on one this workspace sent.
Possible values (may grow over time): contact_request, other
contact_cards.vcard
string
The contact's card in vCard format. WhatsApp sends it on a card shared in the chat and omits it on a button tap, which carries the number alone. Set on a card the contact shared; absent on one this workspace sent.
contact_cards.name
object
The contact's name, when the card carries one.
Untergeordnete Attribute anzeigen
contact_cards.name.formatted_name
string
The whole name as the contact's device renders it.
contact_cards.name.first_name
string
contact_cards.name.middle_name
string
contact_cards.name.last_name
string
contact_cards.name.prefix
string
contact_cards.name.suffix
string
contact_cards.org
object
Where the contact works, when the card carries it.
Untergeordnete Attribute anzeigen
contact_cards.org.company
string
contact_cards.org.department
string
contact_cards.org.title
string
contact_cards.birthday
string
The contact's birthday, which WhatsApp sends as YYYY-MM-DD. Passed through as text rather than typed as a date: the value comes off the contact's own device unvalidated, and a card we could not parse would otherwise have to lose the field or fail the whole read.
contact_cards.phone_numbers
array of object
The numbers on the card. A button tap carries the contact's own number here, which is the point of asking.
Untergeordnete Attribute anzeigen
contact_cards.phone_numbers.phone_number
string
The number as the card holds it, normalized to E.164 where we can parse it. A card is whatever the contact's device stored, so a number that no country's numbering plan accepts, an extension among them, is passed through exactly as it arrived rather than dropped. Parse defensively: most values are E.164 and none is guaranteed to be.
contact_cards.phone_numbers.type
string
The label attached to this value, for example CELL, Home or iPhone. Free text: WhatsApp defines no vocabulary. A label on a received card is lowercased; one this workspace sent reads back exactly as sent.
contact_cards.emails
array of object
Untergeordnete Attribute anzeigen
contact_cards.emails.email
string
contact_cards.emails.type
string
The label attached to this value, for example CELL, Home or iPhone. Free text: WhatsApp defines no vocabulary. A label on a received card is lowercased; one this workspace sent reads back exactly as sent.
contact_cards.urls
array of object
Untergeordnete Attribute anzeigen
contact_cards.urls.url
string
The address as the card holds it, which is often bare rather than a full URL, so it is passed through as text rather than validated.
contact_cards.urls.type
string
The label attached to this value, for example CELL, Home or iPhone. Free text: WhatsApp defines no vocabulary. A label on a received card is lowercased; one this workspace sent reads back exactly as sent.
contact_cards.addresses
array of object
Untergeordnete Attribute anzeigen
contact_cards.addresses.street
string
contact_cards.addresses.city
string
contact_cards.addresses.state
string
contact_cards.addresses.zip
string
contact_cards.addresses.country
string
contact_cards.addresses.country_code
string
The country as the card holds it, left exactly as WhatsApp sent it: it describes a postal address rather than a routing destination.
contact_cards.addresses.type
string
The label attached to this value, for example CELL, Home or iPhone. Free text: WhatsApp defines no vocabulary. A label on a received card is lowercased; one this workspace sent reads back exactly as sent.
interactive
object
Interactive content the message carried. Outbound only: a contact cannot send one. A tap on a reply button or a list row reads back as interactive_reply on the contact's inbound message; a cta_url link sends nothing back, and the two request kinds are answered by an inbound location or contact_cards message.
Untergeordnete Attribute anzeigen
interactive.type
string
erforderlich
Which kind of interactive message this is, and which field carries it.
interactive.header
object
What was shown above the body. Absent when the message carried no header.
Untergeordnete Attribute anzeigen
interactive.header.type
string
erforderlich
Which kind of header this is, and which field carries it.
interactive.header.text
string
The line of text shown above the body.
interactive.header.url
string
The URL of the file shown above the body, as the send supplied it. Interactive content is outbound only, so Bird neither stores nor proxies the file.
interactive.body_text
string
erforderlich
The message's main text.
interactive.footer_text
string
The small print below the body. Absent when the message carried none.
interactive.buttons
array of object
The buttons the message offered, in the order shown.
Untergeordnete Attribute anzeigen
interactive.buttons.type
string
erforderlich
Which kind of button this is, and which field carries it.
interactive.buttons.quick_reply
object
The button's label and the handle it sends back.
Untergeordnete Attribute anzeigen
interactive.buttons.quick_reply.slug
string
erforderlich
The handle the button carries back, never shown to the recipient. On a tap on a template's quick-reply button, it is the payload that template declared.
interactive.buttons.quick_reply.text
string
erforderlich
The label the recipient saw.
interactive.buttons.cta_url
object
The button's label and the address it opens.
Untergeordnete Attribute anzeigen
interactive.buttons.cta_url.text
string
erforderlich
The button's label.
interactive.buttons.cta_url.url
string
erforderlich
The address the button opens, as the send supplied it.
interactive.list
object
The menu the message offered.
Untergeordnete Attribute anzeigen
interactive.list.button_text
string
erforderlich
The label of the button that opens the menu.
interactive.list.sections
array of object
erforderlich
The groups of options in the menu, in the order shown.
Untergeordnete Attribute anzeigen
interactive.list.sections.title
string
erforderlich
The group's heading, shown above its rows.
interactive.list.sections.rows
array of object
erforderlich
The options in this group, in the order shown.
Untergeordnete Attribute anzeigen
interactive.list.sections.rows.slug
string
erforderlich
The handle the row carries back, never shown to the recipient.
interactive.list.sections.rows.text
string
erforderlich
The row's label, shown as its title in the menu.
interactive.list.sections.rows.description
string
The second line under the label. Absent when the row carried none.
interactive.cta_url
object
The link button the message offered.
Untergeordnete Attribute anzeigen
interactive.cta_url.text
string
erforderlich
The button's label.
interactive.cta_url.url
string
erforderlich
The address the button opens, as the send supplied it.
interactive.cards
array of object
The cards the message offered, in the order they appeared, left to right.
Untergeordnete Attribute anzeigen
interactive.cards.header
object
erforderlich
The image or video shown at the top of the card.
Untergeordnete Attribute anzeigen
interactive.cards.header.type
string
erforderlich
Which kind of header this is, and which field carries it.
interactive.cards.header.text
string
The line of text shown above the body.
interactive.cards.header.url
string
The URL of the file shown above the body, as the send supplied it. Interactive content is outbound only, so Bird neither stores nor proxies the file.
interactive.cards.body_text
string
The card's own text. Absent when the card carried none.
interactive.cards.buttons
array of object
erforderlich
The buttons the card offered, in the order shown.
Untergeordnete Attribute anzeigen
interactive.cards.buttons.type
string
erforderlich
Which kind of button this is, and which field carries it.
interactive.cards.buttons.quick_reply
object
The button's label and the handle it sends back.
Untergeordnete Attribute anzeigen
interactive.cards.buttons.quick_reply.slug
string
erforderlich
The handle the button carries back, never shown to the recipient. On a tap on a template's quick-reply button, it is the payload that template declared.
interactive.cards.buttons.quick_reply.text
string
erforderlich
The label the recipient saw.
interactive.cards.buttons.cta_url
object
The button's label and the address it opens.
Untergeordnete Attribute anzeigen
interactive.cards.buttons.cta_url.text
string
erforderlich
The button's label.
interactive.cards.buttons.cta_url.url
string
erforderlich
The address the button opens, as the send supplied it.
in_reply_to_message_id
string
The message this one answers. On an inbound message it is what WhatsApp reports as the reply's target: a tap on a button or a list row, and equally a text or media message the contact sent as a quoted reply. An outbound message echoes the in_reply_to_message_id it was sent with. Absent when the message answers nothing, and absent on an inbound message whose target we cannot match to a message we hold, which is the case for one sent before this workspace started recording them or one already past the 15-day window we keep provider ids for.
interactive_reply
object
What the contact tapped, on a message answering an interactive message or a template's quick-reply button. Inbound only.
Untergeordnete Attribute anzeigen
interactive_reply.type
string
erforderlich
Which kind of tap this reply came from, and which field carries it.
interactive_reply.button
object
The button the contact tapped, as you declared it. On a reply to a template's quick-reply button, slug is the button's payload, which WhatsApp sets to the button's own label.
Untergeordnete Attribute anzeigen
interactive_reply.button.slug
string
erforderlich
The handle the button carries back, never shown to the recipient. On a tap on a template's quick-reply button, it is the payload that template declared.
interactive_reply.button.text
string
erforderlich
The label the recipient saw.
interactive_reply.list
object
The row the contact chose, as you declared it. description is present only when the row carried one.
Untergeordnete Attribute anzeigen
interactive_reply.list.slug
string
erforderlich
The handle the row carries back, never shown to the recipient.
interactive_reply.list.text
string
erforderlich
The row's label, shown as its title in the menu.
interactive_reply.list.description
string
The second line under the label. Absent when the row carried none.
unsupported
object
Set when the contact sent content we do not model, naming the WhatsApp content type so the message is not silently empty. Inbound only.
Untergeordnete Attribute anzeigen
unsupported.type
string
erforderlich
The WhatsApp content type we did not model. unsupported is not a placeholder here: WhatsApp reports its own unsupported type for a message its own clients cannot render, and that arrives as this value. Open enum: WhatsApp adds content types over time, so treat an unrecognized value as a future type rather than an error.
Possible values (may grow over time): reaction, interactive, button, order, system, unsupported
reactions
array of object
Emoji reactions standing on this message right now, one per sender. Absent when the message has none. A reaction that was replaced by a different emoji, or taken back, is not listed; the message's reaction log keeps that history. WhatsApp accepts a reaction on a message up to 30 days old, and we keep provider ids for 15, so a reaction placed on a message older than that cannot be matched to it and does not appear here.
Untergeordnete Attribute anzeigen
reactions.emoji
string
erforderlich
The emoji, as WhatsApp sent it. It is not normalized, so two emoji that render identically can differ byte for byte and compare unequal.
reactions.from
object
erforderlich
Who reacted. On a group message this is what tells one participant's reaction from another's. On a one-to-one message it is your business number on a reaction you placed and the contact on one they placed, which is why it is here rather than inferred from the message's direction.
Untergeordnete Attribute anzeigen
reactions.from.phone_number
string
Phone number in E.164 format, when known.
reactions.from.bsuid
string
Business-scoped user ID, Meta's identifier for the WhatsApp user. Present only on the WhatsApp-user side of the message.
reactions.from.group_id
string
The group this address was addressed as, or reached through. It appears on a message's to and nowhere else: never on from, and never on an event's recipient. Outbound, it stands in for the recipient, because a group send names no single phone number. Inbound, it qualifies one: to carries the business phone_number that received the message and the group it arrived through, while from stays the participant who wrote it. Its presence on to is what tells a group message from a one-to-one one, in either direction.
reactions.from.username
string
Present only on a message received from a WhatsApp user, on from; never on an outbound send's to, where the profile is not known. Absent when the contact has not adopted one, and on a message received before this workspace started recording them. Same form as a number's own username (WhatsAppNumberProfile.username), without a leading @; a message cannot be addressed by it.
reactions.from.display_name
string
Present only on a message received from a WhatsApp user, on from; never on an outbound send's to, where the profile is not known. Absent when the message carries no profile, and on a message received before this workspace started recording them.
status
string
erforderlich
recipient_count
integer
How many recipients a group send was addressed to, taken when the send
was accepted. It is the group's membership at that moment, not its
membership now: someone joining through the invite link while the message
is in flight does not receive it and does not change this count.
Absent on a one-to-one message, along with delivered_count and
read_count. A message with one recipient has no fan-out to report, and
its delivery is what status, delivered_at and read_at already say.
Absent for the same reason on a group message sent before Bird recorded
the count, and on a send to a group nobody had joined yet: there is no
denominator to report, and none can be recovered after the fact, since
membership has moved on. to.group_id is what tells a group message from
a one-to-one one in every case, including those two. With no denominator
to resolve against, status is read as stored, the way a one-to-one
message's is: it reaches sent when the message is handed to WhatsApp and
stops there, because delivery is confirmed per participant and a send with
no participants collects no confirmations.
It is also the denominator status is resolved against: on a group
message status reports the furthest point every recipient has
reached, so it turns delivered only once delivered_count equals this
number, and stays sent while some have confirmed and others have not.
failed and rejected are never per recipient: there is one hand-off to
the WhatsApp network and one way for that to be refused. delivered_at
and read_at are the first recipient's, not the last.
delivered_count
integer
How many of the recipient_count recipients WhatsApp has confirmed the
message reached. A recipient who reported only a read counts here too:
WhatsApp skips the delivery receipt when someone is already looking at
the chat, so waiting for one would leave that person uncounted for ever.
Absent on a one-to-one message, which has no fan-out to count, and on a
group message with no recipient_count to count against.
read_count
integer
How many of the recipient_count recipients have opened the message.
Read receipts do not move status, which has no read value; they
surface here and in read_at.
Absent on a one-to-one message, which has no fan-out to count, and on a
group message with no recipient_count to count against.
last_error
nullable object
Failure detail for a message that did not reach the recipient. Present only when the message failed or was rejected.
Untergeordnete Attribute anzeigen
last_error.code
string
erforderlich
Standardized failure reason:
- insufficient_balance: The workspace wallet could not fund the send.
- price_not_found: No price was configured for the destination and template.
- internal_error: An unexpected service failure occurred.
- undeliverable: The recipient could not be reached.
- service_window_expired: The 24-hour service window closed; send a template.
- rate_limited: The send was throttled.
- recipient_suppressed: The recipient is on the workspace suppression list.
- media_rejected: WhatsApp could not fetch the media URL, or refused the file it found there; description carries its reason.
This is an open enum. Accept unrecognized values.
Possible values (may grow over time): insufficient_balance, price_not_found, internal_error, undeliverable, service_window_expired, rate_limited, recipient_suppressed, media_rejected
last_error.description
string
erforderlich
Human-readable explanation of the failure.
last_error.meta_error_code
nullable string
Raw error code from the WhatsApp Cloud API, when available, for low-level debugging.
last_error.occurred_at
string
erforderlich
When the failure occurred.
created_at
string
erforderlich
When the message was accepted for delivery.
sent_at
nullable string
When the message was handed to the WhatsApp network. Null until then.
delivered_at
nullable string
When delivery was confirmed. Null until then.
read_at
nullable string
When the message was read. On an outbound message this is the recipient opening it. On an inbound one it is when Bird acknowledged the message to WhatsApp for the business, which a read receipt sets. Null until then.
cost
nullable object
What the message cost, split into Bird's charge and any third-party fees passed through. Null on an inbound message, which is never priced, on an outbound message that has not been priced yet, and on one rejected before pricing. The rate depends on the message category and the recipient's country.
Untergeordnete Attribute anzeigen
cost.amount
string
erforderlich
Total charged, as a decimal string: the sum of the components below. Net of tax, which applies to your wallet balance rather than to an individual charge.
cost.currency_code
string
erforderlich
ISO 4217 currency code. Every component is denominated in this currency.
cost.transaction_amount
nullable string
erforderlich
What we charged to carry the message, as a decimal string. null when this component was not priced; "0.00000" when it priced at zero.
cost.passthrough_amount
nullable string
erforderlich
Third-party fees we pass on, as a decimal string, such as US 10DLC carrier surcharges. null when this component was not priced; "0.00000" when it priced at zero.
tags
array of object
Structured {name, value} filter labels applied to this message.
Untergeordnete Attribute anzeigen
tags.name
string
erforderlich
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
tags.value
string
erforderlich
Tag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters.
metadata
object
Arbitrary JSON metadata stored on the message.
Verwandte Ressourcen
Weiter mit der Dokumentation, Anleitungen und Beispielen zu diesem Thema. Die Ressourcen sind auf Englisch.
Anleitung ansehenConnecting WhatsApp to Bird: from buying a number to a live channelDas Konzept verstehenWhat is the 24-hour customer service window on WhatsApp?Das Tool verwendenWhatsApp message builderDie Funktion erkundenWhatsApp
Übung ausprobieren und ein Implementierungs-Briefing erhalten