Messages
WhatsApp has two kinds of outgoing message:
| Type | When you can send it | Endpoint |
|---|---|---|
| Template message | Any time. Required for first contact and once the 24-hour window has closed | POST /send-message/{whatsappPhoneId} |
| Session message | Only within 24 hours of the customer’s last message | POST /v1/send-message/{whatsappPhoneId} |
Both endpoints need the /send-message grant. To find whatsappPhoneId, call GET /account/get and read phone_numbers[].whatsappPhoneId.
Send a template message
Section titled “Send a template message”POST /send-message/{whatsappPhoneId}
The template must be APPROVED. If the recipient isn’t a contact yet, Wabot creates one automatically.
| Field | Required | Description |
|---|---|---|
templateName |
Yes | Name of an approved template in your account |
to |
Yes | Recipient phone number with country code, e.g. +919847392342 (the + is optional) |
receipentName |
No | Name used if the contact has to be created. Note the spelling |
variables |
No | Values for the template’s variables. See Variables below |
mediaUrl |
Media headers | Public URL of the image, video or document for the header |
documentName |
No | File name shown for a document header. Default doc |
carouselData |
No | Card data for carousel templates. If you leave it out, the cards saved on the template are used |
callback_url |
No | URL that receives status updates for this message. See Delivery callbacks |
event |
No | Which updates to send to callback_url: any of sent, delivered, read, failed, replied |
To send in bulk, send an array of these objects instead of a single object.
curl -X POST https://api.wabot.shop/send-message/$PHONE_ID \ -H "Authorization: $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "templateName": "order_update", "to": "+919400294110", "receipentName": "Asha", "variables": { "name": "Asha", "custom_order": "#1042" }, "callback_url": "https://example.com/wabot/status", "event": ["delivered", "read", "replied"] }'await fetch(`https://api.wabot.shop/send-message/${phoneId}`, { method: 'POST', headers: { Authorization: token, 'Content-Type': 'application/json' }, body: JSON.stringify({ templateName: 'order_update', to: '+919400294110', receipentName: 'Asha', variables: { name: 'Asha', custom_order: '#1042' }, }),});requests.post( f"https://api.wabot.shop/send-message/{phone_id}", headers={"Authorization": token}, json={ "templateName": "order_update", "to": "+919400294110", "receipentName": "Asha", "variables": {"name": "Asha", "custom_order": "#1042"}, },)Variables
Section titled “Variables”Body variables are filled in the order of the keys in variables. Use these key names:
| Key | Fills |
|---|---|
name, email |
Body variables |
Any key starting with custom (e.g. custom_order) |
Body variables |
cta_link, or cta_link_0 / cta_link1… for several buttons |
The dynamic part of a URL button |
code |
The code in authentication (OTP) templates |
Responses
Section titled “Responses”200: every message was sent.
{ "message": "All messages sent successfully", "results": [ { "success": true, "message": "Message sent successfully", "contact": { "contact_id": 381, "contact_number": "919400294110" } } ]}207: one or more messages failed. Check each item in results. Wabot also returns 207 when a single message fails.
{ "message": "Some messages failed to send", "results": [{ "success": false, "message": "No Template found", "contact": "+919400294110" }]}Send a session message
Section titled “Send a session message”POST /v1/send-message/{whatsappPhoneId}
Free-form text, media or interactive buttons. You can only send these within the 24-hour customer-care window.
| Field | Required | Description |
|---|---|---|
typOfmsg |
Yes | normal_message, quick_reply or cta |
receipentPhone |
Yes | Recipient phone number with country code |
message |
Yes | The text, or the caption for media |
mediaUrl |
No | Public URL of an attachment (normal_message) |
fileType |
With mediaUrl |
image, video or document |
fileName |
No | File name shown for documents |
buttons |
For buttons | quick_reply: [{"text": "Yes"}, {"text": "No"}]. cta: [{"text": "Track order", "url": "https://…"}] (only the first button is used) |
header |
No | For quick_reply / cta: {"type": "text", "text": "…"} or {"type": "image", "url": "…"} (also video, document) |
receipentName, callback_url, event |
No | Same as for template messages |
{ "typOfmsg": "normal_message", "receipentPhone": "+919400294110", "message": "Thanks, your order is on its way!" }{ "typOfmsg": "normal_message", "receipentPhone": "+919400294110", "message": "Here is your invoice", "mediaUrl": "https://example.com/invoice.pdf", "fileType": "document", "fileName": "invoice-1042.pdf"}{ "typOfmsg": "quick_reply", "receipentPhone": "+919400294110", "message": "Was your delivery on time?", "buttons": [{ "text": "Yes" }, { "text": "No" }]}{ "typOfmsg": "cta", "receipentPhone": "+919400294110", "header": { "type": "text", "text": "Order #1042" }, "message": "Your parcel is out for delivery.", "buttons": [{ "text": "Track order", "url": "https://example.com/track/1042" }]}200
{ "success": true, "message": "Message sent to whatsapp successfully!" }If WhatsApp rejects the message, the 500 response’s message contains WhatsApp’s reason. The most common cause is that the 24-hour window has closed; send a template message instead.
Delivery callbacks
Section titled “Delivery callbacks”Add callback_url and event to either send request and Wabot POSTs updates for that message to your URL.
Status update (sent, delivered, read, failed):
{ "status": "delivered", "senderPhoneNumber": "+919400294110" }Customer reply (replied):
{ "message": "Yes, thank you!", "senderPhoneNumber": "+919400294110" }Wabot sends each callback once and doesn’t retry, so make sure your endpoint returns 2xx quickly. To receive events for all messages, use account webhooks instead.
