Conversations
A conversation is a thread between one of your numbers and a contact (or a group). Threads are created for you automatically on the first message in either direction — you only create one explicitly to start an iMessage group chat.
Browse threads
GET/v1/chats
GET/v1/chats/:id
The list paginates newest-first with limit (1–100, default 50) and before (ISO timestamp), returning { data, has_more, request_id } where each item in data is a chat object:
{
"id": "7f2c9e1b-…",
"from_handle": "+18005551111",
"remote_handle": "+15555550123",
"is_group": false,
"title": null,
"last_message_at": "2026-06-11T18:21:04.000Z",
"created_at": "2026-06-10T02:11:40.000Z",
"updated_at": "2026-06-11T18:21:04.000Z"
}To fetch a thread’s messages, pass its id as conversation_id on GET /v1/messages.
Create an iMessage group
POST/v1/chats
curl -X POST https://api.msgbubbles.com/v1/chats \
-H "Authorization: Bearer sk_live_…" \
-H "content-type: application/json" \
-d '{
"from_handle": "+18005551111",
"addresses": ["+15555550123", "+15555550124"],
"message": "welcome to the group!",
"title": "Launch crew"
}'addresses— 2 to 31 recipients (2+ remotes is what makes it a group).message— required; groups are established by sending their first message.title— optional display name, up to 100 characters.
Pass an Idempotency-Key header to make retries safe: a repeated key returns the original group with 200 instead of creating a second one with 201.
Send follow-ups into the group with conversation_id on POST /v1/messages.
Manage a group
PATCH/v1/chats/:id
Rename: { "title": "New name" }.
POST/v1/chats/:id/participants
DELETE/v1/chats/:id/participants/:handle
Add with { "handle": "+15555550125" }; remove by handle in the path. Group operations apply only to established groups (409 not_a_group otherwise) and run synchronously — the response is the messaging network’s verdict.
Read receipts
POST/v1/chats/:id/read
Marks the thread read on your side, so the people messaging you see read receipts. Works for iMessage and WhatsApp threads.
Typing indicators
POST/v1/chats/:id/typing
{ "typing": true } shows the typing bubble on the recipient’s side; false hides it. It auto-expires on the recipient’s device, so don’t worry about cleanup if your process dies mid-conversation. Inbound typing from your contacts arrives as the conversation.typing webhook event.