API documentation

Upload media

Get a public link for a document, image or video header — no CDN needed.

POSThttps://wabapi.com/api/v1/media

A template with a document, image or video header needs a public link to the file at send time. If you have no file server or CDN of your own, upload the file here and use the url that comes back as the header's link.

Request

Send the file as multipart/form-data, not JSON, with the same Authorization header as a send.

FieldTypeRequiredDescription
filefileyesThe file itself, as a multipart/form-data part. Its type and size must be in the accepted-files table.
filenamestringnoThe name to store the file under, for example invoice-8821.pdf. Defaults to the uploaded file's own name. Anything other than letters, digits, dots, dashes and underscores becomes _, and the name is cut to 120 characters. Its extension decides the file type.

Example

Request
curl -X POST https://wabapi.com/api/v1/media \
  -H "Authorization: Bearer wab_live_0123456789abcdef0123456789abcdef" \
  -F file=@invoice-8821.pdf \
  -F filename=invoice-8821.pdf
Response 201
{
  "id": "Yk3t9QpL2vN8rD5wZa1cXg",
  "url": "https://sin1.contabostorage.com/0a1b2c3d4e5f:wabapi/api-media/ten_7c2e91a04b3f4d8e9a1b5c6d/Yk3t9QpL2vN8rD5wZa1cXg/invoice-8821.pdf",
  "filename": "invoice-8821.pdf",
  "content_type": "application/pdf",
  "size_bytes": 48213,
  "created_at": "2026-09-01T09:59:30.000Z"
}
FieldTypeRequiredDescription
idstringyesThe upload's id — 22 random characters, part of the url.
urlstringyesThe file's public address. Pass it as the link of a document, image or video header.
filenamestringyesThe name the file was stored under, after the clean-up described above.
content_typestringyesThe file's media type, decided by its extension.
size_bytesintegeryesThe file's size.
created_atstringyesWhen it was uploaded, ISO 8601 in UTC.

Accepted files

KindExtensionsLargest file
Imagejpg, jpeg, png5 MB
Videomp4, 3gp16 MB
Audiomp3, ogg, aac, amr, m4a, wav16 MB
Documentpdf, doc, docx, xls, xlsx, ppt, pptx, txt, csv50 MB

The extension of the final filename decides the type, and the file's contents must match it: a .pdf that is not really a PDF is refused. The size limits are WhatsApp's own, so a file that uploads here is not then refused at send time for its size. GIF is not accepted; WhatsApp does not take GIF headers.

Use the url in a send

Request body — POST /messages/template
{
  "to": "917021948630",
  "template_name": "ticket_confirmation",
  "template_language": "en",
  "components": [
    {
      "type": "header",
      "parameters": [
        {
          "type": "document",
          "document": {
            "link": "https://sin1.contabostorage.com/0a1b2c3d4e5f:wabapi/api-media/ten_7c2e91a04b3f4d8e9a1b5c6d/Yk3t9QpL2vN8rD5wZa1cXg/invoice-8821.pdf",
            "filename": "invoice-8821.pdf"
          }
        }
      ]
    },
    {
      "type": "body",
      "parameters": [
        {
          "type": "text",
          "text": "Prajesh"
        },
        {
          "type": "text",
          "text": "Thane"
        },
        {
          "type": "text",
          "text": "04:00 PM"
        }
      ]
    }
  ]
}

Cost and limits

Uploading is free: no credits are used, and it works before your first payment. Each API key may upload 30 files a minute; above that the API answers 429 rate_limited with a Retry-After header. The file is served from our file storage, so the url is not on wabapi.com.

Links are public and kept indefinitely: anyone with the url can open the file. The random id in the path makes the url unguessable, but it is not a password — so do not upload anything you would not send to that customer anyway.

Errors

HTTPcodeMeaning
400invalid_requestThe body is not valid JSON or fails the schema.
401invalid_api_keyThe Authorization header is missing, malformed, unknown or revoked.
400unsupported_media_typeThe uploaded file's type is not accepted, or its contents do not match its extension. Images: jpg, jpeg, png. Video: mp4, 3gp. Audio: mp3, ogg, aac, amr, m4a, wav. Documents: pdf, doc, docx, xls, xlsx, ppt, pptx, txt, csv.
413file_too_largeThe uploaded file is larger than WhatsApp allows for its type: 5 MB for images, 16 MB for video and audio, 50 MB for documents.
429rate_limitedToo many sends on this key in the last minute. Retry after the `Retry-After` seconds.
503storage_unavailableFile storage is unavailable right now, so the file was not saved. Nothing was charged; try again shortly.

A failed upload stores nothing. Retrying the same file after an error is safe; each successful upload gets its own id and url.