WhatsApp message templates for developers
By Andrés Matte
A practical guide to WhatsApp templates: when they are required, how categories affect approval and pricing, how variables work, and what to model in your product.
Templates are where WhatsApp stops being “send a message” and starts being a governed messaging channel.
If a customer writes to you, you get a customer service window where you can reply freely. If your business starts the conversation outside that window, you usually need an approved message template.
That makes templates a product concern, not just a payload format.
What a template is
A WhatsApp message template is a pre-approved message structure stored in a WhatsApp Business Account.
It has:
- A name.
- A language.
- A category.
- Components such as body, header, footer, and buttons.
- Optional variables.
- Review status from Meta.
Approved templates can be sent through the Messages API. Pending or rejected templates cannot be used for production sends.
The three categories
Every template belongs to a category.
| Category | Use it for | Product risk |
|---|---|---|
| Authentication | OTPs, login codes, account verification | Strict format; Meta controls much of the content. |
| Utility | Transactional updates tied to an existing user action | Can be reclassified or rejected if it sounds promotional. |
| Marketing | Promotions, offers, re-engagement, newsletters | Most sensitive to quality, opt-in, pricing, and user feedback. |
Do not treat category as a label your app can choose freely. It affects approval, pricing, deliverability, and policy risk.
The 24-hour service window
Templates are tightly connected to the 24-hour customer service window.
Inside the window, you can generally send free-form replies to a user-initiated conversation. Outside the window, a business-initiated message usually needs a template.
That means your product should know:
- When the last customer message arrived.
- Whether the conversation is inside the service window.
- Which template category is allowed for the intended action.
- Whether an approved template exists in the right language.
If your app cannot answer those questions, it will either block good sends or attempt bad ones.
Variables: prefer named parameters
Templates often include variables:
Hi {{customer_name}}, your order {{order_id}} is ready.
Meta supports positional and named parameter formats. For developer products, named parameters are easier to maintain because the template itself explains the data contract.
Prefer:
{
"parameter_format": "NAMED",
"components": [
{
"type": "BODY",
"text": "Hi {{customer_name}}, your order {{order_id}} is ready.",
"example": {
"body_text_named_params": [
{ "param_name": "customer_name", "example": "Alex" },
{ "param_name": "order_id", "example": "ORDER-123" }
]
}
}
]
}
The examples are not decoration. Meta needs sample values to review variable templates. Missing or weak examples are a common reason template creation becomes painful.
Components and buttons
The common components are:
HEADER: optional text or media.BODY: required main message.FOOTER: optional static text.BUTTONS: optional quick replies, URLs, phone numbers, OTP buttons, or other supported actions.
Button ordering matters. Meta’s template rules are stricter than most UI builders feel at first: quick replies should not be interleaved with URL or phone-number buttons. Keep the structure simple and predictable.
Dynamic URL buttons also need care. The variable belongs at the end of the URL, and the send-time payload must include the matching button parameter.
Authentication templates are special
Authentication templates are not normal text templates with an OTP inside.
They have stricter rules:
- They require Meta business verification.
- Body text is largely fixed by Meta.
- They must include an OTP button such as copy-code or one-tap.
- The OTP value is still passed at send time.
One-tap and autofill-style authentication experiences are platform-specific. Do not promise the same OTP UX on every device; keep copy-code as the reliable baseline.
If your product needs a custom verification message, it may belong in Utility instead, not Authentication. That decision affects approval and pricing, so do not bury it in UI copy.
What to model in your product
For a real template system, model:
| Field | Why it matters |
|---|---|
| WABA ID | Template creation and listing are account-level operations. |
| Phone number ID | Sending uses the connected sending number. |
| Name and language | Send-time payloads must match an approved template. |
| Category | Drives policy, review, and pricing behavior. |
| Status | Approved, pending, rejected, paused, or disabled states affect sends. |
| Variables | Your app must know the required data contract. |
| Examples | Needed for review and useful for UI previews. |
| Last synced at | Meta can change status outside your product. |
The important distinction: template CRUD is usually WABA-level. Sending is phone-number-level.
Status can change without your product initiating it. Meta can reject, pause, or disable templates, and quality updates can affect whether a template should keep sending. Your app should poll, sync, or subscribe to the relevant template webhooks instead of assuming yesterday’s approved state is still valid.
A review-safe writing style
For utility templates, write like a receipt, not a pitch.
Good:
Hi {{customer_name}}, your appointment for {{appointment_date}} is confirmed. Reply if you need to reschedule.
Risky:
Hi {{customer_name}}, your appointment is confirmed. Check out our new offers before your visit.
For marketing templates, be honest that it is marketing. Add opt-out language where appropriate, keep the value clear, and avoid aggressive urgency.
The fastest template system is not the one that submits everything. It is the one that helps users submit fewer bad templates.
Common rejection causes include:
- Weak or missing examples for variables.
- Promotional language in a Utility template.
- A vague body that does not explain why the user is receiving the message.
- Missing opt-out or preference language for Marketing templates where it belongs.
- Variables used in ways that make the final message impossible to review.
How Kapso fits
Kapso exposes template operations through the WhatsApp API layer: list and create templates at the WABA level, then send approved templates from the connected phone_number_id. The surrounding system keeps the template connected to numbers, webhooks, logs, workflows, and inbox context.
That matters because template approval is only one step. The production problem is sending the right approved template from the right customer-owned number at the right time, then observing what happened.