Button Variables
A URL button can end with a dynamic value, e.g. https://example-shop.com/track/{{1}}. Pass the value under variables.buttons, keyed by the button’s param_name from expected_variables.buttons.
POST /v1/whatsapp/sendThe button variable is always {{1}} — even for named templates. You can send either the dynamic value only or the full URL with the variable filled in.
A template may have up to two URL buttons, and both can be dynamic — each with its own {{1}}. Because every URL button’s {{1}} is local to that button, values are keyed by the button’s position in the template’s full button list (counting all buttons, including quick-reply buttons), not by the {{1}} inside the link. So the key is "1" only if that URL button is the first button overall; if a quick-reply button precedes it, the URL button’s key is "2". Always read expected_variables.buttons to get the exact keys — the param_name there is the position.
// expected_variables.buttons for a template with two dynamic URL buttons:
// [ { "param_name": 1, "example": "TRK-98765" },
// { "param_name": 2, "example": "INV-4021" } ]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" },
"buttons": { "1": "TRK-98765" }
}
}'Two dynamic URL buttons
For a template with two dynamic URL buttons, supply both values keyed by position. Each is independent and appended to its own button’s link:
"variables": {
"buttons": {
"1": "TRK-98765",
"2": "INV-4021"
}
}Only URL buttons whose link ends with a variable need a value. The dynamic value sits at the end of the URL and is keyed by the button’s position — this is configured when you build the template in the dashboard. Send the value as-is (e.g. Gonçalves); Bahasha percent-encodes it before appending it to the link.
Values for buttons that are not URL buttons, or whose URL has no variable, are silently ignored — the message still sends, just without that value. If a link arrives without its dynamic part, check that the key matches a param_name in expected_variables.buttons.
Carousel cards can have their own URL buttons, keyed the same way but scoped to the card. See Carousels.