POST /v1/{waba_id}/templates
Creates a message template on a WhatsApp Business Account (WABA) and submits it to WhatsApp for
review. New templates start as PENDING. WhatsApp usually reviews templates within 24 hours at
most; review times are subject to WhatsApp’s policies. Poll
GET /v1/templates/{template_id} to see the result.
The request body is Meta’s own Create Message Template body, forwarded to WhatsApp as sent — any component type or top-level field Meta accepts is accepted here, including kinds this page doesn’t show an example for (carousel, authentication, limited-time offer, catalog, flows).
POST /v1/{waba_id}/templatesAuthorization: Bearer hello_live_xxxxxxxxxxxxxxxxContent-Type: application/jsonExample: text template with variables
Section titled “Example: text template with variables”curl -X POST "$HELLO_API_URL/v1/<your-waba-id>/templates" \ -H "Authorization: Bearer $HELLO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "order_shipped", "language": "en", "category": "UTILITY", "components": [ { "type": "BODY", "text": "Hi {{1}}, your order {{2}} has shipped and will arrive in 2-3 days.", "example": { "body_text": [["Asha", "#10432"]] } }, { "type": "FOOTER", "text": "Reply STOP to opt out" }, { "type": "BUTTONS", "buttons": [ { "type": "URL", "text": "Track order", "url": "https://example.com/track" } ] } ] }'Example: named variables
Section titled “Example: named variables”Use {{name}} placeholders and give examples by name:
{ "name": "login_otp_named", "language": "en", "category": "UTILITY", "parameter_format": "NAMED", "components": [ { "type": "BODY", "text": "Hi {{first_name}}, your appointment is on {{date}}.", "example": { "body_text_named_params": [ { "param_name": "first_name", "example": "Asha" }, { "param_name": "date", "example": "3 October" } ] } } ]}parameter_format is NAMED or POSITIONAL. Hello infers NAMED when you leave it out and
use *_named_params; otherwise it’s worked out from the placeholders.
Example: image header
Section titled “Example: image header”A media header needs a sample file. Put a public URL of the sample in
example.header_handle, and Hello uploads it to WhatsApp for you:
{ "name": "diwali_sale", "language": "en", "category": "MARKETING", "components": [ { "type": "HEADER", "format": "IMAGE", "example": { "header_handle": ["https://example.com/samples/diwali-banner.jpg"] } }, { "type": "BODY", "text": "Our Diwali sale is live — 30% off everything until Sunday." } ]}A value in header_handle is treated as a URL to fetch (and swap for a Meta upload handle) when
it looks like one — starts with a scheme, a /, or contains whitespace. An existing Meta media
handle is left alone.
Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Lowercase letters, numbers and underscores only |
language |
string | Yes | An official WhatsApp template language code, for example en, en_US, hi |
category |
string | Yes | MARKETING, UTILITY or AUTHENTICATION |
components |
array | Yes | Template components in WhatsApp’s format |
parameter_format |
string | No | NAMED or POSITIONAL |
Any other field Meta’s create body accepts (for example sub_category,
message_send_ttl_seconds) is forwarded and stored unchanged.
Components:
type |
Fields |
|---|---|
HEADER |
format: TEXT, IMAGE, VIDEO, DOCUMENT or LOCATION. text for text headers. example.header_handle (sample URL) for media headers. |
BODY |
text (required), and example whenever the text has variables |
FOOTER |
text |
BUTTONS |
buttons[], each with type (QUICK_REPLY, URL, PHONE_NUMBER, COPY_CODE, and Meta’s other button kinds such as OTP and flow buttons), text, and url, phone_number or example as needed |
CAROUSEL, and other component types Meta defines |
Forwarded and stored as sent |
Response 200
Section titled “Response 200”Meta’s own create response:
{ "id": "1234567890123456", "status": "PENDING", "category": "UTILITY" }Errors
Section titled “Errors”| Status | code |
Cause |
|---|---|---|
400 |
VALIDATION_ERROR |
The body isn’t valid JSON, or fails Hello’s minimal checks |
401 |
UNAUTHORIZED |
Missing, wrong or disabled API key |
404 |
NOT_FOUND |
No such WABA in your organization |
409 |
ACCOUNT_NOT_REGISTERED |
The WABA has no active, registered number |
422 |
META_REJECTED |
WhatsApp rejected the template (duplicate name, invalid format, sample media it couldn’t fetch, and so on). meta_error carries Meta’s own error detail. |
500 |
Temporary server error. Retry. |
{ "message": "Meta rejected the template", "code": "META_REJECTED", "meta_error": { "code": 100, "error_user_title": "Invalid Template Format", "error_user_msg": "Template content doesn't match the selected category." }}