Sending with Media
For templates with an image, video, or document header, you can override the default media per send request. There are two ways to do it:
media_url— pass a public URL directly in the send request. No upload needed.media_id— upload a file once; reuse its ID across many sends. Bahasha hosts and serves the file.
POST /v1/whatsapp/send| Field | Type | Description |
|---|---|---|
media_url | string | Any publicly accessible URL — no upload step needed |
media_id | string | An ID returned by the upload endpoint |
If neither media_url nor media_id is provided, the template’s default media is used automatically. Providing both returns 400 Only one of media_id or media_url can be provided.
media_url and media_id override the top-level template header only. They do not apply to carousel cards — each card keeps the media it was approved with. See Media Card Carousels.
Option A — Direct URL (no upload)
Pass a publicly accessible URL in the media_url field of the send request. Use this when you already host the file and just need to point to it.
curl -X POST https://api.bahasha.app/v1/whatsapp/send \
-H "Authorization: Bearer bh_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "+254700000000",
"phone_number_id": "123456789",
"template_name": "promo_banner",
"language_code": "en_US",
"media_url": "https://cdn.example.com/images/summer-sale.jpg"
}'Option B — Upload and send with media_id
Upload the file once and get back a media_id you can reuse in as many send requests as you like.
You’ll need your phone_number_id (see Phone Numbers) and the template’s id (see Templates) before uploading.
Upload your file
POST /v1/whatsapp/phone_numbers/:phone_number_id/templates/:templateId/mediaSend the file as multipart/form-data with a single file field. Do not set Content-Type manually — your HTTP client adds the correct multipart boundary automatically.
cURL
curl -X POST "https://api.bahasha.app/v1/whatsapp/phone_numbers/123456789/templates/987654321/media" \
-H "Authorization: Bearer bh_live_xxxxxxxxxxxx" \
-F "file=@/path/to/promo-banner.jpg"Response:
{
"success": true,
"media_id": "org123/whatsapp/waba456/templates/987654321/media/987654321_1700000000"
}Save the media_id — you’ll pass it in the send request.
Send using the media_id
Pass the media_id in the send request body. It overrides the template’s default media.
cURL
curl -X POST https://api.bahasha.app/v1/whatsapp/send \
-H "Authorization: Bearer bh_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "+254700000000",
"phone_number_id": "123456789",
"template_name": "promo_banner",
"language_code": "en_US",
"media_id": "org123/whatsapp/waba456/templates/987654321/media/987654321_1700000000"
}'Supported file types and size limits
The following file types are accepted for media upload. Uploads that exceed the size limit or use an unsupported type will be rejected with an error.
| Type | MIME types | Max size |
|---|---|---|
| Image | image/png, image/jpeg | 5 MB |
| Video | video/mp4, video/3gpp | 16 MB |
| Document | application/pdf | 100 MB |
These limits match the WhatsApp Business API requirements. Files exceeding the size limit will receive a 413 Payload Too Large response. Unsupported file types will receive a 415 Unsupported Media Type response.
Managing uploaded media
List media
Returns the template’s current default media and all previously uploaded assets.
GET /v1/whatsapp/phone_numbers/:phone_number_id/templates/:templateId/media{
"current_media_id": "org123/tpl789_default",
"available_media_ids": [
{ "media_id": "org123/whatsapp/waba456/templates/987654321/media/987654321_1700000000" }
]
}Delete media
Permanently removes an uploaded asset from the template’s library. Cleaning up unused media is important to avoid unnecessary storage consumption for your organization. Do not delete the file immediately for use in your Bahasha message list in the dashboard.
DELETE /v1/whatsapp/phone_numbers/:phone_number_id/templates/:templateId/media/:mediaIdURL-encode the mediaId before placing it in the path — it contains forward slashes. Use encodeURIComponent() in JavaScript or urllib.parse.quote(media_id, safe='') in Python.
MEDIA_ID="org123/whatsapp/waba456/templates/987654321/media/987654321_1700000000"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$MEDIA_ID', safe=''))")
curl -X DELETE "https://api.bahasha.app/v1/whatsapp/phone_numbers/123456789/templates/987654321/media/$ENCODED" \
-H "Authorization: Bearer bh_live_xxxxxxxxxxxx"Response:
{ "success": true, "message": "Media deleted successfully" }