AI agent, auto-reply & calling
Bind one of your voice AI agents to a WhatsApp number and it can reply to messages automatically and answer WhatsApp voice calls. Both are configured per channel. Auto-reply works on every number in your inbox; calling needs a native WhatsApp number or a Plivo WhatsApp number. This page covers turning them on, the requirements, and the APIs.
The API routes here are on the org surface: use your org API key (X-API-Key: vai_live_…) or a dashboard login. App keys have no agent or calling routes. Changes need an owner, admin or developer key.
AI auto-reply
When a customer messages your number, the bound agent generates and sends a reply — no human needed. You can pause the AI on any single conversation for a human to take over, then resume.
Turn it on
In the dashboard: open Communicate → WhatsApp, pick the channel, and in the agent bar choose an answering agent, then toggle AI on. Owners and admins only.
Over the API (the key's creator must be an owner or admin):
curl -X PUT https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/channels/{channelId}/agent \
-H "X-API-Key: vai_live_…" \
-H "Content-Type: application/json" \
-d '{ "agent_id": "a1b2c3d4-…", "ai_enabled": true, "agent_opener": "Hi! I'\''m the Acme assistant — how can I help?" }'
{ "success": true }
| Field | Type | Required | Notes |
|---|---|---|---|
agent_id | uuid | to enable AI | the agent that answers; must belong to your org (404 agent not found in this workspace otherwise). A realtime-only (speech-to-speech) agent can't answer text and returns 400 |
ai_enabled | bool | — | default false; forced false when no agent is bound |
agent_opener | string | — | optional greeting sent first on a new conversation; blank clears it |
The PUT replaces the whole binding: leaving out agent_id unbinds the agent, and leaving out agent_opener clears the greeting — send all three each time.
Requirement: auto-reply runs only when the platform flag
FEATURE_WHATSAPP_AGENTis on and the channel has an agent bound withai_enabled: true. Text, image and video captions, and button or list taps trigger a reply; voice-note transcription isn't built yet, so a customer's voice note doesn't. A reply is also skipped when your workspace's balance can't cover it.
Pause AI on one conversation
Hand a single thread to a human (and resume later) without unbinding the agent:
curl -X PUT https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/threads/{threadId}/pause \
-H "X-API-Key: vai_live_…" \
-H "Content-Type: application/json" \
-d '{ "paused": true }'
paused is required; the response is { "success": true }. Any org member can pause/resume (with a key, it must be a writing key — not viewer). In the dashboard this is the Agent reply switch in the conversation header: off pauses the AI on that conversation, on resumes it. To hand a conversation to a specific person, see assigning threads.
How it works
An inbound message (fresh, within 24 hours) that is real user text runs the bound agent on that conversation and sends its reply back — the reply shows in the shared inbox tagged AI, and it fires the normal whatsapp.message.status events. While the agent composes, a typing indicator is shown to the customer.
WhatsApp Calling
WhatsApp lets customers place a voice call to your business number. With calling enabled, your voice AI agent answers the call — the same agent stack you use for phone calls, bridged to WhatsApp over WebRTC. Calls are logged, and a call that can't be answered is cleanly rejected rather than left ringing into dead air.
Requirements (mandatory)
Calling needs more than the messaging setup. All of these must be in place:
| Requirement | What / who |
|---|---|
| A native WhatsApp channel | telenow_whatsapp_cloud (the recommended connection). A Plivo WhatsApp number also works — see the note below. Bring-your-own Meta, GupShup, AiSensy and WhatsApp Web numbers return 400 with the reason |
| An answering agent bound to the channel | the voice agent that picks up |
| A messaging limit of 2,000/24 h or higher | yours — it's your business portfolio's limit, shared by every number in it. Raised by business verification + sending history, not by adding numbers. Below it, Meta refuses with 138015 |
| No payment-method block on the WABA | yours — a payment error (141006) blocks business-initiated conversations and shows in the health banner |
An app subscribed to the WABA's calls webhook field | platform — without it Meta refuses with 138018 |
Platform build with the wa_calling_media feature | the media plane is a compile-time cargo feature (operator/self-host step) |
Runtime flag FEATURE_WHATSAPP_CALLING_MEDIA=true | enables the media plane at runtime |
WHATSAPP_CALL_ICE_URLS — a STUN/TURN server | WebRTC needs a reachable ICE path; a public IP or a TURN server is required for media to connect |
The last four are platform/operator settings (see the go-live runbook). On a hosted Telenow plan they're already provisioned — you only bind an agent and toggle calling on. If calling isn't available in your workspace, contact your administrator.
The two marked yours are the ones you can act on, and they're both visible before you try: the account-health endpoint or banner shows your messaging limit and any payment-method warning.
Turn it on
In the dashboard: on the channel, open the Calling bar, pick an answering agent, and toggle calling on. This also flips the calling setting at Meta for your number. Owners and admins only.
Over the API (the key's creator must be an owner or admin):
curl -X PUT https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/channels/{channelId}/calling-agent \
-H "X-API-Key: vai_live_…" \
-H "Content-Type: application/json" \
-d '{ "agent_id": "a1b2c3d4-…", "calling_enabled": true }'
{ "success": true,
"data": { "callingEnabled": true, "agentId": "a1b2c3d4-…", "metaSynced": true, "warnings": [] } }
| Field | Type | Required | Notes |
|---|---|---|---|
agent_id | uuid | to enable calling | the agent that answers calls; must belong to your org, and its Telephony channel must be on (400 otherwise) |
calling_enabled | bool | — | default false; forced false when no agent is bound. Setting this calls Meta to enable/disable calling on the number |
metaSynced says whether Meta's own switch is known to match what was stored: true applied, false we tried and Meta refused (your channel setting still governs whether an agent answers), null Meta never reported its state. warnings carries anything real but non-blocking — a payment-method problem, a display name still in review — and the response can also include notes.
Plivo WhatsApp numbers: calling is switched on in Telenow only — nothing is sent to Meta. The response is
{ callingEnabled, agentId, metaSynced: null, answerUrl, notes }; point the number's call handling in Plivo atanswerUrl.
To turn calling off, send { "calling_enabled": false }. Disabling always succeeds — it is recorded on your channel first and Meta is told afterwards, so an account problem can never trap you with calling stuck on.
Enabling is the direction Meta can refuse. When it does you get an actionable 400 naming the blocker, with the full list under blockers so fixing the first one doesn't just reveal the second:
{ "success": false,
"error": "Your messaging limit is too low for WhatsApp calling. WhatsApp only allows calling once your business can start at least 2000 conversations a day; yours is at 1000. …",
"code": "wa_calling_messaging_limit",
"blockers": [ { "code": "wa_calling_messaging_limit", "level": "error", "title": "…", "detail": "…", "action": "Open Meta Business Manager" } ] }
The 400 also carries advisories and notes next to blockers. When Meta itself rejects the switch, the 400 carries meta: { code, subcode, fbtraceId } instead of blockers. A revoked access token is a 400 with code: "wa_token_revoked". The codes are listed under Calling errors. A 502 from this endpoint means something on Meta's side failed rather than your account being ineligible — retry it.
Re-saving a channel whose calling state is unchanged writes only the agent binding; Telenow then checks Meta's switch and re-applies it if Meta disagrees, and a failure there comes back as a warning rather than an error — so merely re-saving a page can't fail on an account problem you didn't introduce.
How a call flows
- A customer places a WhatsApp call to your number → Meta sends Telenow a
connectevent. - If calling is enabled and an agent is bound and the media plane is on, Telenow answers: it negotiates WebRTC, stands up the agent's session, and accepts the call at Meta. The agent talks to the caller.
- Otherwise the call is rejected at Meta immediately — the caller isn't left ringing.
- When either side hangs up, the call is logged with its duration.
Call log
List a channel's calls (most recent first):
curl "https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/channels/{channelId}/calls" \
-H "X-API-Key: vai_live_…"
{ "success": true, "data": { "calls": [
{ "call_id": "wacid.…", "direction": "inbound", "from_number": "+919876543210",
"status": "completed", "duration_secs": 92, "agent_id": "a1b2c3d4-…",
"start_time": "2026-01-01T12:00:00Z", "end_time": "2026-01-01T12:01:32Z" }
] } }
status is one of ringing, accepted, rejected, completed, failed, or missed (missed comes from Plivo numbers only). Each row also carries id, org_id, channel_id, phone_number_id, to_number, session_id, last_error, created_at and updated_at. The endpoint returns up to the 100 most recent calls (newest first) with no pagination, filtering, or offset, and there's no WhatsApp-call webhook event — poll this endpoint to keep your own history. duration_secs is in seconds, and direction reflects the value WhatsApp reports for the call (e.g. inbound).
Customer satisfaction (CSAT)
Ask customers to rate a conversation when it's resolved. Set it up per channel (Meta Cloud numbers only; the key's creator must be an owner or admin):
curl -X PUT https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/channels/{channelId}/csat \
-H "X-API-Key: vai_live_…" \
-H "Content-Type: application/json" \
-d '{ "enabled": true, "template_name": "csat_rating", "template_language": "en_US" }'
{ "success": true, "data": { "enabled": true } }
- When a thread moves to
resolvedinside the 24-hour window, the customer gets three buttons — Great (5), OK (3), Not good (1). - Outside the window, the approved template named in
template_nameis sent instead. Build it with one body variable (Telenow fills it with "your recent conversation") and three quick-reply buttons — the first counts as 5, the second as 3, the third as 1. Without a template, nobody is asked once the window has closed. - Opted-out numbers are never asked, and each number is asked at most once every 7 days. A blank
template_nameclears the template.
GET …/channels/{channelId}/csat (any member) returns { enabled, templateName, templateLanguage, averageScore, responseCount } for the last 30 days; averageScore is null until someone rates.
Related
- Connecting WhatsApp — set up the number first.
- Webhooks & events — receive messages and delivery statuses in your own system.
- Reading conversations — thread and message history for a human agent.
- Authentication & channels — the org API key these routes use.
- Inbox, contacts & segments — assign, resolve and snooze conversations.
- Authentication — API keys, JWTs and org ids.