Skip to the page

Sending and receiving

Group chats

Find a group chat, text into it with chat_id, and read what its members send. BlueBot can text into a group that already exists but can’t start a new one.

BlueBot can text into any group chat that already exists in Messages on your Mac, and read what everyone in it sends. It can’t start a new group: Messages offers no reliable way for an app to do that.

Dana is selling 412 Oak St, and she has a group chat in Messages called “Oak St closing” with the buyers and their lender. Her code finds the chat once, then posts updates into it as the closing moves along.

Find the chat

GET/v1/chats lists the chats your Mac has copied, newest first. is_group=true leaves out the one-to-one chats:

GET/v1/chatsList chats →
curl "https://usebluebot.com/api/v1/chats?is_group=true" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY"
Response200Group chats
{
  "object": "list",
  "data": [
    {
      "id": "chat_1Hq2LxW9cVbN3mKpRtYs0a",
      "object": "chat",
      "name": "Oak St closing",
      "is_group": true,
      "participants": [
        "+15555550123",
        "+15555550187"
      ],
      "service": "imessage",
      "last_message_at": "2026-11-13T19:41:00.000Z",
      "created_at": "2026-11-02T14:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
FieldWhat it tells you
idThe chat’s id (chat_…). This is what chat_id takes on a send.
nameThe group’s name in Messages, or null when nobody named it.
participantsEveryone in the chat except you.
serviceimessage for an iMessage group, sms for a group of regular texts.

To find a group somebody is in, add person: GET /v1/chats?is_group=true&person=+15555550187. A chat’s id stays the same for as long as the group exists, so look it up once and keep it.

A group appears in the list once your Mac has copied it. Under the default Which chats to copy setting, that means a group in which you’ve already texted every other member through BlueBot. A new group of people you’ve never texted that way won’t show until you set Which chats to copy to Everything. Receive texts explains the setting. When the Mac copies a group BlueBot didn’t know, chat.created fires.

Text into it

Send chat_id in place of to:

POST/v1/messagesSend a text →
curl -X POST "https://usebluebot.com/api/v1/messages" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: oak-st-closing-appraisal" \
  -d '{
    "chat_id": "chat_1Hq2LxW9cVbN3mKpRtYs0a",
    "text": "Good news: the appraisal came back at the asking price. Closing is still on for the 24th."
  }'
Response201A text into a group
{
  "id": "msg_2Bf8QzD4kJmA6nXwEuTr1c",
  "object": "message",
  "direction": "out",
  "state": "queued",
  "to": null,
  "chat_id": "chat_1Hq2LxW9cVbN3mKpRtYs0a",
  "contact_id": null,
  "hold": null
}

Everyone in the group gets it, as if you had typed it in Messages. A group text has "to": null and "contact_id": null, since it goes to the chat rather than one person. Files, send_at, expires_at and metadata work as they do on any send.

Send to or chat_id, never both, or the send is 400 invalid_request. A chat_id that isn’t on your account is 404 not_found.

The id of a one-to-one chat works in chat_id too. BlueBot then sends to that person as if you had used to, so their stop list and their conversation apply.

How groups differ

One-to-oneGroup
Service with autoThe newest chat’s, else iMessage, with one SMS try if iMessage failsThe group’s own service. No SMS fallback.
A failed textfailed, or sent again as SMS once with autofailed with “Messages couldn’t send it to this group.”
The stop listA text to somebody on it is canceledDoesn’t apply: BlueBot can’t leave one person out of a group
New people a dayCounts the first text to somebodyNever counts
Pacing, quiet hours, daily ceilingApplyApply

The stop list covers one-to-one texts. If somebody in a group asks you to stop, take them out of the group on your phone, or stop texting the group. A reply of STOP inside a group doesn’t put anyone on your stop list.

Read what the group sends

Every text a member sends into a copied group comes in as a message with the group’s chat_id. from and contact_id are the member who sent it, and to is null:

A text in a group, as message.received carries it
{
  "id": "msg_3Lp3VsC7hGqE5tZyKbWn2d",
  "object": "message",
  "direction": "in",
  "state": "received",
  "to": null,
  "from": "+15555550187",
  "chat_id": "chat_1Hq2LxW9cVbN3mKpRtYs0a",
  "contact_id": "ct_2Bf8QzD4kJmA6nXwEuTr1c",
  "text": "Thanks Dana! Do we need to bring anything to closing?",
  "service": "imessage",
  "received_at": "2026-11-13T20:02:00.000Z"
}

To read one group’s history:

GET/v1/messagesList texts →
curl "https://usebluebot.com/api/v1/messages?chat_id=chat_1Hq2LxW9cVbN3mKpRtYs0a" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY"

Starting a group

BlueBot can’t make a new group chat. To text a new group from your code, start it once by hand:

  1. In Messages on your Mac or iPhone, start the group with everyone in it and send the first text.
  2. If you haven’t texted them all through BlueBot, set Which chats to copy to Everything, at least until the group shows up.
  3. Find the group with GET /v1/chats?is_group=true and keep its id.

From then on your code can text into it whenever it needs to.

What else BlueBot can’t do in a group

BlueBot can’t add or remove people, rename the group, leave it, or send a tapback in it. Those all need Apple’s private frameworks. Capabilities lists what a Mac can and can’t do.