Skip to content

Upload and download WhatsApp media

Upload bytes to Meta with POST /v2/media/upload (max 100 MB) to get a mediaId, then send it in messages or templates. Download with GET /v2/media/:mediaId/download.

Base: /v2/media

Auth + Premium/Enterprise + active plan required. See HTTP API v2 Overview.

The upload path is POST /v2/media/upload, not POST /v2/media.

Prerequisites

  • An API token and Premium/Enterprise plan (Authentication)
  • A phoneNumberId from GET /v2/me (required on upload)
  • A file within WhatsApp’s 100 MB ceiling

Step-by-step

  1. Authenticate
    Send Authorization: Bearer YOUR_TOKEN or X-API-Token: YOUR_TOKEN.

  2. Upload with POST /v2/media/upload
    Multipart: form fields file and phoneNumberId. Raw body: file bytes plus X-Phone-Number-Id (or phoneNumberId header). Max 100 MB. Success returns { "success": true, "data": { "mediaId": "..." } }.

  3. Use mediaId on send
    Pass the id in message media or a template header (image / video / document).

  4. Download when you have a Meta media ID
    GET /v2/media/:mediaId/download returns a binary stream on success. Optional phoneNumberId or accountId selects the WABA token. Missing URL returns JSON 404 NOT_FOUND. Graph/upload failures return VALIDATION_ERROR with Meta’s payload in details when available.


POST /v2/media/upload

Uploads bytes to Meta POST /{phone-number-id}/media and returns a mediaId for use with send media and templates.

Limits: maximum 100 MB per request (WhatsApp ceiling).

Phone number: phoneNumberId must belong to your account (same rules as message sends).

Mode A — multipart/form-data

FieldRequiredDescription
fileyesFile part
phoneNumberIdyesMeta phone number ID
typenoMIME hint if the part has a generic type

Example (curl):

bash
curl -sS -X POST "https://api.avenping.com/v2/media/upload" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "phoneNumberId=YOUR_META_PHONE_NUMBER_ID" \
  -F "file=@/path/to/photo.jpg;type=image/jpeg"

Response 200:

json
{
  "success": true,
  "data": {
    "mediaId": "1234567890"
  }
}

Mode B — raw body (buffer / stream)

Same pattern as the main AvenPing app upload route: the body is the raw file bytes.

HeaderRequiredDescription
Content-TyperecommendedFile MIME type (e.g. image/jpeg)
X-Phone-Number-IdyesMeta phone number ID (also accepts phoneNumberId header)
X-FilenamenoOriginal filename (default file)
X-Upload-TypenoOptional MIME override

Example (curl):

bash
curl -sS -X POST "https://api.avenping.com/v2/media/upload" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-Phone-Number-Id: YOUR_META_PHONE_NUMBER_ID" \
  -H "X-Filename: photo.jpg" \
  -H "Content-Type: image/jpeg" \
  --data-binary "@/path/to/photo.jpg"

Response 200: same as multipart.

Meta / validation errors

Failures from Meta are returned as JSON with success: false, HTTP status aligned when possible (e.g. 400), message from Meta, and the raw Graph payload in details when available (same style as other proxied Graph calls).


GET /v2/media/:mediaId/download

Path: mediaId — Meta media ID.
Query (optional):

NameDescription
dispositioninline (default) or attachment
phoneNumberIdMeta phone number ID — use that line’s WABA token
accountIdAvenPing WABA id from GET /v2/me

Without a WABA selector, the API tries the default account token, then other linked accounts, until Meta returns the media URL.

Success: binary stream, not JSON.

Example request (save to file):

bash
curl -sS -L "https://api.avenping.com/v2/media/MEDIA_ID_FROM_META/download?disposition=attachment" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o "download.bin"

Response 200 (headers — body is raw bytes):

HeaderExample value
Content-Typeimage/jpeg (from Meta)
Content-Length48291
Content-Dispositionattachment or inline

Response 404 (JSON):

json
{
  "success": false,
  "error": "NOT_FOUND",
  "message": "Media URL not found"
}

FAQ

How do I get a mediaId for sending?

POST /v2/media/upload (multipart file + phoneNumberId, or raw body with X-Phone-Number-Id). The JSON response includes data.mediaId. There is no POST /v2/media route.

Is download JSON or binary?

Success is a binary stream (not JSON). Failures such as missing media URL return JSON (404 NOT_FOUND). A download proxy failure can return 502 INTERNAL_ERROR (Failed to download media).

How do I choose which WABA downloads the file?

Pass optional query phoneNumberId or accountId. Without a selector, the API tries the default account token, then other linked accounts, until Meta returns the media URL.