Media Messages

Sending and receiving images, video, audio, documents, and stickers via Cloud API.

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

TypeTypical supported formatsMax size
Imagejpeg, png5 MB
Audioaac, amr, mp3, m4a, ogg (Opus)16 MB
Videomp4, 3gp16 MB
Documentpdf, doc, docx, ppt, pptx, xls, xlsx, txt100 MB
StickerwebpStatic 100 KB, animated 500 KB
  • document, image, and video can include captions.
  • audio and sticker do 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-Type should 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_id sends for higher reliability.
  • Keep retry logic with exponential backoff for 429 and 5xx.
  • Avoid tight retry loops for repeated 4xx validation failures.

Related

Browse more docsGet started with Dualhook