Documentation menu

Guides

Media

Images, video, audio, documents, voice notes and stickers — sent from a URL or an upload, received as decryptable descriptors or as permanent links.

Send by URL

The simplest path: give us a public URL and we fetch, type and send it. The media kind is taken from mimeType, the response's Content-Type, or the file name, in that order.

POST https://api.meowsapp.com/send-media-message
{
  "clientId": "acmemain",
  "to": "123456789012345",
  "downloadUrl": "https://files.example.com/brochure.pdf",
  "fileName": "Brochure.pdf",
  "caption": "Here is the brochure",
  "quotedMessageId": "3EB0…"
}
// → { "status": "sent", "messageId": "3EB0…", "mediaType": "document", "bytes": 482113 }

Send by upload

For files you hold in memory, upload them as multipart/form-data. Set the part's Content-Type correctly — it decides image/video/audio/document.

curl -X POST "https://api.meowsapp.com/send-media-message?clientId=acmemain" \
  -H "Authorization: Bearer $SN_TOKEN" \
  -F "[email protected];type=image/jpeg" \
  -F clientId=acmemain -F to=123456789012345 -F caption="Here you go"

Multipart needs ?clientId= in the URL

Requests are routed to the machine holding the session by reading clientId from the query string or JSON body. Form bodies cannot be read by the router, so multipart calls must repeat clientId in the URL.

Voice notes & stickers

// voice note (push-to-talk bubble) — supply OGG/Opus
{ "clientId": "acmemain", "to": "123456789012345", "downloadUrl": "https://files.example.com/reply.ogg", "mimeType": "audio/ogg; codecs=opus", "sendAudioAsVoice": true }

// sticker — supply WebP (512×512 recommended)
{ "clientId": "acmemain", "to": "123456789012345", "downloadUrl": "https://files.example.com/thumbs-up.webp", "asSticker": true }

Audio without sendAudioAsVoice is delivered as a regular audio file. There is no transcoding: convert to OGG/Opus (e.g. ffmpeg -i in.mp3 -c:a libopus -b:a 32k out.ogg) before sending a voice note.

Receiving media

Webhook media events carry descriptors, not bytes:

Webhook event
{
  "type": "image",
  "messageId": "3EB0…",
  "body": "Here you go",
  "media": {
    "mimeType": "image/jpeg", "mediaType": "image", "fileName": "photo.jpg", "fileSize": 102400, "caption": "Here you go",
    "download": { "directPath": "/v/t62.7118-24/…", "mediaKey": "base64…", "fileSha256": "base64…", "fileEncSha256": "base64…", "fileLength": 102400 }
  }
}

You have two options:

  1. Download and decrypt yourself with any WhatsApp Web client library — they all take exactly these fields. Treat mediaKey as a secret; the CDN path expires after some days, so download promptly.
  2. Use the hosted inbox. Point the session's webhook at the hosted receiver and every file is downloaded, decrypted and stored under a permanent public link within seconds; downloadUrl appears on the message in GET /chatrooms/{id}/messages. Voice notes keep their audio/ogg; codecs=opus type and play in any modern browser.

Limits

LimitValue
Send by URL — fetch cap100 MB, 60 s timeout
Send by URL — over 60 MBDelivered as a text message containing the link ("fallback": "text") instead of failing
Upload — ingress cap128 MB request; keep files ≤ 64 MB for WhatsApp's own limits
ImagesWhatsApp re-encodes to JPEG; send PNG/JPEG for photos, WebP with asSticker for stickers
DocumentsAny type; set fileName so the recipient sees a sensible name