Chats
Channel-scoped threads with opaque chat_ ids — create, send, and reply without using phone numbers as ids.
In v4, a chat is a messaging thread on a specific channel (sender). Ids look like chat_... — opaque and stable. Do not treat the recipient's phone number as the chat id (that was a common v2 pattern).
Mental model
| Channel | Your side of the wire (ch_... — a Blooio number, Twilio line, AMB sender, …) |
| Chat | The thread between that channel and a peer (chat_...) |
| Contact | The person, with one or more identities (ct_...) |
The same contact can have multiple chats — one per channel (for example SMS on Twilio and iMessage on Blooio are different chats).
Two ways to send
1. Agnostic send (find-or-create)
POST /messages takes to + content. Blooio picks a channel via priorities / hybrid, finds or creates the chat, and returns chat_id on the message.
Use this for cold outreach and simple bots.
2. Send into an existing chat
When you already have chat_id (from a webhook, a previous send, or create-chat):
curl -X POST https://api.blooio.com/v4/chats/chat_.../messages \
-H "Authorization: Bearer bl_live_..." \
-H "Content-Type: application/json" \
-d '{
"content": { "type": "text", "text": "Following up" }
}'Try itNo from or to — the chat already knows the channel and peer.
Create a chat explicitly
Use this when you need the chat_id before the first message, or must pin a channel:
curl -X POST https://api.blooio.com/v4/chats \
-H "Authorization: Bearer bl_live_..." \
-H "Content-Type: application/json" \
-d '{
"channel_id": "ch_...",
"to": { "identifier": "+15551234567" }
}'Try itResponse:
{
"id": "chat_...",
"channel_id": "ch_...",
"channel_type": "blooio",
"contact_id": "ct_...",
"identity_id": "cid_...",
"state": "open",
"created": true
}If the thread already exists, you get the same chat with "created": false (HTTP 200).
Chat-scoped actions
Once you have chat_id, these stay on the chat:
- List / send messages
- Typing indicators and read receipts (where the channel supports them)
- Reactions on a message
- Share contact card
- Polls (also available as message
content.type: "poll") - Participants (group-capable channels only)
State
Chats are typically open or closed. Closed chats (for example AMB closed by the user) reject new sends with a conflict such as 409 chat_closed_by_user. Patch state with PATCH /chats/{chatId} when your product needs to mark a thread closed.
Webhooks
Inbound and lifecycle events include chat_id (and often a hydrated message or chat in data). Persist chat_id from the first event or send response and use it for all follow-ups.