Skip to main content
This guide covers the read side of WhatsApp: finding the sender number to send from, inspecting conversations (threads) and their 24-hour window state, and reading inbound replies. For exact field tables, see the reference: Senders and Conversations.
These are read endpoints - they return the resource directly (a bare JSON array or object), with no success/data/errors envelope. Errors use { "detail": "..." }. Everything is scoped to the workspace bound to your API key.

Finding a sender

A sender is a WhatsApp business phone number (WABA number) configured for your workspace. You reference it by sender_id when sending; if you omit sender_id, the workspace’s first active sender is used.
curl "https://karibu.briq.tz/v1/whatsapp/senders?is_active=true" \
  -H "X-API-Key: YOUR_API_KEY"
The response is a JSON array. Capture the id of an active sender to use as sender_id:
[
  {
    "id": "3f1c2b8a-9d4e-4a7b-bf2c-1e6a0d5c4b21",
    "display_number": "255700000001",
    "label": "Support line",
    "is_default": true,
    "is_active": true
  }
]
Use is_active and is_default query filters to narrow results. Fetch a single sender with GET /v1/whatsapp/senders/{sender_id} - a sender from another workspace returns 404.

Conversations and the 24-hour window

A conversation is the thread between one of your senders and a single recipient. Its is_active field tells you whether the 24-hour customer-care window is currently open - i.e. whether freeform (non-template) sends are allowed.
curl "https://karibu.briq.tz/v1/whatsapp/conversations?is_active=true&limit=50" \
  -H "X-API-Key: YOUR_API_KEY"
{
  "items": [
    {
      "id": "b1d8f2a0-3c4e-4a1b-9f2c-7d6e5a4b3c2d",
      "recipient_phone": "+255712345678",
      "is_active": true,
      "last_message_at": "2026-05-30T10:15:30.000000Z"
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}
The response wrapper is { items, total, limit, offset }. Filter by sender_id and is_active; paginate with limit (1-100, default 50) and offset.
Before sending freeform text, check the target conversation’s is_active. If it’s false (or there’s no conversation yet), open the thread with an approved template first.
Fetch a single thread with GET /v1/whatsapp/conversations/{conversation_id} to inspect its current is_active and last_message_at.

Reading inbound messages

Inbound message webhooks (whatsapp.received) are upcoming - until then, poll the conversation’s messages endpoint to read replies from your customer.
curl "https://karibu.briq.tz/v1/whatsapp/conversations/CONVERSATION_ID/messages?limit=100&offset=0" \
  -H "X-API-Key: YOUR_API_KEY"
Messages are returned oldest-first (created_at ascending). Inbound messages have is_outbound: false:
{
  "items": [
    {
      "id": "a1b2c3d4-e5f6-4789-90ab-cdef12345678",
      "message_id": "local-3f2a9c8e1d",
      "is_outbound": false,
      "message_type": "text",
      "content": { "body": "Thanks, when will it arrive?" },
      "status": "delivered",
      "created_at": "2026-05-30T10:15:30.000000Z"
    }
  ],
  "total": 1,
  "limit": 100,
  "offset": 0
}
status follows the delivery lifecycle: pending, queued, sent, delivered, read, failed. Paginate with limit (1-200, default 100) and offset. A simple polling loop:
import requests, time

BASE = "https://karibu.briq.tz"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}

def poll_inbound(conversation_id: str, seen: set):
    r = requests.get(f"{BASE}/v1/whatsapp/conversations/{conversation_id}/messages",
                     headers=HEADERS, params={"limit": 100})
    for m in r.json()["items"]:
        if not m["is_outbound"] and m["id"] not in seen:
            seen.add(m["id"])
            handle_inbound(m)  # your logic

seen = set()
while True:
    poll_inbound("CONVERSATION_ID", seen)
    time.sleep(15)
When you process an inbound message, consider sending a read receipt so the customer sees it was read.
Next: Templates | Delivery events