Skip to content
Wazapin
Esc
navigateopen⌘Jpreview
On this page

Send template

Send approved template notifications (order updates, reminders).

Use templates when you need to reach out first — order updates, OTP codes, appointment reminders — especially outside the 24-hour reply window. Each template is pre-approved by Meta.

A template send needs more than name and language. Pass components that match how the template was built: body variables, optional header image or text, and button URL parameters when the template defines them.

Before you send

Create and approve the template

Create the template in the Wazapin app or sync from Meta on official channels. Status must be approved.

GET /v1/templates lists templates for your workspace. See Channel support for official vs unofficial behavior.

Read the template structure

Open the template in the app and note:

  • Header — none, text ({{1}}), image, video, or document
  • Body — static text with {{1}}, {{2}}, … placeholders
  • Buttons — quick reply, URL (may include {{1}} in the link), copy code, etc.

Your components array must mirror these sections in order.

Build the components array

Each section becomes one object in content.template.components:

Component type When required
header Template has a dynamic header (text, image, video, document)
body Template body has {{n}} variables
button URL or other dynamic button parameters (sub_type, index)

Omit a section if the template has no variables in that part.

Request shape

All template sends use POST /v1/messages with type: "template" and a nested content.template object (Meta-compatible shape).

Field Required Description
channel_id Yes Connected WhatsApp channel
to Yes Recipient phone (international format)
type Yes template
content.template.name Yes Approved template name
content.template.language.code Yes Locale, e.g. en_US, id
content.template.components Often Parameters per header/body/button

Example: body variables only

Template body: Hi {{1}}, your order {{2}} is on the way.

curl -X POST "https://api.wazapin.com/v1/messages" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "wzp_abc123",
    "to": "6281234567890",
    "type": "template",
    "content": {
      "template": {
        "name": "order_shipped",
        "language": { "code": "en_US" },
        "components": [
          {
            "type": "body",
            "parameters": [
              { "type": "text", "text": "John" },
              { "type": "text", "text": "ORD-42" }
            ]
          }
        ]
      }
    }
  }'
import { WazapinClient, templateMessage } from "@wazapin/sdk";

const wazapin = new WazapinClient({ apiKey: process.env.WAZAPIN_API_KEY! });

const { data: message } = await wazapin.messages.send(
  templateMessage({
    channel_id: "wzp_abc123",
    to: "6281234567890",
    name: "order_shipped",
    language: "en_US",
    components: [
      {
        type: "body",
        parameters: [
          { type: "text", text: "John" },
          { type: "text", text: "ORD-42" },
        ],
      },
    ],
  }),
);

console.log(message.id);
import requests

response = requests.post(
    "https://api.wazapin.com/v1/messages",
    headers={"X-Api-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
    json={
        "channel_id": "wzp_abc123",
        "to": "6281234567890",
        "type": "template",
        "content": {
            "template": {
                "name": "order_shipped",
                "language": {"code": "en_US"},
                "components": [
                    {
                        "type": "body",
                        "parameters": [
                            {"type": "text", "text": "John"},
                            {"type": "text", "text": "ORD-42"},
                        ],
                    }
                ],
            }
        },
    },
    timeout=30,
)
response.raise_for_status()
print(response.json())

Example: header image + body

Template with an image header and one body variable.

{
  "channel_id": "wzp_abc123",
  "to": "6281234567890",
  "type": "template",
  "content": {
    "template": {
      "name": "promo_with_image",
      "language": { "code": "id" },
      "components": [
        {
          "type": "header",
          "parameters": [
            {
              "type": "image",
              "image": { "link": "https://cdn.example.com/promo.jpg" }
            }
          ]
        },
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Ramadan Sale" }
          ]
        }
      ]
    }
  }
}

Example: header text variable

Template header text: Hello {{1}} — the header component lives inside content.template.components.

{
  "channel_id": "wzp_abc123",
  "to": "6281234567890",
  "type": "template",
  "content": {
    "template": {
      "name": "greeting_header",
      "language": { "code": "en_US" },
      "components": [
        {
          "type": "header",
          "parameters": [
            { "type": "text", "text": "John" }
          ]
        },
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Your appointment is confirmed." }
          ]
        }
      ]
    }
  }
}

Example: dynamic URL button

Template with a URL button containing {{1}} in the path — button component nested in the same components array.

{
  "channel_id": "wzp_abc123",
  "to": "6281234567890",
  "type": "template",
  "content": {
    "template": {
      "name": "order_tracking",
      "language": { "code": "en_US" },
      "components": [
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "John" },
            { "type": "text", "text": "ORD-42" }
          ]
        },
        {
          "type": "button",
          "sub_type": "url",
          "index": "0",
          "parameters": [
            { "type": "text", "text": "ORD-42" }
          ]
        }
      ]
    }
  }
}

index is the zero-based button index in the template definition. sub_type matches the button type Meta approved (url, quick_reply, copy_code, etc.).

List and sync templates with wazapin.templates.list() and wazapin.templates.sync(). See SDK templates (advanced).

Common mistakes

Mistake Fix
Template not approved Wait for Meta approval or pick another name
Wrong language.code Must match the template locale exactly (en_US vs en)
Missing components Add parameters for every {{n}} in header/body/buttons
Flat template_name in content Use nested content.template.name
Header image URL not HTTPS Use a public HTTPS URL Meta can fetch

Was this page helpful?