Skip to main content

Sending WhatsApp messages

Send WhatsApp with the same POST /messages as SMS, with channel set to WHATSAPP. What you can send depends on when the customer last wrote to you.

You need

  • An API key with the Messaging API turned on. See API keys and base URLs.
  • A WhatsApp number: your sandbox WhatsApp number, or one you connected in live. Its number is the sender.
  • An approved template, to start a conversation. See Templates.

The 24-hour window​

The 24-hour customer service window opens each time a customer writes to you, and closes 24 hours after their last message.

In a WhatsApp thread, the customer replies to a template, which opens the 24-hour window, and the team's free-form reply is sent.
after 24 hoursCUSTOMER WRITESWINDOW OPENfree-form repliesWINDOW CLOSEDtemplates only
Every new message from the customer restarts the 24 hours. To start a conversation, or after the window closes, send an approved template.
  • Inside the window, reply with text, a file, buttons or a list. Each reply is charged at the reply price.
  • Outside the window, or to start a conversation, send an approved template. It's charged at its category's price.

Send a template​

curl -X POST $PONITOR_BASE_URL/messaging/v1/messages \
-H "apiKey: $PONITOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sender": "+231770000000",
"channel": "WHATSAPP",
"recipient": "+231770123456",
"externalId": "remind-0412",
"template": {
"id": "6f1c2a3e-8b4d-4e5f-9a1b-2c3d4e5f6a7b",
"body": ["Blama", "LRD 4,500", "18 June"]
}
}'

For a template approved as Hi {{1}}, your repayment of {{2}} is due {{3}}., the customer gets Hi Blama, your repayment of LRD 4,500 is due 18 June.

FieldWhat to send
template.idThe Template ID from the template's page in WhatsApp › Templates. It must be approved, and belong to the WhatsApp account of the number you send from.
template.bodyThe values for {{1}}, {{2}} and so on, in order, as text. Up to 20 values of up to 1,024 characters each. Leave it out if the template has no placeholders.
template.buttonsThe values for the buttons' placeholders, in order, such as the end of a link button's address. Leave it out if the buttons have none.

The header is sent as it was approved. The older templateId with templateParameters still works. To send an SMS when the number isn't on WhatsApp, add smsFallback. See If they're not on WhatsApp.

Read the response​

201 Created means the message is charged and queued for WhatsApp:

{
"message": {
"id": "8d0f3c2a-5b7e-4a91-b6c4-1e2f3a4b5c6d",
"channel": "WHATSAPP",
"direction": "OUTBOUND",
"sender": "+231770000000",
"recipient": "+231770123456",
"status": "QUEUED",
"messageType": "TEMPLATE",
"inServiceWindow": false,
"cost": 0.03,
"externalId": "remind-0412",
"createdAt": "2026-10-05T09:30:00.112Z"
}
}

inServiceWindow says whether it went inside the customer's 24-hour window. 200 OK instead means you already used this externalId, and the body is the original message.

Reply inside the window​

Put your reply in text:

{
"sender": "+231770000000",
"channel": "WHATSAPP",
"recipient": "+231770123456",
"externalId": "support-reply-77",
"text": "Thanks Blama, your refund is on its way."
}

WhatsApp formatting works in text: *bold*, _italic_, ~strikethrough~ and ```monospace```. To send an image, a video, an audio file, a document, a location or contact cards, or to add buttons or a list, see WhatsApp replies.

Customers' messages come to your webhook as message.received events. See Receiving webhooks.

When a send is refused​

StatusWhyFix
400E10006: Free-form WhatsApp messages are only allowed during an active customer service windowThe window is closed. Send a template.
400The template isn't approved, isn't in this number's WhatsApp account (E10005), or has too few or too many values. The message says which.Check the Template ID and the number of values.
400A field is missing or invalid (E01001), or your balance is too low (E03001).Fix the request, or add funds.
401The key is wrong, or it doesn't match the base URL.See API keys and base URLs.
403The Messaging API isn't turned on, or your team isn't approved (E02010).Check Subscribed APIs and Settings › Compliance.
422E10008: the person unsubscribed from your marketing.Don't send them marketing templates. See below.
429Too many requests in a minute (E01011).Wait, then try again. See Rate limits.

Nothing is charged for a refused send.

When someone unsubscribes​

When someone sends your WhatsApp number UNSUBSCRIBE (or STOP), or taps Stop promotions on a marketing template, they're unsubscribed from your team's marketing. The message must be only that word: "How do I unsubscribe?" doesn't count.

  • Marketing templates aren't sent to them. The API answers 422 with the code E10008, and nothing is charged.
  • Authentication and utility templates still go, so they keep getting their codes and order updates.
  • Your replies inside the 24-hour window still go.
  • If they send SUBSCRIBE, they're subscribed again.

Either way, they get a short reply saying so, charged as a reply. See who unsubscribed, and subscribe someone again when they ask, under WhatsApp › Settings.

{
"error": {
"type": "unprocessable_error",
"code": "E10008",
"name": "RecipientOptedOut",
"message": "This number unsubscribed, so marketing templates aren't sent to it. Utility and authentication templates still go.",
"doc_url": "https://docs.ponitor.com/api/errors#E10008",
"request_id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"
}
}

Before codes, this answer had "code": "RECIPIENT_OPTED_OUT" at its top level. It's deprecated and still sent.

WhatsApp statuses​

WhatsApp messages move through the same statuses as SMS (see Delivery statuses), with these differences:

  • There's no EXPIRED. A message that can't reach the phone ends as UNDELIVERED.
  • Read isn't a status. A read message stays DELIVERED.
  • An UNDELIVERED message is charged the lower not-delivered price, and the difference goes back to your balance.
StatusMeaning on WhatsAppCharged?
QueuedPonitor accepted it and is handing it to WhatsApp.Held
SentWhatsApp accepted it.Yes
DeliveredWhatsApp confirmed it reached the phone.Yes
UndeliveredWhatsApp couldn't deliver it, for example to a number that isn't on WhatsApp.The not-delivered price
UnknownNo delivery update arrived within 48 hours. It may have arrived.Yes
FailedIt never reached WhatsApp.No, refunded

An undelivered WhatsApp message says why in failureCode and failedReason. WhatsApp's own reasons are the E111 codes in Errors: E11101 not on WhatsApp, E11103 outside the 24-hour window, E11109 a marketing message held back, and more.