Skip to main content
The Media API lets you upload files to Meta’s servers (getting a reusable media_id), retrieve the download URL of a media file (for inbound messages), and delete media you no longer need. See Media by URL vs Media ID for when to use media ID vs URL in outbound messages.

1. Upload media (get a media_id)

POST https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/media
Authorization: Bearer YOUR_TOKEN
Content-Type: multipart/form-data

messaging_product = whatsapp
file              = [file bytes]
type              = image/jpeg
Response:
{ "id": "1234567890" }
Use this id in the image.id, document.id, video.id, etc. field of any message. Media IDs expire after 30 days.

2. Retrieve media URL (to download received media)

When a webhook delivers an inbound media message, the payload contains a media_id. Use this to get the download URL:
GET https://graph.facebook.com/v21.0/{MEDIA_ID}
Authorization: Bearer YOUR_TOKEN
Response:
{
  "url": "https://lookaside.fbsbx.com/...",
  "mime_type": "image/jpeg",
  "sha256": "abc123...",
  "file_size": 12345,
  "id": "1234567890",
  "messaging_product": "whatsapp"
}
Then download the file from the returned URL with your token in the header.

3. Delete media

DELETE https://graph.facebook.com/v21.0/{MEDIA_ID}
Authorization: Bearer YOUR_TOKEN
Response:
{ "deleted": true }

Frequently asked

Send a multipart/form-data POST to /{phone-number-id}/media with messaging_product=whatsapp, the file bytes, and the MIME type. Meta returns a media_id to use in your message.
The inbound webhook gives you a media_id. Call GET /{media_id} to get a temporary download URL, then download the file using that URL with your Authorization header.
30 days. After that the ID stops working and you must re-upload the file to get a new ID.
Call DELETE /{media_id} with your Authorization header. Returns {"deleted": true} on success.

Gotchas & common mistakes

  • Media ID expires in 30 days — store the upload date and re-upload before expiry if you reuse the same file frequently.
  • Download URL is temporary — the URL returned by GET /{media_id} expires quickly. Download the file immediately; don’t store the URL.
  • Must include Authorization when downloading — the download URL itself is not public. Always pass Authorization: Bearer YOUR_TOKEN when fetching it.
  • Wrong MIME type on upload — the type field must match the actual file format.