Send a Message
The 24-hour rule
Section titled “The 24-hour rule”WhatsApp only allows free-form text within 24 hours of the customer’s last message. Outside that window (or to start a fresh conversation), you must send an approved template.
Whatbot checks this before calling WhatsApp. If the window is shut and you
asked for text or media, you get a 409 naming the problem rather than a message
that quietly never arrives:
{ "detail": { "error": "window_closed", "require_template": true, "last_inbound_at": "2026-08-01T09:00:00Z", "message": "Outside the 24-hour window — a free-form message will not be delivered. Send an approved template, or pass 'fallback_template_name' to fall back to one automatically." }}Call Messaging Window first if you want to know before you send.
Let whatbot fall back for you
Section titled “Let whatbot fall back for you”Pass fallback_template_name alongside a text or media send. Inside the window
your actual message goes out; outside it, the template goes instead — one call
either way. The response’s delivered_as tells you which actually happened.
curl -X POST https://api.whatbot.in/public/v1/messages \ -H "X-API-Key: wa_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "to": "9876543210", "type": "text", "body": "Here is the brochure we discussed.", "fallback_template_name": "voice_call_followup", "fallback_components": [ { "type": "body", "parameters": [ { "type": "text", "text": "Ravi" } ] } ] }'This matters when you cannot know the window state in advance — an automated caller messaging someone who may or may not have written to you before.
The fallback fires on either of two signals, so a caller gets one call either way even when we cannot look the window up:
- the window is known to be shut, in which case the free-form send is never attempted; or
- the free-form send was attempted and WhatsApp refused it as out-of-window (error 131047) — which is what happens when the window lookup itself fails, or when the window closed between the lookup and the send.
Only 131047 triggers it. A template is exempt from the 24h rule, so substituting one for any other failure would send unrelated billable marketing in place of your message, and report it as a window problem.
Read delivered_as and template_name in the response to say something
truthful about what the customer actually received.
Send a template
Section titled “Send a template”Use this to start a conversation or message outside the 24h window.
curl -X POST https://api.whatbot.in/public/v1/messages \ -H "X-API-Key: wa_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "to": "9876543210", "type": "template", "template_name": "order_update", "language_code": "en", "components": [ { "type": "body", "parameters": [ { "type": "text", "text": "Ravi" } ] } ] }'Send a text (inside the 24h window)
Section titled “Send a text (inside the 24h window)”curl -X POST https://api.whatbot.in/public/v1/messages \ -H "X-API-Key: wa_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "to": "9876543210", "type": "text", "body": "Thanks! Your order ships today." }'Send media (image, PDF, video, audio)
Section titled “Send media (image, PDF, video, audio)”Set type to image, document, video, or audio and pass a public
media_url — Whatbot hands the link to WhatsApp, which fetches it (no upload
step). The file must be reachable over public HTTPS and within WhatsApp’s media
size limits for that type. Like text, media is a service message — it delivers
inside the 24-hour window; outside it, send a template with a media header
instead.
Send a PDF (document):
curl -X POST https://api.whatbot.in/public/v1/messages \ -H "X-API-Key: wa_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "to": "9876543210", "type": "document", "media_url": "https://example.com/invoices/INV-1042.pdf", "filename": "Invoice INV-1042.pdf", "caption": "Your invoice" }'Send an image:
curl -X POST https://api.whatbot.in/public/v1/messages \ -H "X-API-Key: wa_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "to": "9876543210", "type": "image", "media_url": "https://example.com/photos/site.jpg", "caption": "Site photo" }'type: "video" and type: "audio" work the same way (video takes an optional
caption; audio takes neither caption nor filename).
Sending from a specific number
Section titled “Sending from a specific number”A workspace can hold several WhatsApp numbers. Pass from to choose which one
sends — either the number itself in any format, or its WhatsApp phone number ID
(the phone_number_id that arrives on message.received).
Leave it out to send from the workspace’s default number.
curl -X POST https://api.whatbot.in/public/v1/messages \ -H "X-API-Key: wa_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "to": "9876543210", "from": "+91 78100 83015", "type": "text", "body": "Hi from our Chennai store" }'A from that isn’t one of this workspace’s numbers — or one that has been
disconnected — returns 400. It never silently falls back to the default number.
Body fields
Section titled “Body fields”| Field | Type | Required | Description |
|---|---|---|---|
| to | string | Yes | Destination phone, any format (normalized to E.164). An invalid number returns 422. |
| from | string | Which of your numbers sends: the number in any format, or its phone number ID. Defaults to the workspace’s default number. | |
| type | string | text, template, image, document, video, or audio. Defaults to text. Any other value is treated as text. | |
| body | string | The message text. Required when type is text. | |
| media_url | string | Public HTTPS URL of the file. Required when type is image/document/video/audio. | |
| caption | string | Optional caption for image/video/document. | |
| filename | string | Optional display filename for document (e.g. Invoice.pdf). | |
| template_name | string | The approved template’s name. Required when type is template. | |
| language_code | string | Template language, e.g. en, en_US. Defaults to en. | |
| components | array | Template variable values (header/body/button parameters), per the WhatsApp template component format. | |
| name | string | Optional contact name for the conversation. If given, it also replaces the name shown on an existing conversation. | |
| fallback_template_name | string | Template to send instead when a free-form message will not be delivered — either because the window is known to be shut, or because WhatsApp rejects the send as out-of-window (error 131047). Not consulted for an explicit type: "template" send. | |
| fallback_language_code | string | Language for the fallback template. Defaults to en. | |
| fallback_components | array | Variable values for the fallback template. |
Response
Section titled “Response”| Field | Type | Required | Description |
|---|---|---|---|
| message_id | string | Whatbot’s id for the message row. | |
| wa_message_id | string | WhatsApp’s wamid, once accepted. | |
| status | string | sent once WhatsApp accepted it. Later delivery states arrive on the message.status webhook. | |
| conversation_id | string | The conversation it was recorded on. | |
| delivered_as | string | What actually went out — your type, or template if the fallback fired. | |
| window_open | boolean | Whether the 24h window was open. null for an explicit template send, where it is not checked, and when the window lookup failed and the message was sent anyway. | |
| template_name | string | Present only when the fallback fired. |
{ "message_id": "b1f0...", "wa_message_id": "wamid.HBg...", "status": "sent", "conversation_id": "a5230fa7-...", "delivered_as": "text", "window_open": true}Read delivered_as on a success to tell what actually went out: text means your
message was sent, template means the window was shut and the fallback template
went instead. The two are identical on status alone.
Errors
Section titled “Errors”| Status | Cause |
|---|---|
400 | from is not one of this workspace’s numbers, or is disconnected |
401 | Missing/invalid API key |
402 | Not enough prepaid wallet balance (error: "insufficient_balance", with balance, required, currency), or the workspace’s plan is not active. Nothing was sent. |
409 | window_closed — a text/media send outside the 24-hour window with no fallback_template_name |
422 | Invalid to; body missing for text; template_name missing for a template; media_url missing for media. Checked before the window, so a malformed request fails the same way whatever the window state. |
424 | The workspace has no WhatsApp number connected |
502 | WhatsApp rejected the message (send_failed / fallback_template_failed) |