Inbox, contacts & segments

Everything your team does in the dashboard's WhatsApp inbox — assigning and resolving conversations, keeping contact records, saving audiences, quick replies, the business profile — is also available over HTTP with your org API key (X-API-Key: vai_live_…). App keys don't reach these routes.

All paths below are under https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub unless noted. Responses use the standard { "success": true, "data": … } envelope with snake_case fields. Any change needs an owner, admin or developer key; the role the key's creator needs is noted per route.


Manage threads

A thread is one conversation with one contact on one number. List them with GET /channels/{channelId}/threads (filter by status, assigned, q, tag); manage each one with:

MethodPathBodyReturns
PUT/threads/{threadId}/assign{ "user_id": "<user uuid>" } — null or omitted unassigns{ assignedTo }
PUT/threads/{threadId}/status{ "status": "open" | "pending" | "resolved" | "snoozed", "snoozed_until"? }{ status }
PUT/threads/{threadId}/pause{ "paused": true } — pause the AI agent on this thread{ success }
curl -X PUT https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/threads/{threadId}/status \
  -H "X-API-Key: vai_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "status": "snoozed", "snoozed_until": "2026-07-19T09:00:00Z" }'
  • Assign only to someone in your workspace (400 that person isn't in this workspace otherwise). assigned=mine on the thread list means threads assigned to the key's creator.
  • Snooze needs a future snoozed_until (RFC 3339); a snoozed thread reopens as open within about a minute of that time.
  • Resolve — moving a thread into resolved sends the customer a rating request when CSAT is on for the number.
  • Any member can do all three (the creator role is M).

To reply inside a thread, see Text messages — POST /threads/{threadId}/send. A reply sent that way is what counts as the thread's first response for inbox health.

Inbox health

GET /channels/{channelId}/inbox-health?days=30&threshold_mins=60 (any member) returns response-time numbers for one number:

{ "success": true, "data": {
  "health": {
    "median_first_response_secs": 312.5,
    "awaiting_reply": 4,
    "awaiting_over_threshold": 1,
    "resolved_in_window": 57,
    "unassigned_open": 2
  },
  "windowDays": 30,
  "thresholdMins": 60
} }
FieldMeaning
median_first_response_secsMedian time from a thread starting to its first reply from a person, for threads started in the window (null if none)
awaiting_replyOpen threads whose last message is from the customer
awaiting_over_thresholdOf those, how many have waited longer than threshold_mins
resolved_in_windowThreads resolved in the last days
unassigned_openOpen threads with nobody assigned

days is 1–365 (default 30); threshold_mins is 1–10,080 (default 60).


Contacts

Telenow keeps one contact record per phone number in your org. A record is created when a conversation with that number starts, and carries your own fields: a display name, notes, custom attributes, and tags (labels).

MethodPathWhat it does
GET/contacts?q&tag&limit&offsetList → { contacts, total, limit, offset }, most recent conversation first
GET/contacts/tagsEvery label in use → { tags }
GET/contacts/{contactId}One contact → { contact }
GET/contacts/by-phone/{phone}Look up by number → { contact }; creates the record if the number has a conversation, otherwise 404 no conversation with that number here
PATCH/contacts/{contactId}Edit → { contact }
  • List: q searches the number, display name and WhatsApp profile name; tag matches one label exactly. limit is 1–200 (default 50). Each row adds provider_name, thread_count and last_message_at.
  • Contact fields: id, phone, display_name, attributes, tags, notes, created_at, updated_at.
  • Any member can read and edit contacts.
curl -X PATCH https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/contacts/{contactId} \
  -H "X-API-Key: vai_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "display_name": "Asha Rao", "tags": ["vip", "mumbai"], "attributes": { "plan": "gold" } }'

Send only the fields you're changing — omitted fields are left alone:

FieldNotes
display_name, notesText, or null to clear
attributesAn object — it replaces the whole attributes object
tagsA list — it replaces the whole list. Each label is trimmed; blank labels and labels over 40 characters are dropped, duplicates are removed (ignoring case), and at most 50 are kept

Segments

A segment is a saved audience — a rule over your contacts that you can preview and turn into broadcast recipients. Opted-out numbers are always excluded.

MethodPathWhat it doesCreator
GET/segmentsList → { segments }any member
POST/segmentsSave { name, definition } → { segment } — saving an existing name replaces its ruleowner/admin/developer
DELETE/segments/{segmentId}Deleteowner/admin/developer
POST/segments/previewCount a rule before saving: { definition } or { segment_id } → { count, sample, capped }any member

The definition is an object; {} matches every contact.

KeyMeaning
tagsA list of labels (≤ 50). Contacts with any of them match — or all of them with "tagMode": "all"
attributesAn object (≤ 50 keys); contacts whose attributes contain these exact values match
quietForDays0–3,650 — leaves out anyone who has messaged you in the last N days
curl -X POST https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/segments/preview \
  -H "X-API-Key: vai_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "definition": { "tags": ["vip"], "attributes": { "plan": "gold" } } }'
{ "success": true, "data": { "count": 1240, "sample": ["+919876543210", "…"], "capped": false } }

sample is the first five numbers. Previews count at most 5,000; capped is true once the count reaches 5,000. A broadcast takes at most 5,000 contacts from a segment — see Broadcasts.


Quick replies

Quick replies (canned replies) are saved message snippets your team inserts in the dashboard composer. Telenow never sends them on its own. Any member can manage them.

MethodPathBodyReturns
GET/canned-replies—{ cannedReplies }, by title
POST/canned-replies{ title, body, shortcut? }{ cannedReply }
PUT/canned-replies/{replyId}{ title, body, shortcut? } — replaces the reply; leaving out shortcut clears it{ cannedReply }
DELETE/canned-replies/{replyId}—{ deleted: true }

title and body are required; body is at most 4,096 characters (WhatsApp's limit). shortcut is normalised — a leading / dropped, lowercased, only letters, digits, - and _ kept, at most 32 characters — and must be unique in your org (409 another quick reply already uses the shortcut /…).


Numbers in your inbox

GET /channels lists every number in your inbox (any member). Each row has id, kind (provider or baileys — WhatsApp Web), provider_id, label, phone, webhook_status, agent_id, ai_enabled and calling_enabled.

MethodPathWhat it doesCreator
GET/linkable-connectionsWhatsApp connections in your integrations that aren't in the inbox yet → { connections }any member
POST/channelsAdd one: { "kind": "provider", "connection_id": "…", "label"? } → { channel, webhookUrl }owner/admin
GET/channels/{channelId}/webhookThe inbound webhook URL and verify token to give a partner providerany member
DELETE/channels/{channelId}Remove a number from the inbox — it can be restoredowner/admin
GET/channels/removedRemoved numbers you can still restoreany member
POST/channels/{channelId}/restoreRestore a removed number → { channel }owner/admin
POST/channels/{channelId}/purgePermanently delete a removed number with its conversations, messages and broadcastsowner/admin
  • Connecting a brand-new number (Meta Embedded Signup) and linking WhatsApp Web by QR need a dashboard login — see Connecting WhatsApp.
  • Removing a WhatsApp Web number also unlinks the phone from Telenow.
  • Purge can't be undone, and works only on a number that's already removed.

Business profile

The profile your customers see — about text, address, description, email, websites and business category — for a Meta Cloud number. Paths are under …/api/orgs/{orgId}/whatsapp-cloud/channels/{channelId}:

MethodPathWhat it doesCreator
GET/profile{ profile: { about, address, description, email, profile_picture_url, websites, vertical }, verticals } — verticals lists the allowed categoriesany member
POST/profileUpdate any of about, address, description, email, websites, vertical → { profile }owner/admin
curl -X POST https://api.telenow.ai/api/orgs/{orgId}/whatsapp-cloud/channels/{channelId}/profile \
  -H "X-API-Key: vai_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "about": "Order help, 9am–9pm", "websites": ["https://shop.example.com"] }'

websites holds at most two links, each starting with http:// or https://; vertical must be one of verticals. A request with no fields returns 400; if Meta refuses the update you get 502. The profile picture can't be changed through the API.