Receiving WhatsApp video
A clip a contact records or attaches arrives as an inbound message carrying video: the same media reference every inbound media arm uses, plus any caption they typed under it.
What an inbound video carries
Ejemplo de código
{
"id": "wam_01kyc5r9pewu7s3j6m0xyd5qgb",
"direction": "inbound",
"from": { "phone_number": "+14155550100" },
"to": { "phone_number": "+13124495569" },
"status": "received",
"video": {
"id": "waf_01kyc4n5yr8xit1e9o4qsw7ufa",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kyc5r9pewu7s3j6m0xyd5qgb/media/waf_01kyc4n5yr8xit1e9o4qsw7ufa",
"mime_type": "video/mp4",
"caption": "The rattle starts around 0:12"
},
"created_at": "2026-08-25T09:11:48Z"
}| Field | What it carries |
|---|---|
| id | The stored file, to pass as media_id when fetching the bytes |
| url | A Bird URL, fetched with your API key |
| mime_type | The media type WhatsApp reported for the clip, such as video/mp4 |
| caption | The text the contact typed under the video; absent when they sent none |
The arm carries no duration, no dimensions, and no thumbnail. Read those from the file itself once you have the bytes, or from your own media pipeline.
id and mime_type appear only on an inbound video, since Bird learns both by fetching the file. An outbound video reads back with the url you supplied and no id.
Fetching the bytes
Pass the message ID and the media id to the channel's media method. The hub's fetching inbound media carries that call in every language, along with the redirect and header rules it follows.
A video is the largest thing a contact is likely to send you, and the fetch serves the bytes straight from storage rather than through the API, so stream the response to disk or to your own bucket rather than buffering it. The message and its media expire together, 30 days after the message arrives; the hub's fetching inbound media owns that window and what the reads return once it passes.
The webhook payload
whatsapp.received carries the video arm on the event envelope:
Ejemplo de código
{
"type": "whatsapp.received",
"timestamp": "2026-08-25T09:11:48.204Z",
"data": {
"whatsapp_id": "wam_01kyc5r9pewu7s3j6m0xyd5qgb",
"workspace_id": "ws_01ky7m235keycbnwyajabe1a6b",
"direction": "inbound",
"from": { "phone_number": "+14155550100" },
"to": { "phone_number": "+13124495569" },
"video": {
"id": "waf_01kyc4n5yr8xit1e9o4qsw7ufa",
"url": "https://platform.bird.com/v1/whatsapp/messages/wam_01kyc5r9pewu7s3j6m0xyd5qgb/media/waf_01kyc4n5yr8xit1e9o4qsw7ufa",
"mime_type": "video/mp4",
"caption": "The rattle starts around 0:12"
},
"tags": null,
"metadata": null
}
}Fetch the clip from a queued worker rather than inside the webhook handler: the endpoint has to answer quickly, and the media stays available for the whole retention window.
Things to watch
- A video note reads as a video. WhatsApp's round video note arrives on this arm with no flag distinguishing it, unlike audio, where a voice note sets voice.
- One clip per message. Several videos arrive as several inbound messages, each with its own media reference.
Next steps
- How receiving works: the inbound envelope, media fetching, and the whatsapp.received webhook
- WhatsApp video messages: the send side of the same arm
- Receiving audio: voice notes and attached audio files
- WhatsApp events: the full event list, over the API or webhooks