Typing indicators & read receipts

Mark an inbound message read (the blue double-tick the customer sees) and optionally show a typing… indicator while you compose a reply — both from a single call. This makes an automated conversation feel like a real one.

Both actions use POST /messages/read, which needs the whatsapp scope on an app key and works on Meta Cloud numbers (native or your own Meta app). There is no org-API-key route for this; with an org key, reading a thread's messages marks it read for you (see In the dashboard).


Mark an inbound message read

Send the wamid of the inbound message you want to acknowledge. The customer’s single grey ticks turn to blue double ticks.

curl -X POST https://api.telenow.ai/api/app-whatsapp/messages/read \
  -H "Authorization: Bearer vai_app_…" \
  -H "Content-Type: application/json" \
  -d '{
    "channelId": "b1e2c3d4-…",
    "wamid": "wamid.HBgLMTQxNTU1NTAxMDAVAgAREg…"
  }'
{ "success": true }
FieldTypeNotes
channelIdstringRequired. The channel that received the message (channel_id also accepted)
wamidstringRequired. The WhatsApp id of the inbound message — the wamid from its whatsapp.message.received event or /threads/{id}/messages
typingboolOptional. Also show a typing indicator (see below)

You mark read against the message id you got when the message arrived, so a typical bot calls this the moment it receives a whatsapp.message.received webhook.

Errors: a missing wamid returns 400 wamid is required; a channel that isn't a Meta Cloud number returns 400; an unknown channel returns 404 WhatsApp channel not found; if WhatsApp refuses the call, you get 502 with mark_read failed (…) and code: "provider_error".


Show a typing indicator

Add "typing": true to the same call. This marks the message read and shows the customer a typing… bubble — a good move right after you receive a message and before you send a reply that takes a moment to generate.

curl -X POST https://api.telenow.ai/api/app-whatsapp/messages/read \
  -H "Authorization: Bearer vai_app_…" \
  -H "Content-Type: application/json" \
  -d '{
    "channelId": "b1e2c3d4-…",
    "wamid": "wamid.HBgLMTQxNTU1NTAxMDAVAgAREg…",
    "typing": true
  }'
{ "success": true }

The indicator auto-dismisses — it clears as soon as you send your reply, or after roughly 25 seconds if you don’t, whichever comes first. There’s no separate “stop typing” call; just send your message. If your reply will take longer than ~25 s, call again to re-arm it.

The typing indicator is tied to reading an inbound message — you can’t show typing out of the blue. Pass a real inbound wamid and set typing: true.


In the dashboard

The shared inbox does both of these for you:

  • Opening a thread auto-marks it read — the newest inbound message is acknowledged and the customer sees blue ticks.
  • When the AI agent starts composing a reply to an inbound message, it auto-shows the typing indicator, then clears it when the reply is sent.

So you only need /messages/read when you’re driving conversations programmatically (a custom bot or backend). How reading history behaves depends on the key:

  • App key — GET /api/app-whatsapp/threads/{id}/messages sends no read receipt. This endpoint sends the receipt, but neither resets the thread's unreadCount.
  • Org API key — GET …/whatsapp-hub/threads/{threadId}/messages behaves like opening the thread in the dashboard: it marks the thread read for the key's creator and, if they had unread messages, sends the customer a read receipt (without typing).

See Reading conversations.


Endpoint reference

MethodPathScopeBodyReturns
POST/api/app-whatsapp/messages/readwhatsapp{ channelId, wamid, typing? }{ success: true }

There's no org-API-key equivalent: marking a chosen message read and showing typing are app-key only. A bound AI agent shows typing automatically.