WhatsApp API & Developers

Send Media with the WhatsApp API: Images, PDFs, Video

Text gets a reply. A photo of the actual product, the invoice as a PDF, or a 20-second video of how to fix the thing gets the problem solved. That's why most WhatsApp integrations need media within a week of launch, and why "the image didn't arrive" and "the video won't play on Android" are such common tickets.

To send media with the WhatsApp API, you need to know three things: which file types and sizes Meta accepts, whether to upload the file or hand Meta a link, and the encoding rules that decide whether a voice note or video plays properly on the customer's phone.

This guide covers all three for Meta's Cloud API, with limits taken from Meta's media documentation as of October 2026, then how media works on Tenashi's API. For everything else about the platform, see our complete guide to the WhatsApp API.

Supported types and size limits

Meta's media page lists these supported formats as of October 2026:

MediaFormats (MIME type)Max sizeNotes
ImageJPEG (image/jpeg), PNG (image/png)5 MBMust be 8-bit RGB or RGBA
VideoMP4 (video/mp4), 3GPP (video/3gpp)16 MBH.264 video, AAC audio, one audio stream or none
AudioAAC, AMR, MP3 (audio/mpeg), M4A (audio/mp4), OGG (audio/ogg, Opus only)16 MBOGG must be Opus and mono
DocumentPDF, TXT, DOC, DOCX, XLS, XLSX, PPT, PPTX100 MBOther types may send but aren't supported
StickerWebP (image/webp)100 KB static, 500 KB animatedWebP is only for sticker messages

Captions on images, videos and documents can be up to 1,024 characters. Meta's audio and sticker message formats have no caption field.

Two consequences people miss. WebP and GIF aren't on the image list, so convert them to JPEG or PNG before sending as an image. And HEIC photos from iPhones aren't supported either, so convert anything a user uploads to your system before forwarding it on WhatsApp.

Every media message takes either an id (a file you uploaded to Meta) or a link (a public URL Meta fetches). Meta's message references mark link as "not recommended" and suggest uploaded media for better performance.

Upload, then send by idSend by link
HowPOST /PHONE_NUMBER_ID/media, get an IDPut a public HTTPS URL in the message
ReuseThe ID works for 30 days, for anyone you message from that numberMeta caches the fetched file for 10 minutes per URL
Speed at volumeBest; Meta recommends it for high throughputDepends on your server
PrivacyFile never needs a public URLURL must be reachable by Meta, so effectively public
Updating a fileUpload again for a new IDCached copy is reused for 10 minutes; add a query string to force a fresh fetch

The caching detail bites people who regenerate a file at the same URL, such as invoice.pdf rebuilt with a correction. If you send the same link again within 10 minutes, Meta reuses the old cached file. Meta's documented fix is to append a random query string, for example invoice.pdf?v=2.

For a single customer-specific file, either works. For anything sent to many people, such as a product brochure for a campaign, upload once and reuse the ID.

Upload a file and send it

Upload with a multipart request. The type comes from the MIME type you attach to the file field:

curl "https://graph.facebook.com/v23.0/PHONE_NUMBER_ID/media" \
  -H "Authorization: Bearer $WHATSAPP_TOKEN" \
  -F "messaging_product=whatsapp" \
  -F "file=@./INV-1042.pdf;type=application/pdf"

The response is just an ID:

{ "id": "1037543291543636" }

Send it as a document. filename is what the customer sees and decides the file icon, so include the extension:

curl "https://graph.facebook.com/v23.0/PHONE_NUMBER_ID/messages" \
  -H "Authorization: Bearer $WHATSAPP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "recipient_type": "individual",
    "to": "+919811122233",
    "type": "document",
    "document": {
      "id": "1037543291543636",
      "filename": "INV-1042.pdf",
      "caption": "Your invoice for October. Reply here with any questions."
    }
  }'

An image by link looks the same with a different type:

{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "+919811122233",
  "type": "image",
  "image": {
    "link": "https://example.com/products/blue-kettle.jpg",
    "caption": "The blue one, back in stock today."
  }
}

These free-form media messages need an open 24-hour customer service window. Outside it, media has to travel inside an approved template with a media header; our guide to sending messages by API covers the template side. Examples use Graph API v23.0; use the current version from Meta's changelog.

Uploaded files can be deleted early with DELETE /MEDIA_ID, which is worth doing for sensitive documents once they're delivered.

Voice notes versus audio files

The same audio message type produces two different experiences, and the difference is one flag and one codec:

  • A voice note shows your business profile picture, a microphone icon, and can be transcribed on the user's phone. Send an OGG file encoded with Opus and set "voice": true. Meta notes the play icon only appears if the file is 512 KB or smaller; larger files show a download arrow instead.
  • A basic audio message shows a music icon and a download button. Any supported audio format works, with voice left out or false.

