whatsapp-templates
SKILL.md
WhatsApp Templates
When to Use
Use this skill when building code to create, manage, or send WhatsApp template messages. Templates are required to initiate conversations outside the 24-hour window.
When Templates Are Required
Has user messaged you in the last 24 hours?
-> YES: Send free-form message (text, image, buttons, etc.)
-> NO: Must use template message
Need to send bulk/broadcast messages?
-> YES: Use template (recommended for consistency)
Want proactive outbound notifications?
-> YES: Must use template
Template Categories
| Category | Use Case | Examples |
|---|---|---|
UTILITY |
Transactional updates | Order confirmations, shipping updates, appointment reminders |
MARKETING |
Promotional content | Sales, offers, product announcements |
AUTHENTICATION |
OTP/verification codes | Login codes, 2FA, password resets |
Create Template
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.",
whatsappCategory: "UTILITY",
variables: ["customer_name", "order_id"],
});
console.log(template.id); // tpl_xxx
Python:
template = zavu.templates.create(
name="order_confirmation",
language="en",
body="Hi {{1}}, your order {{2}} has been confirmed and will ship within 24 hours.",
whatsapp_category="UTILITY",
variables=["customer_name", "order_id"],
)
Template with Buttons
// Quick reply buttons
const template = await zavu.templates.create({
name: "feedback_request",
language: "en",
body: "Hi {{1}}, how was your experience with order {{2}}?",
whatsappCategory: "MARKETING",
variables: ["customer_name", "order_id"],
buttons: [
{ type: "quick_reply", text: "Great!" },
{ type: "quick_reply", text: "Could be better" },
],
});
// URL button
const template = await zavu.templates.create({
name: "track_order",
language: "en",
body: "Hi {{1}}, your order {{2}} has shipped!",
whatsappCategory: "UTILITY",
variables: ["customer_name", "order_id"],
buttons: [
{ type: "url", text: "Track Order", url: "https://example.com/track/{{1}}" },
],
});
// Phone button
const template = await zavu.templates.create({
name: "contact_support",
language: "en",
body: "Need help? Call our support team.",
whatsappCategory: "UTILITY",
buttons: [
{ type: "phone", text: "Call Support", phoneNumber: "+14155551234" },
],
});
OTP Authentication Templates
// Copy code button
const template = await zavu.templates.create({
name: "login_otp",
language: "en",
body: "Your verification code is {{1}}. Do not share this code.",
whatsappCategory: "AUTHENTICATION",
variables: ["otp_code"],
addSecurityRecommendation: true,
codeExpirationMinutes: 5,
buttons: [
{ type: "otp", text: "Copy Code", otpType: "COPY_CODE" },
],
});
// One-tap autofill (Android)
const template = await zavu.templates.create({
name: "login_otp_autofill",
language: "en",
body: "Your verification code is {{1}}.",
whatsappCategory: "AUTHENTICATION",
variables: ["otp_code"],
addSecurityRecommendation: true,
codeExpirationMinutes: 10,
buttons: [
{
type: "otp",
text: "Autofill",
otpType: "ONE_TAP",
packageName: "com.example.app",
signatureHash: "abc123hash",
},
],
});
Submit for Meta Approval
Templates must be approved by Meta before use:
// Submit template for review
const submitted = await zavu.templates.submit({
templateId: "tpl_abc123",
senderId: "snd_abc123",
category: "UTILITY",
});
console.log(submitted.status); // "pending"
Track approval via webhooks (template.status_changed event) or polling:
const template = await zavu.templates.get({ templateId: "tpl_abc123" });
console.log(template.status); // draft | pending | approved | rejected
Send Template Message
await zavu.messages.send({
to: "+14155551234",
messageType: "template",
content: {
templateId: "tpl_abc123",
templateVariables: { "1": "John", "2": "ORD-12345" },
},
});
Python:
zavu.messages.send(
to="+14155551234",
message_type="template",
content={
"templateId": "tpl_abc123",
"templateVariables": {"1": "John", "2": "ORD-12345"},
},
)
Template Lifecycle
draft -> pending (submitted to Meta) -> approved (ready to use)
-> rejected (edit and resubmit)
Other Operations
// List templates
const templates = await zavu.templates.list({ limit: 50 });
for (const tpl of templates.items) {
console.log(tpl.id, tpl.name, tpl.status);
}
// Get template
const tpl = await zavu.templates.get({ templateId: "tpl_abc123" });
// Delete template (draft only)
await zavu.templates.delete({ templateId: "tpl_abc123" });
Constraints
- Template names: lowercase, underscores only (e.g.,
order_confirmation) - Variables use positional format:
{{1}},{{2}},{{3}} - Max 3 buttons per template
- Button text: max 25 characters
- OTP
ONE_TAPrequires AndroidpackageNameandsignatureHash addSecurityRecommendationonly for AUTHENTICATION templatescodeExpirationMinutes: 1-90, only for AUTHENTICATION- Meta approval typically takes minutes to hours, but can take up to 24h
- Rejected templates can be edited and resubmitted
Weekly Installs
3
Repository
zavudev/zavu-skillsFirst Seen
5 days ago
Security Audits
Installed on
opencode3
gemini-cli3
github-copilot3
codex3
kimi-cli3
cursor3