Skip to main content

Sending WhatsApp Template Messages via API

Send a pre-approved WhatsApp template to a phone number or a Business-Scoped User ID (BSUID) over HTTPS, from any backend that can make a

Written by Tarek Khalil

Endpoint

POST https://app.octopods.io/api/v1/whatsapp/templates/{template_id}/messages

  • {template_id} is the ID of the approved WhatsApp template you want to send.

  • Authentication: X-Octopods-Auth: YOUR_WHATSAPP_API_KEY (see API Overview and Authentication).

  • Content type: application/json.

Finding a template ID

Templates must be approved on the WhatsApp channel before they can be sent. Each approved template has a numeric ID you can copy from the Octopods UI:

  1. Open Settings → Channels and select your WhatsApp channel.

  2. Open the Templates tab.

  3. Click the template you want to send. The ID appears in the template details.

Request body

Identify the recipient with either destination_phone or destination_user_id — supply exactly one. If both are omitted, the request is rejected with error code 1.

Field

Type

Required

Description

destination_phone

string

Conditional

Recipient phone in E.164 format, e.g. +14155552671. Required unless you supply destination_user_id.

destination_user_id

string

Conditional

Business-Scoped User ID (BSUID) for a WhatsApp lead with no phone number on file, e.g. US.13491208655302741918. Required unless you supply destination_phone. A malformed value returns error code 11.

message_variables

object or array

Conditional

Values for the template’s placeholders. Required when the template has variables. See the format details below.

header_attachment_url

string

Conditional

Public URL of the header media file. Required when the template has an image, video, or document header.

destination_user_name

string

No

Display name to associate with the contact if one does not already exist.

open_intercom_conversation

boolean

No

Set to true to open a CRM conversation thread when the message is sent. Defaults to false. Accepts true/false, 1/0, yes/no, on/off.

intercom_teammate_id

string

No

The ID of the teammate the sent message should be attributed to.

Message variable formats

The template determines the shape you must send.

Body-only templates. If every placeholder lives in the template body ({{1}}, {{2}}, …), send an array of strings:

{
  "destination_phone": "+14155552671",
  "message_variables": ["Alex", "1234"]
}

Templates with header, footer, or button placeholders. Send an object with one array per section. Include every section even if it is empty:

{
  "destination_phone": "+14155552671",
  "message_variables": {
    "header": ["Order #1234"],
    "body":   ["Alex", "1234"],
    "footer": [],
    "buttons": ["track/1234"]
  }
}

If the template has non-body placeholders and you send a plain array, the API rejects the request with error code 9.

Media headers

For templates with an image, video, or document header, provide a public URL in header_attachment_url. The URL must be reachable by Octopods’s servers and must point to a file that matches the template’s declared header type.

{
  "destination_phone": "+14155552671",
  "header_attachment_url": "https://example.com/invoice.pdf",
  "message_variables": { "header": [], "body": ["Alex"], "footer": [], "buttons": [] }
}

Full example

curl -X POST "https://app.octopods.io/api/v1/whatsapp/templates/123/messages" \
  -H "X-Octopods-Auth: YOUR_WHATSAPP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "destination_phone": "+14155552671",
    "destination_user_name": "Alex Rivera",
    "message_variables": ["Alex", "1234"],
    "open_intercom_conversation": true
  }'

Successful response

HTTP 201 Created:

{
  "request_id": "abc123…",
  "message_id": 98765,
  "channel_message_id": "provider-id-here"
}

  • message_id — use this value with GET /api/v1/whatsapp/messages/{message_id} to poll delivery status.

  • channel_message_id — the WhatsApp provider’s own ID.

Error codes

Errors return HTTP 400 Bad Request (or HTTP 429 for rate-limit breaches) with:

{ "request_id": "…", "error_code": N, "error": "…" }

Code

Meaning

Fix

1

A required argument is missing (e.g. destination_phone or destination_user_id, waba_template_id, header_attachment_url).

Include the named field.

2

message_variables is the wrong type.

Send an array for body-only templates or an object for templates with non-body placeholders.

3

Template does not exist or is not approved on this channel.

Re-check the template ID and confirm it is in the Approved state.

4

The number of variables you supplied does not match the template.

Count the placeholders in the template and supply exactly that many.

5

destination_phone is invalid.

Use E.164 format (leading +, country code, no spaces).

6

Deprecated API key.

Copy the current key from the channel settings screen.

7

WhatsApp provider returned an error.

See the error field; common causes are “recipient not on WhatsApp”, template paused, or a rate limit at the provider.

8

Invalid header media URL.

Confirm the URL is public and the file matches the header’s declared type.

9

Legacy variable format — an array was sent for a template that has header/footer/button variables.

Send message_variables as an object with per-section arrays.

11

destination_user_id is not a valid Business-Scoped User ID (BSUID).

Confirm the value matches the BSUID format Octopods returned for this lead.

Note: Full details and recovery steps for provider errors are in Troubleshooting Failed Proactive Messages.

Rate limits

WhatsApp endpoints are rate-limited per channel. On a breach, Octopods returns HTTP 429 with a blocked_until timestamp telling you when the block lifts. Pause sends until the timestamp passes.


What’s next

Did this answer your question?