Converting a recording into a voice note that meets Meta's rules (Opus, mono):

ffmpeg -i recording.m4a -vn -c:a libopus -ac 1 -b:a 24k voice.ogg

At 24 kbps, a minute of speech comes in well under the 512 KB play-icon threshold. Since March 17, 2026, Meta also sends a played status webhook the first time a user plays a voice message.

Video that plays on every phone

Meta requires H.264 video and AAC audio, and adds a warning: Android WhatsApp clients don't support H.264 "High" profile videos with B-frames. Many phones and editing apps export exactly that, so a video can play fine on iPhone and fail on Android. Meta recommends Main profile without B-frames, or Baseline, with the moov atom placed before the media data.

This ffmpeg command applies all of that, keeps at most one audio stream, and works whether or not the source has sound:

ffmpeg -i input.mov -map 0:v:0 -map "0:a:0?" \
  -c:v libx264 -profile:v main -bf 0 -pix_fmt yuv420p \
  -c:a aac -movflags +faststart output.mp4

We checked the output with ffprobe: H.264 Main profile, zero B-frames, AAC audio. Keep the result under 16 MB, which in practice means short clips or a lower resolution; add -vf scale=-2:720 to cap the height at 720 pixels.

Media errors you'll meet

  • 131053: media upload failed. Most often a MIME type that doesn't match the file, such as a PNG named .jpg or uploaded with type=image/jpeg. Meta suggests checking with file -I yourfile and making the extension match.
  • Expired or invalid media ID. Upload IDs last 30 days. A send with an expired ID fails with an error instead of a message ID, so re-upload rather than caching IDs forever.
  • 131051: unsupported message type. The type you sent isn't one Cloud API supports for this message; check it against Meta's list of message types.
  • 131052 on inbound media. Customers can send files up to 100 MB; bigger ones arrive as this error. Downloading what customers send is covered in receiving WhatsApp messages by API.

The full list, with fixes, is in our WhatsApp API error codes reference.

Sending media through Tenashi

Tenashi's API attaches media to the same POST /api/v1/messages call as text. Pass media as a URL Tenashi downloads, or as base64 with a mimetype, add filename for documents, and the text becomes the caption:

curl https://usetenashi.com/api/v1/messages \
  -H "Authorization: Bearer $TENASHI_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: invoice-INV-1042" \
  -d '{
    "to": "+919811122233",
    "text": "Your invoice for October",
    "media": { "url": "https://example.com/invoices/INV-1042.pdf", "filename": "INV-1042.pdf" }
  }'

Tenashi's limits are its own and differ from Meta's: images up to 5 MB, video up to 16 MB, and PDFs and Office files up to 25 MB. A file over the limit returns media_too_large. Because it's not the Cloud API, there's no template or 24-hour window, and you can send the same file into a WhatsApp group by using conversationId instead of to.

Where Tenashi fits

If the files you send are invoices, quotes, photos and voice replies inside ongoing customer conversations, Tenashi sends them from the number your team already uses, linked by QR scan, and every file lands in the shared inbox thread where a teammate can follow up. No template approvals, no per-message fees; plans start from $18/mo with the API included.

The limit to know: sends are paced, one message every 4 to 12 seconds per number, so Tenashi isn't the tool for mailing a brochure to thousands of people at once.

Read the API docs · Get started

FAQ

What is the maximum file size for media on the WhatsApp Cloud API?

As of October 2026, Meta allows images up to 5 MB, video and audio up to 16 MB, documents up to 100 MB, and stickers up to 100 KB static or 500 KB animated. Images must be JPEG or PNG, and videos MP4 or 3GPP with H.264 video and AAC audio.

Meta recommends uploading and sending by ID for better performance. An uploaded ID can be reused for 30 days for anyone you message from that number, and the file never needs a public URL. Links work too, but Meta caches each URL's file for 10 minutes, so add a query string when a file changes.

Why won't my WhatsApp video play on Android?

Android WhatsApp clients don't support H.264 High profile video with B-frames, which many phones and editors export by default. Re-encode to H.264 Main or Baseline profile without B-frames, with AAC audio, a single audio stream and the moov atom first, using ffmpeg's faststart flag.

How do I send a voice note with the WhatsApp API?

Send an audio message with the voice flag set to true, using an OGG file encoded with the Opus codec in mono. The voice note shows your profile picture and can be transcribed on the user's phone. Keep it at 512 KB or smaller, or WhatsApp shows a download icon instead of play.

Can I add a caption to a WhatsApp document message?

Yes. Image, video and document messages accept a caption of up to 1,024 characters on the Cloud API. Documents also accept a filename, which the customer sees and which sets the file icon, so include the extension. Audio and sticker messages have no caption field.


Getting media right is mostly about formats and a couple of encoding flags. To attach invoices and photos to the chats your team is already in, read how media works in Tenashi's API.