Send WhatsApp Messages
Send an approved WhatsApp template message to any phone number.
POST /v1/whatsapp/sendRequest body
| Field | Type | Required | Description |
|---|---|---|---|
to | string | ✓ | Recipient phone number in E.164 format (e.g. +254700000000) |
phone_number_id | string | ✓ | Your sending phone number id from /v1/whatsapp/phone_numbers |
template_name | string | ✓ | The template name from the templates endpoint |
language_code | string | ✓ | The template language from the templates endpoint (e.g. en_US) |
variables | object | — | Template placeholder values. See below. |
media_url | string | — | Public URL of media to use as template header. Alternative to media_id. See Handling Media. |
media_id | string | — | media_id from the Upload Media endpoint. Alternative to media_url. See Handling Media. |
Use the exact template_name and language_code as returned by the templates endpoint. Phone numbers are identified by their phone number ID (id field), not the phone number itself.
Response
{
"success": true,
"message_id": "wamid.HBgNMjU0NzAwMDAwMDAwFQIAERgSNDQ1...",
"to": "+254700000000",
"template": "order_confirmation"
}A successful response means the request was accepted — it does not guarantee delivery. Use webhooks to track delivery status (sent, delivered, read, failed).
Passing template variables
Fetch the template list first, then read expected_variables to know what to pass in variables. Use each param_name as the key.
No variables
If the template has no placeholders, omit the variables field entirely.
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": "hello_world",
"language_code": "en_US"
}'Named variables
Placeholders use string names like {{customer_name}}. The param_name is a string — use it as the key.
// expected_variables.body:
// [ { "param_name": "customer_name", "example": "John Doe" },
// { "param_name": "order_id", "example": "ORD-12345" } ]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": "order_confirmation",
"language_code": "en_US",
"variables": {
"body": {
"customer_name": "Jane Smith",
"order_id": "ORD-78901"
}
}
}'Positional variables
Placeholders use numbers like {{1}}, {{2}}. The param_name is a number — use the number as a string key.
// expected_variables:
// header: [ { "param_name": 1, "example": "Acme Corp" } ]
// body: [ { "param_name": 1, "example": "John" },
// { "param_name": 2, "example": "2026-03-01" } ]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": "appointment_reminder",
"language_code": "en_US",
"variables": {
"header": { "1": "Acme Corp" },
"body": { "1": "John", "2": "2026-03-01" }
}
}'Authentication (OTP) templates
Authentication templates always have a single body variable with param_name: 1. Pass the OTP code as variables.body["1"].
// expected_variables.body:
// [ { "param_name": 1, "example": "123456" } ]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": "your_otp_template",
"language_code": "en_US",
"variables": {
"body": { "1": "847291" }
}
}'Sending with media
For templates with an image, video, or document header, you can override the default media per send request. See Handling Images, Videos, and Documents for full details and upload instructions.
Direct URL
# Pass any publicly accessible URL — no upload step needed
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"
}'If neither media_url nor media_id is provided, the template’s default media is used automatically. Providing both will return an error.