Text messages
A plain text message is the simplest thing you can send on WhatsApp: one string through a send route — message with an app key, body with your org API key. It's also the message type most constrained by the 24-hour customer service window, so it's the best place to learn that rule.
Send a text message
Post to /api/app-whatsapp/send with a channelId, the recipient's E.164 number in to, and your text in the message field. That's the entire body — no other content field.
curl -X POST https://api.telenow.ai/api/app-whatsapp/send \
-H "Authorization: Bearer vai_app_…" \
-H "Content-Type: application/json" \
-d '{
"channelId": "b1e2c3d4-…",
"to": "+919876543210",
"message": "Hi Asha! Your order #1234 has shipped and will arrive Thursday."
}'
await fetch('https://api.telenow.ai/api/app-whatsapp/send', {
method: 'POST',
headers: {
Authorization: 'Bearer vai_app_…',
'Content-Type': 'application/json',
},
body: JSON.stringify({
channelId: 'b1e2c3d4-…',
to: '+919876543210',
message: 'Hi Asha! Your order #1234 has shipped.',
}),
})
import requests
requests.post(
'https://api.telenow.ai/api/app-whatsapp/send',
headers={'Authorization': 'Bearer vai_app_…'},
json={
'channelId': 'b1e2c3d4-…',
'to': '+919876543210',
'message': 'Hi Asha! Your order #1234 has shipped.',
},
)
{ "success": true, "data": { "wamid": "wamid.HBgLMTQxNTU1MDEwMBUCABIYFj…" } }
message carries plain text. WhatsApp renders its own light formatting (*bold*, _italic_, ~strike~, ```mono```) and makes bare URLs tappable; Telenow sends with link previews off, so no preview card is shown. Keep it under 4,096 characters — WhatsApp's limit. Telenow doesn't pre-check the length; a longer body comes back as WhatsApp's own refusal (502, see Errors).
With an app key, text works on Meta Cloud numbers (native or your own Meta app), and on WhatsApp Web numbers when the app holds the whatsapp:web scope; a partner number (GupShup, Plivo, AiSensy) returns 400 that channel cannot send WhatsApp messages — use your org API key for those.
Get your
channelIdfromGET /api/app-whatsapp/channels— it's theidof the WhatsApp number you connected. See WhatsApp overview.
The returned wamid
Every successful send returns a wamid (WhatsApp message ID). It is the one durable handle on the message, and it's what ties the send to its delivery lifecycle: each whatsapp.message.status webhook you receive carries the same wamid, letting you correlate sent → delivered → read (or failed) back to this exact message. (wamid can be null when the number's provider doesn't return a message id.)
Abridged status event — the full payload is in Webhooks & events:
{
"event": "whatsapp.message.status",
"channelId": "b1e2c3d4-…",
"wamid": "wamid.HBgLMTQxNTU1MDEwMBUCABIYFj…",
"status": "delivered",
"recipient": "+919876543210",
"timestamp": "2026-07-18T09:31:04+00:00"
}
To make retries safe, send an Idempotency-Key header (any unique string, such as a UUID) with the POST. A retry with the same key and the same body within 24 hours returns the original response — marked Idempotent-Replay: true — instead of sending twice. The same key with a different body returns 422; the same key while the first request is still running returns 409. Without the header, dedupe on the returned wamid. See Webhooks & events for the full status payload and signature verification.
Reply to a specific message
To quote a particular message — so it shows as a threaded reply under the message you're answering, just like tapping Reply in the WhatsApp app — add reply_to set to that message's wamid. You get the wamid from the whatsapp.message.received webhook (its wamid field) or from the message history (each message's wamid).
curl -X POST https://api.telenow.ai/api/app-whatsapp/send \
-H "Authorization: Bearer vai_app_…" \
-H "Content-Type: application/json" \
-d '{
"channelId": "b1e2c3d4-…",
"to": "+919876543210",
"message": "Yes — it shipped this morning and arrives tomorrow.",
"reply_to": "wamid.HBgLMTQx…"
}'
{ "success": true, "data": { "wamid": "wamid.HBgLMjE2…" } }
reply_to(camelCasereplyToalso works) is the wamid of the message you're replying to. It's optional — omit it for a normal, unquoted message.- It works with any content type, not just text — add
reply_toalongside amediaId,location,interactive, etc. on/send, and on the org-key…/channels/{channelId}/sendand…/threads/{threadId}/sendroutes. - Quoting works on Meta Cloud numbers (native or your own Meta app). On WhatsApp Web and partner numbers
reply_tois ignored and the message is sent unquoted. If the wamid isn't a real message in that conversation, WhatsApp ignores the quote and still delivers the message.
The 24-hour window
You can only send free-form text — this endpoint's message field — inside the 24-hour customer service window: the 24 hours that follow the customer's most recent inbound message. Every inbound message from that customer resets the clock.
Outside the window there is no open conversation to reply into, so free-form text is blocked and you must re-open the thread with an approved template message. WhatsApp reports a closed window (Meta code 131047) in one of two ways:
- Right away — Telenow returns
400with a plain-English error (no code number in the body):
{ "success": false, "error": "This contact hasn't messaged you in 24 hours — send an approved template to reopen the conversation." }
- After accepting the message — the send succeeds, then a
whatsapp.message.statusevent arrives withstatus: "failed"and the code in itserrors.
Handle either by falling back to a template; once the customer replies to it, the window re-opens and free-form text works again.
| Situation | What you can send |
|---|---|
| Within 24h of the customer's last inbound message | Free-form text (this page), media, interactive, etc. |
| Outside the 24h window | An approved template only |
With your org API key
With your org API key (X-API-Key: vai_live_…) the channel goes in the path and the text field is body, not message:
curl -X POST https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/channels/{channelId}/send \
-H "X-API-Key: vai_live_…" \
-H "Content-Type: application/json" \
-d '{ "to": "+919876543210", "body": "Hi Asha! Your order #1234 has shipped." }'
{ "success": true, "data": { "wamid": "wamid.HBgLMTQxNTU1MDEwMBUCABIYFj…" } }
- Reply inside a conversation without repeating the number:
POST /api/orgs/{orgId}/whatsapp-hub/threads/{threadId}/sendwith{ "body": "…" }. ThethreadIdis in everywhatsapp.message.receivedevent, and this route also reaches WhatsApp Web chats where WhatsApp hides the customer's number (@lidchats). - Every number in your inbox takes text this way — Meta Cloud, partner numbers (GupShup, Plivo, AiSensy) and WhatsApp Web.
reply_toand the 24-hour rule work as above. The key needs theowner,adminordeveloperrole.- Sending
messagehere (orbodyon the app-key route) is ignored, and the request fails with400send exactly one of body, mediaId, location, reaction, contacts or interactive.
Related
- Sending template messages — re-open a thread outside the 24-hour window.
- Media messages — images, documents, audio and video.
- Interactive messages — reply buttons, lists, and CTA URLs.
- Webhooks & events — track delivery with
whatsapp.message.status. - WhatsApp overview — connect a number and find your
channelId.