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