Creating WhatsApp Templates
Learn how to create and manage WhatsApp message templates for your business
WhatsApp templates are pre-approved message formats that allow you to initiate conversations with users outside the 24-hour messaging window. This guide covers how to create, submit, and manage templates.
Overview
Templates are required for:
- Starting new conversations with users
- Re-engaging users after the 24-hour window expires
- Sending transactional notifications (order updates, appointments, etc.)
Template Structure
A WhatsApp template consists of:
| Component | Required | Description |
|---|---|---|
| Name | Yes | Unique identifier (lowercase, underscores only) |
| Language | Yes | Language code (e.g., en, es, pt) |
| Category | Yes | UTILITY, MARKETING, or AUTHENTICATION |
| Body | Yes | Main message content with variables |
| Header | No | Text, image, video, or document |
| Footer | No | Short footer text |
| Buttons | No | Quick reply or URL buttons (max 3) |
Creating a Template
Via Dashboard
- Navigate to Senders in your dashboard
- Select the sender you want to create templates for
- Go to the Templates tab
- Click Create Template
- Fill in the template details and submit
Via API
import Zavudev from '@zavudev/sdk';
const zavu = new Zavudev({
apiKey: process.env["ZAVUDEV_API_KEY"],
});
const template = await zavu.templates.create({
name: 'order_confirmation',
language: 'en',
body: 'Hi {{1}}, your order {{2}} has been confirmed and will ship within 24 hours.',
category: 'UTILITY',
variables: ['customer_name', 'order_id'],
});
console.log('Template ID:', template.id);
console.log('Status:', template.whatsappStatus); // "draft"
Template Variables
Use numbered placeholders for dynamic content:
CodeHi {{1}}, your order {{2}} is ready for pickup at {{3}}.
When sending a message, provide the variable values:
TypeScriptawait zavu.messages.send({ to: '+14155551234', messageType: 'template', content: { templateId: 'tmpl_abc123', templateVariables: { '1': 'John', '2': 'ORD-12345', '3': '123 Main St' } } });
Templates can also use named placeholders ({{customer_name}}) and text-header variables. For how named vs positional formats work and how to send them, see How Variables Work.
Template Categories
UTILITY
For transactional messages with specific, agreed-upon information.
Examples:
- Order confirmations
- Shipping updates
- Appointment reminders
- Account notifications
Cost: Lower messaging rates
MARKETING
For promotional content and offers.
Examples:
- Sales announcements
- Product recommendations
- Newsletter content
- Promotional offers
Cost: Higher messaging rates
AUTHENTICATION
For one-time passwords and verification codes.
Examples:
- Login verification
- Two-factor authentication
- Account verification
Cost: Lowest messaging rates
Adding Headers
Add a header to make your template more engaging:
TypeScriptconst template = await zavu.templates.create({ name: 'shipping_update', language: 'en', body: 'Your package {{1}} is on its way!', category: 'UTILITY', headerType: 'text', headerContent: 'Shipping Update', });
Header Types
| Type | Description |
|---|---|
text | Plain text header |
image | Image header (provide URL) |
video | Video header (provide URL) |
document | PDF or document header |
Adding Buttons
Templates can include up to 3 buttons:
TypeScriptconst template = await zavu.templates.create({ name: 'order_tracking', language: 'en', body: 'Your order {{1}} has shipped!', category: 'UTILITY', buttons: [ { type: 'url', text: 'Track Order', url: 'https://example.com/track/{{1}}' }, { type: 'quick_reply', text: 'Contact Support' } ] });
Button Types
| Type | Description |
|---|---|
quick_reply | Sends predefined response |
url | Opens a URL (can include variables) |
phone | Initiates a phone call |
request_contact_info | Asks the recipient to share their phone number. The label is fixed by WhatsApp (Share Contact Info), so text is not required. Useful for username contacts known only by BSUID. |
TypeScriptconst template = await zavu.templates.create({ name: 'callback_request', language: 'en', body: 'Hi {{1}}, we need a phone number to schedule your callback.', category: 'UTILITY', buttons: [ { type: 'request_contact_info' } ] });
The recipient's answer arrives as an inbound contact message, and Zavu links the shared number to the contact automatically. See Contact Info Request Messages.
Best Practices
Templates have character limits. Body text should be under 1024 characters.
Name your variables descriptively in the documentation for easier maintenance.
Incorrect categorization may lead to rejection or higher costs.
Always test templates with your own number first.
Naming Conventions
Template names must:
- Be unique within your account
- Use only lowercase letters, numbers, and underscores
- Not exceed 512 characters
- Not start with a number
Good examples:
order_confirmation_v2appointment_remindershipping_update_en
Bad examples:
Order Confirmation(spaces not allowed)2fa_code(starts with number)ORDER_CONFIRMATION(uppercase not allowed)