Overview
Media messages let you send non-text content through the same Cloud API message endpoint:
POST https://graph.facebook.com/<GRAPH_VERSION>/<PHONE_NUMBER_ID>/messages
Supported outbound types: image, video, audio, document, sticker.
In Dualhook architecture, sending is performed by your backend directly to Meta Graph API. Inbound media webhooks are delivered directly to your endpoint via Webhook Override. Dualhook does not proxy or store media binaries.
Supported Formats and Size Limits
| Type | Typical supported formats | Max size |
|---|---|---|
| Image | jpeg, png | 5 MB |
| Audio | aac, amr, mp3, m4a, ogg (Opus) | 16 MB |
| Video | mp4, 3gp | 16 MB |
| Document | pdf, doc, docx, ppt, pptx, xls, xlsx, txt | 100 MB |
| Sticker | webp | Static 100 KB, animated 500 KB |
document,image, andvideocan include captions.audioandstickerdo not use captions.- Validate MIME type and file extension consistency before upload/send.
Send Media by Media ID
Recommended flow: upload media first to get a media_id, then send using id.
{
"messaging_product": "whatsapp",
"to": "<RECIPIENT_PHONE_NUMBER>",
"type": "image",
"image": {
"id": "<MEDIA_ID>",
"caption": "<OPTIONAL_CAPTION>"
}
}
For document sends, include filename:
{
"messaging_product": "whatsapp",
"to": "<RECIPIENT_PHONE_NUMBER>",
"type": "document",
"document": {
"id": "<MEDIA_ID>",
"filename": "<DOCUMENT_FILENAME>",
"caption": "<OPTIONAL_CAPTION>"
}
}
For upload instructions, see Upload, Retrieve & Delete Media.
Send Media by Public URL
{
"messaging_product": "whatsapp",
"to": "<RECIPIENT_PHONE_NUMBER>",
"type": "image",
"image": {
"link": "https://<PUBLIC_MEDIA_HOST>/<MEDIA_PATH>",
"caption": "<OPTIONAL_CAPTION>"
}
}
URL requirements:
- URL must be publicly reachable over HTTPS.
- The endpoint must return the binary file directly.
Content-Typeshould match the real file type.
Inbound Media Webhooks
Inbound media from users includes a media object with an ID. Your backend should use that media ID to retrieve the binary from Meta.
{
"messages": [
{
"from": "<WHATSAPP_USER_PHONE_NUMBER>",
"id": "<WHATSAPP_MESSAGE_ID>",
"timestamp": "<TIMESTAMP>",
"type": "image",
"image": {
"id": "<MEDIA_ID>",
"mime_type": "image/jpeg",
"sha256": "<MEDIA_SHA256>",
"caption": "<OPTIONAL_CAPTION>"
}
}
]
}
Error Handling
- Message API acceptance does not guarantee recipient delivery.
- Final outcomes arrive via status webhooks.
- Prefer
media_idsends for higher reliability. - Keep retry logic with exponential backoff for
429and5xx. - Avoid tight retry loops for repeated
4xxvalidation failures.