skills/zavudev/zavu-skills/whatsapp-templates

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_TAP requires Android packageName and signatureHash
  • addSecurityRecommendation only for AUTHENTICATION templates
  • codeExpirationMinutes: 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
First Seen
5 days ago
Installed on
opencode3
gemini-cli3
github-copilot3
codex3
kimi-cli3
cursor3