Get a WhatsApp message
GET
/v1/whatsapp/messages/{message_id}
const msg = await bird.whatsapp.get("wa_abc123");
msg.status; // "accepted" | "delivered" | …msg = client.whatsapp.get("wa_abc123")
print(msg.id, msg.status)package main
import (
"context"
"fmt"
"log"
"os"
bird "github.com/messagebird/bird-sdk-go"
"github.com/messagebird/bird-sdk-go/option"
)
func main() {
client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
if err != nil {
log.Fatal(err)
}
msg, err := client.Whatsapp.Get(context.Background(), "wam_01krdgeqcxet5s7t44vh8rt9mg")
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)
}$message = $bird->whatsapp->get('wamid_01krdgeqcxet5s7t44vh8rt9mg');
echo $message->getStatus();bird whatsapp get <message-id>curl -X GET "https://us1.platform.bird.com/v1/whatsapp/messages/{message_id}" \
-H "Authorization: Bearer $TOKEN"Response200
{
"id": "wam_01krdgeqcxet5s7t44vh8rt9mg",
"direction": "outbound",
"from": {
"phone_number": "+15550001111",
"bsuid": "NL.xxxx"
},
"to": {
"phone_number": "+15550001111",
"bsuid": "NL.xxxx"
},
"template": {
"slug": "bird_otp",
"category": "authentication",
"language": "pt-BR",
"components": [
{
"type": "header",
"parameters": [
{
"type": "text",
"url": "https://cdn.example.com/receipts/a1b2c3.png",
"location": {
"latitude": 52.3702,
"longitude": 4.8952,
"name": "Bird HQ",
"address": "Keizersgracht 117, Amsterdam"
}
}
],
"cards": [
{
"components": [
{
"type": "header"
}
]
}
]
}
]
},
"text": {
"body": "Does it come in another color?"
},
"image": {
"id": "waf_01krdgeqcxet5s7t44vh8rt9mg",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya19eknftrs2s6p82asmvnh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
"mime_type": "image/jpeg",
"caption": "Your receipt for order A1B2C3"
},
"video": {
"id": "waf_01krdgeqcxet5s7t44vh8rt9mg",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya19eknftrs2s6p82asmvnh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
"mime_type": "image/jpeg",
"caption": "How to set it up"
},
"audio": {
"id": "waf_01krdgeqcxet5s7t44vh8rt9mg",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya19eknftrs2s6p82asmvnh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
"mime_type": "image/jpeg",
"voice": true
},
"sticker": {
"id": "waf_01krdgeqcxet5s7t44vh8rt9mg",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya19eknftrs2s6p82asmvnh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
"mime_type": "image/jpeg",
"animated": false
},
"document": {
"id": "waf_01krdgeqcxet5s7t44vh8rt9mg",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kya19eknftrs2s6p82asmvnh/media/waf_01kyb2m4xq7whs0d8n3prv6tez",
"mime_type": "image/jpeg",
"caption": "Signed contract",
"filename": "contract-a1b2c3.pdf"
},
"location": {
"latitude": 52.3702,
"longitude": 4.8952,
"name": "Bird HQ",
"address": "Keizersgracht 117, Amsterdam",
"url": "https://www.google.com/maps/place/Statue+of+Liberty/@40.6246301,-74.5291919,124716m/"
},
"contact_cards": [
{
"origin": "contact_request",
"phone_numbers": [
{
"phone_number": "+16505551234",
"type": "CELL"
}
]
}
],
"interactive": {
"type": "button",
"header": {
"type": "image",
"text": "New workshop dates announced",
"url": "https://cdn.example.com/banners/workshop.png"
},
"body_text": "Your workshop is scheduled for 9am tomorrow.",
"footer_text": "Lucky Shrub, your gateway to succulents",
"buttons": [
{
"type": "quick_reply",
"quick_reply": {
"slug": "change-booking",
"text": "Change"
},
"cta_url": {
"text": "See dates",
"url": "https://example.com/workshops?click_id=a1b2c3"
}
}
],
"list": {
"button_text": "Shipping options",
"sections": [
{
"title": "As soon as possible",
"rows": [
{
"slug": "priority_express",
"text": "Priority Mail Express",
"description": "Next day to 2 days"
}
]
}
]
},
"cta_url": {
"text": "See dates",
"url": "https://example.com/workshops?click_id=a1b2c3"
},
"cards": [
{
"header": {
"type": "image",
"text": "New workshop dates announced",
"url": "https://cdn.example.com/banners/workshop.png"
},
"body_text": "*Blue Echeveria*",
"buttons": [
{
"type": "quick_reply",
"quick_reply": {
"slug": "change-booking",
"text": "Change"
},
"cta_url": {
"text": "See dates",
"url": "https://example.com/workshops?click_id=a1b2c3"
}
}
]
}
]
},
"in_reply_to_message_id": "wam_01krdgeqcxet5s7t44vh8rt9mg",
"interactive_reply": {
"type": "list",
"list": {
"slug": "priority_express",
"text": "Priority Mail Express",
"description": "Next day to 2 days"
}
},
"unsupported": {
"type": "reaction"
},
"status": "scheduled",
"last_error": {
"code": "insufficient_balance",
"description": "Message could not be delivered.",
"meta_error_code": "131026"
},
"cost": {
"amount": "0.00990",
"currency_code": "USD",
"transaction_amount": "0.00790",
"passthrough_amount": "0.00200"
},
"tags": [
{
"name": "category",
"value": "welcome"
}
]
}
Returns a single WhatsApp message: its current delivery status, per-stage timestamps (sent_at, delivered_at, read_at), and failure detail when it failed. It carries the one content object it was built from: template, or free-form text, image, video, audio, sticker, document, location, interactive or contact_cards. An inbound message carries interactive_reply when the contact tapped a reply button or a list row. An inbound message whose content WhatsApp models and we do not carries unsupported instead, naming the type rather than reading back empty. The status advances asynchronously as delivery progresses, so poll this endpoint (or subscribe to whatsapp.* webhook events) after a send to confirm delivery. For the per-event timeline, use List events for a WhatsApp message instead.
Parameters
message_id
string
ID of the message, as returned in the send response's id field.
Response Payload
id
string
required
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
required
Whether the message was sent by the business (outbound) or received from the contact (inbound).
Possible values: outbound, inbound
from
object
required
Sender of the message. On outbound messages, the business number it was sent from; on inbound, the WhatsApp contact.
Show child attributes
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.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
required
Recipient of the message. On outbound messages, the WhatsApp contact; on inbound, the business number.
Show child attributes
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.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.
Show child attributes
template.slug
string
required
The template's stable handle (for example bird_otp).
template.category
string
required
Content classification applied to messages sent from this template.
template.language
string
required
The canonical BCP-47 tag of the template variant that was sent.
template.components
array of object
required
The values that filled the template's placeholders. Empty for an authentication template, whose content is never returned.
Show child attributes
template.components.type
string
required
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.
Show child attributes
template.components.parameters.type
string
required
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.
Show child attributes
template.components.parameters.location.latitude
number
required
Latitude in decimal degrees.
template.components.parameters.location.longitude
number
required
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.
Show child attributes
template.components.cards.components
array of object
required
The values that fill this card's blocks.
Show child attributes
template.components.cards.components.type
string
required
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.
Show child attributes
template.components.cards.components.parameters.type
string
required
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.
Show child attributes
template.components.cards.components.parameters.location.latitude
number
required
Latitude in decimal degrees.
template.components.cards.components.parameters.location.longitude
number
required
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.
Show child attributes
text.body
string
required
The message text.
image
object
Image the message carried.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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.
Show child attributes
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
Show child attributes
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
Show child attributes
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
Show child attributes
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.
Show child attributes
interactive.type
string
required
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.
Show child attributes
interactive.header.type
string
required
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
required
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.
Show child attributes
interactive.buttons.type
string
required
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.
Show child attributes
interactive.buttons.quick_reply.slug
string
required
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
required
The label the recipient saw.
interactive.buttons.cta_url
object
The button's label and the address it opens.
Show child attributes
interactive.buttons.cta_url.text
string
required
The button's label.
interactive.buttons.cta_url.url
string
required
The address the button opens, as the send supplied it.
interactive.list
object
The menu the message offered.
Show child attributes
interactive.list.button_text
string
required
The label of the button that opens the menu.
interactive.list.sections
array of object
required
The groups of options in the menu, in the order shown.
Show child attributes
interactive.list.sections.title
string
required
The group's heading, shown above its rows.
interactive.list.sections.rows
array of object
required
The options in this group, in the order shown.
Show child attributes
interactive.list.sections.rows.slug
string
required
The handle the row carries back, never shown to the recipient.
interactive.list.sections.rows.text
string
required
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.
Show child attributes
interactive.cta_url.text
string
required
The button's label.
interactive.cta_url.url
string
required
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.
Show child attributes
interactive.cards.header
object
required
The image or video shown at the top of the card.
Show child attributes
interactive.cards.header.type
string
required
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
required
The buttons the card offered, in the order shown.
Show child attributes
interactive.cards.buttons.type
string
required
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.
Show child attributes
interactive.cards.buttons.quick_reply.slug
string
required
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
required
The label the recipient saw.
interactive.cards.buttons.cta_url
object
The button's label and the address it opens.
Show child attributes
interactive.cards.buttons.cta_url.text
string
required
The button's label.
interactive.cards.buttons.cta_url.url
string
required
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.
Show child attributes
interactive_reply.type
string
required
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.
Show child attributes
interactive_reply.button.slug
string
required
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
required
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.
Show child attributes
interactive_reply.list.slug
string
required
The handle the row carries back, never shown to the recipient.
interactive_reply.list.text
string
required
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.
Show child attributes
unsupported.type
string
required
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
status
string
required
last_error
nullable object
Failure detail for a message that did not reach the recipient. Present only when the message failed or was rejected.
Show child attributes
last_error.code
string
required
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
required
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
required
When the failure occurred.
created_at
string
required
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 by the recipient. 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.
Show child attributes
cost.amount
string
required
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
required
ISO 4217 currency code. Every component is denominated in this currency.
cost.transaction_amount
nullable string
required
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
required
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.
Show child attributes
tags.name
string
required
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
tags.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.
Related resources
Continue with the documentation, guides and examples for this topic. Resources are in English.
Watch the guideConnecting WhatsApp to Bird: from buying a number to a live channelUnderstand the conceptWhat is the 24-hour customer service window on WhatsApp?Use the toolWhatsApp message builderExplore the capabilityWhatsApp
Try the practice and get an implementation brief