Conversations

A conversation is a stateful thread of messages between one of your agents and one external number. Conversations span both SMS and WhatsApp channels — the platform threads inbound and outbound messages onto the same conversation when they share an agent + remote-number pair.

ConceptWhat it is
conversation_id (conv_*)Stable ID for the thread. Returned on every message.received and message.sent event.
ai_modeWho is currently responding: ai, human, or closed.
WindowFor WhatsApp only: rolling 24-hour limit on free-form outbound. Templates bypass it. See WhatsApp guide.

This guide covers list/get, the AI ↔ human handoff via PATCH /v1/conversations/{id}, and live updates via SSE.

List Conversations

curl "https://api.voicebip.com/v1/conversations?page_size=20" \
-H "Authorization: Bearer pk_live_your_key"

Filter by agent_id or channel (sms | whatsapp). Paginate with ?page_token=... returned by the previous response. See Pagination for the cursor format.

Response — 200 OK

{
"conversations": [
{
"conversation_id": "conv_abc123",
"agent_id": "agt_PAEZ_njcfm2kycpjs",
"channel": "whatsapp",
"from_number": "+2348031234567",
"to_number": "+2349012345678",
"window_expires_at": "2026-05-16T14:32:01Z",
"opt_out": false,
"created_at": "2026-05-15T10:15:00Z",
"updated_at": "2026-05-15T14:32:01Z",
"last_message_at": "2026-05-15T14:32:01Z"
}
],
"next_page_token": "eyJ..."
}

window_expires_at is WhatsApp-only — null for SMS conversations. To inspect the current ai_mode for a conversation, fetch it via GET /v1/conversations/{conversation_id} — the list endpoint omits it to keep the listing query cheap.

Get a Single Conversation

Returns full message history (paginated reverse-chronological) and metadata.

curl "https://api.voicebip.com/v1/conversations/conv_abc123" \
-H "Authorization: Bearer pk_live_your_key"

The response includes the message thread plus the current ai_mode, created_at, and the WhatsApp window state if applicable.

Hand Off to a Human (AI → Human)

Operator dashboards take over an active AI conversation by PATCHing the mode:

curl -X PATCH "https://api.voicebip.com/v1/conversations/conv_abc123" \
-H "Authorization: Bearer pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "ai_mode": "human" }'
TransitionEffect
ai → humanVoicebip stops dispatching new inbound messages to the agent’s BYOM webhook / hosted AI. Operators reply via POST /v1/messages as usual.
human → aiAI dispatcher resumes — the next inbound message is delivered to the agent.
* → closedTerminal. The next inbound message from this remote number starts a brand-new conversation.

Idempotency. PATCHing the same ai_mode returns the current state with changed: false and does not publish a conversation.mode_changed event — safe to call from a click handler that may double-fire.

Audit trail. Every transition writes a row to conversation_mode_history with actor_user_id, from_mode, to_mode, and timestamp. Operators can see who handed off when.

Live Updates via SSE

Subscribe to message and mode-change events for a single conversation:

const es = new EventSource(
`https://api.voicebip.com/v1/conversations/${conversationId}/stream?token=${apiKey}`
);
es.onmessage = (frame) => {
const event = JSON.parse(frame.data);
// event.event_type: message.received | message.delivered | message.read | conversation.mode_changed
// event.conversation_id
// event.timestamp (ISO 8601)
// event.payload — event-specific fields (message_id, direction, text, from_mode, to_mode, etc.)
};

Browsers can’t set custom headers on EventSource, so authenticate via ?token= (server only accepts the query param on this specific path). For server-side consumers use Authorization: Bearer. Full stream reference: Live Streaming.

Export an Agent’s Call Transcripts (CSV / JSON)

For offline analysis or backup. Note this endpoint exports the agent’s voice call transcripts (call metadata + transcript text), not SMS/WhatsApp message threads:

curl "https://api.voicebip.com/v1/agents/agt_PAEZ_njcfm2kycpjs/conversations/export?format=csv" \
-H "Authorization: Bearer pk_live_your_key" \
-o transcripts.csv

format accepts csv or json (defaults to json). The CSV columns are call_id, from_number, to_number, direction, status, duration_seconds, created_at, transcript_text. The endpoint returns up to the 1,000 most-recent calls for the agent. For larger exports use the deliveries replay API or contact support.

Closing a Conversation

curl -X PATCH "https://api.voicebip.com/v1/conversations/conv_abc123" \
-H "Authorization: Bearer pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{ "ai_mode": "closed" }'

closed is terminal. The next inbound message from the same remote number to the same agent will create a fresh conv_* ID.

Webhook Events for Conversations

Conversation activity surfaces through the normal messaging webhook events: message.received, message.delivered, message.read (WhatsApp), message.opt_out, and window.closing. See Webhooks for the full event reference.

The conversation.mode_changed event is an internal subject today — it fires on PATCH /v1/conversations/{id} but is not delivered to your webhook URL. The SSE stream above is the recommended way to subscribe to mode changes.