> ## Documentation Index
> Fetch the complete documentation index at: https://bluebubbles.anmho.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage iMessage Chats with the BlueBubbles SDK

> List, create, and manage iMessage chats with the BlueBubbles SDK — add participants, mark read state, send typing indicators, and delete chats.

The `client.chats` service gives you full control over the iMessage conversations on your BlueBubbles Server. You can paginate through all chats, create new ones, add or remove participants, manage read state, send typing indicators, and delete or leave group chats. Many of these operations require the Private API to be enabled on your server.

## List chats

Use `list()` to query chats from the server's local iMessage database. Pass a request body to control pagination, sorting, and the related data you want returned.

```typescript theme={null}
import { BlueBubblesClient } from "bluebubbles-sdk";

const client = new BlueBubblesClient({
  BASE: "http://your-server:1234",
  PASSWORD: "your-server-password",
});

const response = await client.chats.list({
  requestBody: {
    limit: 25,
    offset: 0,
    with: ["lastMessage", "participants"],
    sort: "lastmessage",
  },
});
```

### Query options

| Parameter | Type      | Description                                                                                                                                                           |
| --------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `limit`   | number    | Max number of chats to return (default `1000`)                                                                                                                        |
| `offset`  | number    | Number of chats to skip — use for pagination (default `0`)                                                                                                            |
| `with`    | string\[] | Related data to include. Options: `participants`, `lastMessage`, `sms`, `archived`, `message.attributed-body`, `message.message-info-summary`, `message.payload-data` |
| `sort`    | string    | Sort order. Must be `lastmessage`. Requires `lastMessage` in `with`                                                                                                   |

### Paginate through all chats

```typescript theme={null}
const PAGE_SIZE = 50;
let offset = 0;
let allChats: any[] = [];

while (true) {
  const response = await client.chats.list({
    requestBody: {
      limit: PAGE_SIZE,
      offset,
      with: ["lastMessage", "participants"],
      sort: "lastmessage",
    },
  });

  const chats = response.data ?? [];
  allChats = allChats.concat(chats);

  if (chats.length < PAGE_SIZE) break;
  offset += PAGE_SIZE;
}
```

***

## Fetch a single chat

Use `get()` to retrieve a specific chat by its GUID:

```typescript theme={null}
const chat = await client.chats.get({
  chatGuid: "iMessage;+;+15551234567",
});
```

The GUID format for direct messages is `iMessage;-;+15551234567` (note the `-`) or `iMessage;+;+15551234567` for group chats. Use the GUIDs returned by `list()` to ensure you have the correct format.

***

## Create a new chat

`create()` opens a new iMessage conversation with one or more participants. You can optionally send an opening message at the same time.

<Note>
  Creating chats requires the Private API. Requires BlueBubbles Server 0.3.0+.
</Note>

```typescript theme={null}
// Direct message to one person
await client.chats.create({
  requestBody: {
    addresses: ["+15551234567"],
    message: "Hey, I just set up BlueBubbles!",
  },
});

// Group chat with multiple participants
await client.chats.create({
  requestBody: {
    addresses: ["+15551234567", "+15559876543", "friend@icloud.com"],
    message: "Welcome to the group!",
  },
});
```

Include country codes in phone numbers where possible. For US numbers, prefix with `1`.

***

## Add and remove participants

Add or remove participants from an existing group chat using `addParticipantToChat()` and `removeParticipantFromChat()`.

<Note>
  Both methods require the Private API. Requires BlueBubbles Server 0.3.0+.
</Note>

<Tabs>
  <Tab title="Add a participant">
    ```typescript theme={null}
    await client.chats.addParticipantToChat({
      chatGuid: "iMessage;+;chat-group-guid",
      requestBody: {
        address: "+15551234567",
      },
    });
    ```
  </Tab>

  <Tab title="Remove a participant">
    ```typescript theme={null}
    await client.chats.removeParticipantFromChat({
      chatGuid: "iMessage;+;chat-group-guid",
    });
    ```

    <Note>
      `removeParticipantFromChat()` takes only the `chatGuid` path parameter. The server determines which participant to remove based on the context of the request.
    </Note>
  </Tab>
</Tabs>

***

## Mark a chat as read or unread

<Tabs>
  <Tab title="Mark as read">
    `markRead()` marks a chat as read and dispatches a read event to other connected BlueBubbles clients.

    <Note>
      Requires Private API and BlueBubbles Server 1.1.0+.
    </Note>

    ```typescript theme={null}
    await client.chats.markRead({
      chatGuid: "iMessage;+;+15551234567",
    });
    ```
  </Tab>

  <Tab title="Mark as unread">
    `markChatAsUnread()` marks a chat as unread. The event is dispatched to all BlueBubbles clients, but the unread state is only reflected on other Apple devices when running macOS Ventura or later.

    <Note>
      Requires Private API, macOS Ventura, and BlueBubbles Server 1.4.0+.
    </Note>

    ```typescript theme={null}
    await client.chats.markChatAsUnread({
      chatGuid: "iMessage;+;+15551234567",
    });
    ```
  </Tab>
</Tabs>

***

## Send typing indicators

Show or hide the typing bubble in a conversation. Both methods require the Private API.

<Note>
  Typing indicators automatically stop when you send a message to the same chat. You don't need to call `stopSendTypingIndicator()` after a successful `sendText()`.
</Note>

```typescript theme={null}
// Start typing
await client.chats.startSendTypingIndicator({
  chatGuid: "iMessage;+;+15551234567",
});

// ... do some work, compose the message ...

// Stop typing manually if you decide not to send
await client.chats.stopSendTypingIndicator({
  chatGuid: "iMessage;+;+15551234567",
});
```

***

## Leave or delete a chat

<Tabs>
  <Tab title="Leave a group">
    Use `leaveChat()` to remove yourself from a group conversation. This only works for group chats — calling it on a direct message chat returns an error.

    <Note>
      Requires the Private API.
    </Note>

    ```typescript theme={null}
    await client.chats.leaveChat({
      chatGuid: "iMessage;+;group-chat-guid",
    });
    ```
  </Tab>

  <Tab title="Delete a chat">
    `deleteChat()` removes a chat from the iMessage client on the macOS host. This change only applies to the server's Mac — it does not affect other Apple devices signed into the same account.

    <Note>
      Requires the Private API. Requires BlueBubbles Server 1.3.0+.
    </Note>

    <Warning>
      Deleting a chat on the Mac is irreversible on that device. Other iCloud-connected devices retain the conversation.
    </Warning>

    ```typescript theme={null}
    await client.chats.deleteChat({
      chatGuid: "iMessage;+;+15551234567",
    });
    ```
  </Tab>
</Tabs>

***

## Set or remove a group icon

Customize a group chat's avatar using `setGroupIcon()`, or revert to the default with `removeGroupIcon()`. Both methods require the Private API.

<Tabs>
  <Tab title="Set an icon">
    ```typescript theme={null}
    import { readFileSync } from "fs";

    const formData = new FormData();
    formData.append(
      "icon",
      new Blob([readFileSync("./team-photo.jpg")], { type: "image/jpeg" }),
      "team-photo.jpg"
    );

    await client.chats.setGroupIcon({
      chatGuid: "iMessage;+;group-chat-guid",
      requestBody: formData,
    });
    ```
  </Tab>

  <Tab title="Remove an icon">
    ```typescript theme={null}
    await client.chats.removeGroupIcon({
      chatGuid: "iMessage;+;group-chat-guid",
    });
    ```
  </Tab>
</Tabs>
