Skip to main content
POST
/
send-whatsapp-template
Send WhatsApp template
curl --request POST \
  --url https://api.sagepilot.ai/send-whatsapp-template \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: application/json' \
  --header 'X-SP-Workspace-Id: <x-sp-workspace-id>' \
  --data '
{
  "channel_id": "<string>",
  "customer_phone": "<string>",
  "message_type": "<string>",
  "template_name": "<string>",
  "customer_name": "<string>",
  "parameter_type": "<string>",
  "parameters": {}
}
'
{
  "message_id": "0fa3bc4b-50b0-446c-842f-cc7b36f57151",
  "success": true
}
Use this endpoint to send an approved WhatsApp template from one of your connected WhatsApp channels to a customer. This endpoint uses the legacy template-send contract. You pass the template name and a Meta-style parameters component list.
Marketing templates may require the recipient to start or reopen a WhatsApp conversation with your business before testing. Ask the test recipient to send a message such as Hi to your connected WhatsApp number first.

Required access

AuthenticationRequired headers
Legacy workspace API keyAuthorization: Bearer <legacy_workspace_api_key> and X-SP-Workspace-Id: <workspace_id>.

Headers

Authorization
string
required
Bearer token using the legacy workspace API key.
X-SP-Workspace-Id
string
required
Workspace ID for the request. This header is required so Sagepilot can resolve the workspace, channel, template, and customer record before sending the WhatsApp template.
Send the workspace ID in the X-SP-Workspace-Id header. Do not send it as workspace_id inside the JSON body.

Before you send

1

Get your workspace API details

In Sagepilot, go to Settings > API Details. Copy your workspace ID and generate or copy a legacy workspace API key.
2

Choose the WhatsApp channel

Use the channel_id for the WhatsApp number you want to send from. Each connected number has its own channel ID.
3

Confirm the approved template name

Use the template name exactly as it appears in Sagepilot or Meta, for example checkout_1. Template names are case-sensitive.
4

Map every template variable

For each {{1}}, {{2}}, or media/button placeholder in the template, add the matching entry in parameters.
5

Send to a phone number with country code

Send customer_phone as digits only with the country code first, such as 918888888888 for India or 14155550123 for the United States.
6

Validate required fields before testing

Confirm that X-SP-Workspace-Id, customer_name, customer_phone, channel_id, template_name, parameter_type, and parameters are present before sending the request.

Body

channel_id
string
required
WhatsApp channel UUID from Settings > API Details > Channels. This decides which connected WhatsApp number sends the message.
customer_phone
string
required
Destination phone number with country code at the start. Use digits only. Do not include +, spaces, brackets, or hyphens.Examples: 918888888888, 14155550123, 447700900123.
message_type
string
default:"template"
required
Must be template.
template_name
string
required
Approved WhatsApp template name. Use the exact name from Sagepilot or Meta.
customer_name
string
required
Customer name to associate with the recipient. This is required for the legacy send flow because Sagepilot creates or updates the customer record before queueing the WhatsApp template.This does not automatically fill a template variable unless you also pass the same value in parameters.
parameter_type
string
default:"list"
required
Must be list. This tells Sagepilot that parameters is already in Meta’s positional component format.
parameters
object
required
Meta-style template component payload. Supported component types include body, header, and button.For a body template such as Hi {{1}}, pass:
[
  {
    "type": "body",
    "parameters": [
      { "type": "text", "text": "Ankita" }
    ]
  }
]
For an image header and one body variable, pass:
[
  {
    "type": "header",
    "parameters": [
      {
        "type": "image",
        "image": {
          "link": "https://example.com/product-image.png"
        }
      }
    ]
  },
  {
    "type": "body",
    "parameters": [
      { "type": "text", "text": "Ankita" }
    ]
  }
]

Phone number format

Always include the country code at the start of customer_phone.
Customer locationCorrectIncorrect
India9188888888888080365185, +91 8080365185
United States141555501234155550123, +1 (415) 555-0123
United Kingdom44770090012307700900123, +44 7700 900123
If the phone number is missing the country code, WhatsApp cannot reliably route the message.

How template variables map

WhatsApp templates use positional placeholders such as {{1}}, {{2}}, and {{3}}. The API does not use the placeholder names from your internal systems. It uses component order.

Body text variables

For this template body:
Hi {{1}}, your order {{2}} is ready.
Send this body component:
{
  "type": "body",
  "parameters": [
    { "type": "text", "text": "Ankita" },
    { "type": "text", "text": "#1001" }
  ]
}
Ankita fills {{1}}. #1001 fills {{2}}.

Header media variables

If the template has an image header, send:
{
  "type": "header",
  "parameters": [
    {
      "type": "image",
      "image": {
        "link": "https://example.com/product-image.png"
      }
    }
  ]
}
For a document header, use document instead:
{
  "type": "header",
  "parameters": [
    {
      "type": "document",
      "document": {
        "link": "https://example.com/invoice.pdf"
      }
    }
  ]
}
The media URL must be publicly accessible by WhatsApp.

