Skip to content

Sending media

Media (images, audio, video, documents and stickers) is sent through the same POST /v1/messages endpoint used for text. The media fields go inside the content object. The type comes from the anchor field present (image_url, video_url, audio_url, document_url or sticker_url).

Supported media types

VariantAnchor fieldCommon formatsMaximum sizecaption?filename?
imageimage_urlJPEG, PNG, WebP16 MB✓—
videovideo_urlMP4100 MB✓—
audioaudio_urlMP3, OGG, M4A16 MB——
documentdocument_urlPDF, DOCX, XLSX, etc.100 MB✓✓
stickersticker_urlWebP (static or animated), exactly 512×512px500 KB——

caption is not accepted for audio and sticker. The API returns 422 if the field is sent with those types.

After sending, only the caption of an image, video or document can be edited. The file, audio and stickers cannot: deleting is the only change. See what can be changed after sending.

Method: public URL

Provide a publicly accessible HTTPS URL. Turbo Notify downloads the file before delivering it to WhatsApp.

Image

send-image.sh
curl -X POST \
https://api.turbonotify.com/v1/messages \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": {"number": "+5511988887777"},
"content": {
"image_url": "https://cdn.example.com/product-photo.jpg",
"mime_type": "image/jpeg",
"caption": "Product photo"
}
}'

Video

send-video.sh
curl -X POST \
https://api.turbonotify.com/v1/messages \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": {"number": "+5511988887777"},
"content": {
"video_url": "https://cdn.example.com/product-clip.mp4",
"mime_type": "video/mp4",
"caption": "Watch the video"
}
}'

A video caption also accepts @<number> mentions.

Audio

send-audio.sh
curl -X POST \
https://api.turbonotify.com/v1/messages \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": {"number": "+5511988887777"},
"content": {
"audio_url": "https://cdn.example.com/audio.ogg",
"mime_type": "audio/ogg"
}
}'

mime_type is optional and does not change how the file is sent: the format WhatsApp receives comes from what the server behind the URL actually delivers.

Document

send-document.sh
curl -X POST \
https://api.turbonotify.com/v1/messages \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": {"number": "+5511988887777"},
"content": {
"document_url": "https://cdn.example.com/invoice.pdf",
"mime_type": "application/pdf",
"filename": "Invoice-April.pdf",
"caption": "Your invoice for April"
}
}'

filename appears as the attachment name in the recipient’s chat. A document caption also accepts @<number> mentions.

Sticker

send-sticker.sh
curl -X POST \
https://api.turbonotify.com/v1/messages \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": {"number": "+5511988887777"},
"content": {
"sticker_url": "https://cdn.example.com/animated-sticker.webp",
"mime_type": "image/webp"
}
}'

Stickers must be WebP (static or animated), with exact dimensions of 512×512 pixels (any other size is rejected even if the WebP is valid), and stay within the 500 KB limit.

Field schema (all types)

The media fields go inside the content object. The anchor field (e.g. image_url) determines the variant. Every media send uses a public URL; you cannot send a file by giving only its key in your BYO Storage.

Field in contentTypeRequiredNotes
image_urlURLconditionalAnchor field for images; public HTTPS URL
video_urlURLconditionalAnchor field for videos; public HTTPS URL
audio_urlURLconditionalAnchor field for audio; public HTTPS URL
document_urlURLconditionalAnchor field for documents; public HTTPS URL
sticker_urlURLconditionalAnchor field for stickers; public HTTPS URL
mime_typestringnooptional and informational: it does not change the send. The format is identified from the file downloaded from the URL
captionstringpartialaccepted for image, video, document; not accepted for audio and sticker (returns 422). Accepts @<number> mention tokens, detected implicitly, with the same rules as text
filenamestringnodocument only; appears as the attachment name in the chat

Response

HTTP status: 202
{
  "message_id": "msg_a1b2c3d4e5f60718293a4b5c6d7e8f90",
  "status": {
    "state": "pending",
    "at": "2026-04-27T10:00:05Z",
    "error": null
  }
}

The actual confirmation arrives through the message.sent webhook. If the send fails (unreachable URL, unsupported format, size exceeded) you receive message.send.failed with a specific error object ({ code, message, hint }).

Outbound webhook

When WhatsApp confirms the send, the message.sent webhook includes content_type and preview (same format as message.received):

webhook-message-sent.json
{
"id": "evt_3f9a1c2b4d5e6f708192a3b4c5d6e7f8",
"type": "message.sent",
"organization_id": "org_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"number_alias": "main",
"number_id": "num_0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"created_at": "2026-04-27T10:00:08Z",
"data": {
"id": "msg_a1b2c3d4e5f60718293a4b5c6d7e8f90",
"from": { "alias": "main", "number": "5511973117056" },
"to": { "number": "5511988887777" },
"preview": "Product photo",
"content_type": "image",
"direction": "outbound",
"channel": "whatsapp",
"origin": "tn",
"at": "2026-04-27T10:00:08Z"
}
}

To download the file of a received media message, use GET /v1/numbers/{ref}/messages/{id}: the media fields appear directly in the object named after the content_type (image, video, audio, document, sticker), with no media sub-object. With BYO Object Storage set up, that object comes with kind: "available" and a url holding the presigned download URL.