Conversations

A conversation is every message exchanged with one person, in both directions, oldest to newest. It is what the console shows under Messages, and it is two endpoints if you would rather build your own.

List them

GET /v1/chats
curl https://njiwa.upeo.ai/v1/chats \
  -H "Authorization: Bearer sk_live_..."
{
  "object": "list",
  "data": [
    {
      "jid": "254712345678",
      "msisdn": "254712345678",
      "is_group": false,
      "last_message_at": "2026-09-02T11:19:46Z",
      "message_count": 29,
      "last_message": {
        "direction": "outbound", "type": "text",
        "status": "delivered", "text": "Your invoice for August"
      }
    }
  ]
}

Ordered by most recent activity. last_message is there so a list of conversations can show a preview line without a request per row.

Read one

GET /v1/chats/{id}/messages?limit=200

id is the jid from the list. Messages come back newest first, in the same shape as GET /v1/messages, with direction telling you which side each one is. Reverse the list to render a thread.

curl https://njiwa.upeo.ai/v1/chats/254712345678/messages \
  -H "Authorization: Bearer sk_live_..."

Replying

There is no reply endpoint. Send to the same number with POST /v1/messages and it joins the thread.

What identifies a conversation

The other person's phone number, not the address WhatsApp used.

This distinction is worth a paragraph because it is not obvious. WhatsApp addresses the same person two different ways: messages from them can arrive from an internal account id, while messages to them go to their phone number. Keyed on the address, one conversation becomes two, each holding one half, and neither reads like a conversation. Keyed on the number, which is the same in both directions, it is one thread.

So jid is a phone number for a one to one chat. A group has no single other person, so a group is identified by its own group id and msisdn is null; check is_group rather than guessing from the shape of the string. An old chat id still resolves to the right conversation, so a stored id does not go stale.

Status updates and channels are not conversations. They are not addressed to you and cannot be replied to, so they never appear here.