Send a template with media and buttons
The richest message you can send to any customer, even outside the 24-hour window, is a template that combines a media header, body text, a footer and buttons. Product launches, offers, tickets and invoices commonly use it.
This page goes end to end: create the template, wait for approval, then send it.
1. Create the template
Section titled “1. Create the template”curl -X POST "$HELLO_API_URL/v1/<your-waba-id>/templates" \ -H "Authorization: Bearer $HELLO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "new_arrival_offer", "language": "en", "category": "MARKETING", "components": [ { "type": "HEADER", "format": "IMAGE", "example": { "header_handle": ["https://example.com/samples/sneaker.jpg"] } }, { "type": "BODY", "text": "Hi {{1}}, the {{2}} just landed. Get 15% off this week only.", "example": { "body_text": [["Asha", "Runner 2"]] } }, { "type": "FOOTER", "text": "Reply STOP to opt out" }, { "type": "BUTTONS", "buttons": [ { "type": "URL", "text": "Shop now", "url": "https://example.com/new-arrivals" }, { "type": "QUICK_REPLY", "text": "Not interested" } ] } ] }'The response is Meta’s { id, status, category }, with "status": "PENDING". Keep the id.
2. Wait for approval
Section titled “2. Wait for approval”curl "$HELLO_API_URL/v1/templates/$TEMPLATE_ID" \ -H "Authorization: Bearer $HELLO_API_KEY"Send once status is APPROVED. If it’s REJECTED, rejected_reason says what to change.
3. Send it
Section titled “3. Send it”Each send supplies the header image and the body variables. The footer and buttons come from the template.
curl -X POST "$HELLO_API_URL/v1/<your-phone-number-id>/messages" \ -H "Authorization: Bearer $HELLO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to": "+919999999999", "type": "template", "template": { "name": "new_arrival_offer", "language": { "code": "en" }, "components": [ { "type": "header", "parameters": [ { "type": "image", "image": { "link": "https://example.com/catalog/runner-2-red.jpg" } } ] }, { "type": "body", "parameters": [ { "type": "text", "text": "Asha" }, { "type": "text", "text": "Runner 2" } ] } ] } }'{ "messaging_product": "whatsapp", "contacts": [{ "input": "+919999999999", "wa_id": "919999999999" }], "messages": [{ "id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b", "message_status": "queued" }]}To send the same image to many people, upload it once and use
"image": { "id": "<media_id>" } instead of link. WhatsApp then doesn’t fetch the file for
every message.
Variations
Section titled “Variations”Video header. Create the template with "format": "VIDEO" and send
{ "type": "video", "video": { "link": "https://…/launch.mp4" } }.
Document header with buttons, for example an invoice with a “Pay now” link:
{ "type": "header", "parameters": [ { "type": "document", "document": { "link": "https://example.com/invoices/INV-2291.pdf", "filename": "INV-2291.pdf" } } ]}Call button. Add { "type": "PHONE_NUMBER", "text": "Call us", "phone_number": "+919812345678" }
to the template’s buttons. Nothing changes in the send request.
Dynamic URL or copy-code button. Add a button component to the send — see
Buttons.