Creating templates#
This guide shows you how to build a valid Create Whatsapp Template request for every kind of template Chronox supports, and lists every rule the API checks.How it works#
You describe the template in your request: the text, the header, the buttons. Chronox checks it, then sends it to Meta for approval and saves the result in your workspace.Values such as the category, language and button types are sent as ID numbers, not words. You get those IDs from the lookup endpoints.Interactive messages are different. When whatsapp_template_flag_interactive_message is true, Chronox checks your message and saves it in your workspace but doesn't send it to Meta. There's no approval step, and the category and language are ignored.
Before you start#
2
Find your WhatsApp connection ID
Call Get Meta Integration and note the meta_integration_whatsapp_id for the WhatsApp number this template belongs to.
3
Fetch the lookup lists you need
Call the lookups below and copy the IDs you need into your request.
The lookup endpoints#
| What you need | Call this |
|---|
| Template shape: basic, carousel and so on | GET /global/whatsapp-template-type |
| Category: Marketing, Utility, Authentication | GET /global/whatsapp-template-category |
| Message language | GET /global/whatsapp-languages |
| Header kind: text, image, video, document | GET /global/whatsapp-template-header-type |
| Buttons: types, sub-types, their fields and options | GET /global/whatsapp-template-button-type |
| Where blanks can be used | GET /global/whatsapp-template-dynamic-variable-type |
| Interactive kinds: list, reply buttons, flow and so on | GET /global/interactive-types |
Always read button IDs from the lookup. The button response is nested: button type → sub-type → fields, and some fields have fixed options. The ID numbers aren't fixed values you can memorise, and they differ between Chronox environments. Read them from GET /global/whatsapp-template-button-type and use what it returns.
The request#
POST /meta-integration/create-whatsapp-templateTop-level fields#
| Field | When to send it | What it does |
|---|
meta_integration_whatsapp_id | Always | Which connected WhatsApp number the template belongs to. |
whatsapp_template_data | Always | The template itself: name, language, text, buttons. |
whatsapp_template_type_id | Optional | Leave it out for a basic template. Set it for carousel and other types. |
flag_named_parameter | With named blanks | true for {{order_id}}-style blanks. Leave out for {{1}}-style. |
whatsapp_template_flag_interactive_message | Interactive only | true to create an interactive message instead of a Meta template. |
interactive_type_id | Interactive only | From Get Whatsapp Template Interactive Type. |
interactive_list_button_text | List interactive only | The label on the list button. Only valid with the list type. |
whatsapp_template_flag_flow | Flow buttons only | true when the template opens a WhatsApp Flow. |
Inside whatsapp_template_data#
| Field | Needed? | What it does |
|---|
whatsapp_template_name | Yes | Machine name: lowercase letters, numbers and underscores, unique for that WhatsApp number, up to 512 characters. Generated from the display name if you only send that. |
whatsapp_template_display_name | Optional | Friendly name shown in Chronox. |
whatsapp_template_description | Optional | Your own notes. |
whatsapp_language_id | Yes* | From the languages lookup. |
whatsapp_template_category_id | Yes* | From the category lookup. |
whatsapp_template_header | Optional | Text at the top of the message. |
whatsapp_template_body | Yes | The message text. For carousels, each card has its own body. |
whatsapp_template_footer | Optional | Small line under the message. |
whatsapp_template_button | Optional | Buttons. |
whatsapp_template_carousel | Carousel only | The cards. |
whatsapp_template_security_recommendation | Authentication only | Changes which body sentence Meta requires. |
whatsapp_template_code_expiration_minutes | Authentication only | How long the code is valid. Chronox passes this to Meta when it's between 1 and 90. |
* Not used for interactive messages.A complete example#
A utility template with a text header, blanks, a footer and two buttons:{
"meta_integration_whatsapp_id": 123,
"whatsapp_template_type_id": 1,
"flag_named_parameter": true,
"whatsapp_template_data": {
"whatsapp_template_name": "order_shipped_details",
"whatsapp_template_display_name": "Order shipped (with details)",
"whatsapp_template_category_id": 2,
"whatsapp_language_id": 15,
"whatsapp_template_header": {
"whatsapp_template_header_type_id": 1,
"whatsapp_template_header_data": [
{
"whatsapp_template_header_data_value": "Order {{order_id}} is on its way",
"whatsapp_template_header_variable_data": [
{
"whatsapp_template_dynamic_variable_key": "{{order_id}}",
"whatsapp_template_dynamic_variable_sample_value": "ORD-10045"
}
]
}
]
},
"whatsapp_template_body": {
"whatsapp_template_body_value": "Hi {{customer_name}}, good news! Your order has been shipped and should reach you within {{delivery_days}} days.",
"whatsapp_template_body_variable_data": [
{
"whatsapp_template_dynamic_variable_key": "{{customer_name}}",
"whatsapp_template_dynamic_variable_sample_value": "Priya"
},
{
"whatsapp_template_dynamic_variable_key": "{{delivery_days}}",
"whatsapp_template_dynamic_variable_sample_value": "3"
}
]
},
"whatsapp_template_footer": {
"whatsapp_template_footer_value": "Example Store"
},
"whatsapp_template_button": [
{
"whatsapp_template_button_type_id": 2,
"whatsapp_template_button_data": [
{
"whatsapp_template_button_sub_type_id": 3,
"whatsapp_template_button_sub_type_field_data": [
{ "whatsapp_template_button_sub_type_field_id": 3, "whatsapp_template_button_sub_type_field_value": "Track order" },
{ "whatsapp_template_button_sub_type_field_id": 4, "whatsapp_template_button_sub_type_field_option_id": 2 },
{ "whatsapp_template_button_sub_type_field_id": 5, "whatsapp_template_button_sub_type_field_value": "https://example.com/track" }
]
},
{
"whatsapp_template_button_sub_type_id": 4,
"whatsapp_template_button_sub_type_field_data": [
{ "whatsapp_template_button_sub_type_field_id": 6, "whatsapp_template_button_sub_type_field_value": "Call us" },
{ "whatsapp_template_button_sub_type_field_id": 2, "whatsapp_template_button_sub_type_field_option_id": 64 },
{ "whatsapp_template_button_sub_type_field_id": 12, "whatsapp_template_button_sub_type_field_value": "9876543210" }
]
}
]
}
]
}
}
The IDs above come from the lookups: header type 1 is Text, button type 2 is Call to action, sub-type 3 is Visit Website and sub-type 4 is Call phone number. Check the field IDs against your own lookup response before using them.The parts of a template#
Send whatsapp_template_header with a whatsapp_template_header_type_id and a whatsapp_template_header_data array containing exactly one item.Put the text in whatsapp_template_header_data_value.
Maximum 60 characters. Each {{blank}} counts as one character.
Any blank in the text needs an entry in whatsapp_template_header_variable_data, with a key and a sample value.
Image, video and document headers can't be created through the API. They need a file that's already been uploaded to Chronox (whatsapp_template_header_data_google_storage_id), and there's no public endpoint for uploading files. Create these templates in the Chronox dashboard instead. If you already have a storage ID, the allowed file types are jpg, jpeg, png for images, mp4, 3gp for video and pdf for documents.
Body#
Send whatsapp_template_body with:whatsapp_template_body_value — the message text.
whatsapp_template_body_description — optional notes.
whatsapp_template_body_variable_data — required whenever the text contains blanks. Each entry needs:whatsapp_template_dynamic_variable_key, for example {{1}} or {{order_id}} (the braces are optional).
whatsapp_template_dynamic_variable_sample_value — an example Meta uses when reviewing.
Inside {{ }} use only lowercase letters, numbers and underscores.
Use either numbered blanks ({{1}}, {{2}}) or named ones ({{order_id}}), never both.
Numbered blanks must run in order with no gaps.
For named blanks, set flag_named_parameter to true. Purely numeric names such as {{1}} are then rejected.
Every blank in the text needs exactly one entry in the variable array, and every entry must appear in the text.
The text needs enough real words around the blanks: roughly three words per blank, plus one.
Send whatsapp_template_footer with whatsapp_template_footer_value.Send whatsapp_template_button as an array. Each item has:whatsapp_template_button_type_id — from the button lookup.
whatsapp_template_button_data — one or more entries, each with a whatsapp_template_button_sub_type_id and a whatsapp_template_button_sub_type_field_data array.
Each field entry has the whatsapp_template_button_sub_type_field_id from the lookup, plus either:whatsapp_template_button_sub_type_field_value for a normal field, or
whatsapp_template_button_sub_type_field_option_id for a field with fixed options, such as Country or URL Type.
Group buttons by type. All buttons of one type must sit together. You can't return to a type you've already finished.
Button labels must be unique within a template.
Website buttons can be static or dynamic. For a dynamic link, choose the Dynamic URL Type option, include a blank in the URL, and add a whatsapp_template_button_field_data_variable array with a sample value.
Quick reply payloads: the optional Payload field takes an array of { "payload_key", "payload_key_value" } entries, each key used once.
Button Description is only allowed on interactive messages. Sending it on a normal template is rejected.
Flow buttons: set whatsapp_template_flag_flow to true, use only one flow button per template, and use a Flow that already exists in Chronox.
View Catalog buttons always use the label View catalog, whatever you send.
Link tracking: setting flag_allow_tracking on a website button makes Chronox use a tracking link for it.
WhatsApp limits how many buttons a template can have: 10 in total, of which at most 2 website buttons, 1 phone number button, 1 copy code button, and up to 10 quick reply buttons. Chronox doesn't check these, so Meta refuses templates that break them.Carousel#
Set the template type to Carousel and send whatsapp_template_carousel:whatsapp_template_carousel_header — the text above the cards. Required, and it may contain blanks.
whatsapp_template_carousel_header_dynamic_variable — sample values for those blanks.
whatsapp_template_carousel_card — between 2 and 10 cards.
Each card uses the same structure as a normal template: whatsapp_template_header, whatsapp_template_body, whatsapp_template_footer and whatsapp_template_button.If one card has body text, every card must have body text.
The carousel header can't contain more than one line break in a row, and carousel card bodies can't either.
WhatsApp also requires that every card has an image or video header, that card bodies are 160 characters or fewer, and that each card has at most two buttons. Chronox doesn't check these, so a carousel that breaks them is refused by Meta rather than by the API. Since media headers need a file uploaded in the dashboard, carousel templates are usually easier to create there.Copy Offer Code buttons can't be used on carousels. They only work on basic Marketing templates.Authentication (OTP) templates#
Use the Authentication category. These have the strictest rules:| Rule | Detail |
|---|
| No header | Authentication templates can't have a header at all. |
| Exact body text | *{{1}}* is your verification code. |
| With security advice | Set whatsapp_template_security_recommendation to true and use *{{1}}* is your verification code. For your security, do not share this code. |
| One blank only | Exactly one {{1}}, with exactly one entry in the variable array. |
| One button at most | Must be a Copy Code or One Tap button. |
| Copy Code label | Must be exactly Copy Code or Copy code. |
| Footer | Up to 60 characters. Required when you set a code expiry. |
| Code expiry | whatsapp_template_code_expiration_minutes is passed to Meta when it's between 1 and 90. |
Interactive messages#
Set whatsapp_template_flag_interactive_message to true and choose an interactive_type_id. Each kind has its own rules:| Kind | Rules |
|---|
| Reply buttons | 1–3 buttons. Each label up to 20 characters. |
| List | If you use a header it must be text. 1–10 rows, each title up to 24 characters. Body up to 4096 characters. interactive_list_button_text is allowed only here. |
| Text | Body required, up to 4096 characters. No buttons and no footer. |
| Flow | Exactly one flow button, with a flow ID and button text. Body up to 4096 characters. |
| CTA URL | Exactly one website button. Display text up to 20 characters. Body up to 1024, footer up to 60. |
| Catalog | Body up to 1024 characters, footer up to 60. |
With a non-text header, an interactive message can have at most 3 buttons.Character limits#
| Where | Field | Limit |
|---|
| Template | Name | 512 |
| Template | Header text | 60 (each blank counts as 1) |
| Template | Authentication footer | 60 |
| Button | Any button label | 25 |
| Button | Website URL | 2000 (including the blank) |
| Button | Phone number | 20 |
| Button | Offer code | 20 |
| Button | Flow payload / input payload | 2000 each |
| Body | Message text | 1024 (WhatsApp's limit) |
| Footer | Footer text | 60 (WhatsApp's limit) |
| Authentication | The code you send later | 15 (WhatsApp's limit) |
| Carousel | Each card's body | 160 (WhatsApp's limit) |
| Interactive | Reply button label | 20 |
| Interactive | List row title | 24 |
| Interactive | CTA URL display text | 20 |
| Interactive | Body (list, text, flow) | 4096 |
| Interactive | Body (CTA URL, catalog) | 1024 |
| Interactive | Footer (CTA URL, catalog) | 60 |
Button field limits come from field_character_limit in the button lookup, so the lookup is always the authority. Where an interactive rule is stricter than the general button rule, the interactive one applies.
Other limits that apply to the body text:Marketing templates: at most 10 emojis.
Marketing and Utility: no more than 2 line breaks in a row.
Carousel: no more than 1 line break in a row.
After you create a template#
| What you created | What happens |
|---|
| Basic or carousel template | Sent to Meta. The status is usually Pending until Meta reviews it. |
| Interactive message | Saved in Chronox and ready to use. No Meta review. |
GET /meta-integration/{meta_integration_whatsapp_id}/whatsapp-template/{whatsapp_template_id}
The status is in whatsapp_template_metadata.meta_whatsapp_template_status_name.If it fails#
Chronox errors cover the rules on this page: blanks that don't match, buttons in the wrong order, carousel size, OTP wording, missing sample values and so on. Most come back as Invalid body!, which doesn't say which field was wrong, so check your request against this page.
Meta errors come back with Meta's own code and message, and cover their content and category policies.