Dynamic URL buttons

If the template has a URL button with a dynamic placeholder, add a button component.
{
  "type": "button",
  "sub_type": "url",
  "index": 0,
  "parameters": [
    {
      "type": "text",
      "text": "https%3A%2F%2Fstore.example.com%2Fcart%3Fid%3Dtest123"
    }
  ]
}
Use index: 0 for the first button, index: 1 for the second button, and so on. For Sagepilot CTA buttons such as https://app.sagepilot.ai/cta?redirect={{1}}, pass only the encoded destination URL as the button text. Do not pass the full Sagepilot CTA wrapper URL.

Complete example

This example sends an abandoned checkout template with:
  • An image header.
  • One body variable for the customer name.
  • One dynamic URL button for the checkout link.
curl --request POST \
  --url "https://api.sagepilot.ai/send-whatsapp-template" \
  --header "Authorization: Bearer <legacy_workspace_api_key>" \
  --header "X-SP-Workspace-Id: <workspace_id>" \
  --header "Content-Type: application/json" \
  --data '{
    "channel_id": "<channel_id_uuid>",
    "customer_phone": "918888888888",
    "message_type": "template",
    "template_name": "checkout_1",
    "customer_name": "Ankita",
    "parameter_type": "list",
    "parameters": [
      {
        "type": "header",
        "parameters": [
          {
            "type": "image",
            "image": {
              "link": "https://example.png"
            }
          }
        ]
      },
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "Ankita"
          }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": 0,
        "parameters": [
          {
            "type": "text",
            "text": "https%3A%2F%2Fstore.example.com%2Fcart%3Fid%3Dtest123"
          }
        ]
      }
    ]
  }'

OTP / authentication template example

Use this shape for authentication templates that send a one-time password and include a Copy Code button. For example, the approved authentication template otp_authentication expects the OTP in the body and in the OTP button parameter. Use the same code in both places.
curl --request POST \
  --url "https://api.sagepilot.ai/send-whatsapp-template" \
  --header "Authorization: Bearer <legacy_workspace_api_key>" \
  --header "X-SP-Workspace-Id: <workspace_id>" \
  --header "Content-Type: application/json" \
  --data '{
    "channel_id": "<whatsapp_channel_id>",
    "customer_phone": "918888888888",
    "message_type": "template",
    "template_name": "otp_authentication",
    "customer_name": "Ankita",
    "parameter_type": "list",
    "parameters": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "123456"
          }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": 0,
        "parameters": [
          {
            "type": "text",
            "text": "123456"
          }
        ]
      }
    ]
  }'

Body-only example

Use this shape when the template has only body text placeholders and no header media or buttons.
curl --request POST \
  --url "https://api.sagepilot.ai/send-whatsapp-template" \
  --header "Authorization: Bearer <legacy_workspace_api_key>" \
  --header "X-SP-Workspace-Id: <workspace_id>" \
  --header "Content-Type: application/json" \
  --data '{
    "channel_id": "<whatsapp_channel_id>",
    "customer_phone": "918888888888",
    "message_type": "template",
    "template_name": "order_shipped_3291",
    "customer_name": "Anushka Pawar",
    "parameter_type": "list",
    "parameters": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "Anushka" },
          { "type": "text", "text": "#1234" },
          { "type": "text", "text": "Rs. 100" },
          { "type": "text", "text": "https://sagepilot.ai" }
        ]
      }
    ]
  }'

Successful response

{
  "message_id": "0fa3bc4b-50b0-446c-842f-cc7b36f57151",
  "success": true
}

Common errors

ErrorWhat it meansHow to fix it
Template <name> not foundThe template name does not exist for the selected channel or workspace.Confirm the exact template_name, channel_id, and X-SP-Workspace-Id.
Missing workspace IDThe legacy route cannot resolve the workspace context.Send X-SP-Workspace-Id as a request header, not as a body field.
Missing customer nameThe legacy route creates or updates a customer profile before queueing the template.Send customer_name in the request body.
Missing or invalid phone numbercustomer_phone is empty or not routable.Pass digits only with country code at the start.
Template variable mismatchThe template has placeholders that are missing from parameters, or the order is wrong.Match each Meta component and placeholder in order.
Media cannot be fetchedWhatsApp cannot access the header media URL.Use a public HTTPS URL for image, video, or document media.
Marketing template not received during testingThe recipient may not have an open WhatsApp conversation with the business.Ask the recipient to message your business number first, then retry.

Meta template component reference

The parameters array follows Meta’s WhatsApp template component structure. Refer to Meta’s WhatsApp template documentation when mapping body placeholders, media headers, and URL buttons: