> ## 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.

# Messages API reference — BlueBubbles SDK

> Send texts, attachments, and reactions, query message history, and manage scheduled messages using the BlueBubbles SDK MessagesService.

The `MessagesService` gives you full control over iMessage messaging through your BlueBubbles Server. You can send plain text, file attachments, multipart messages with inline mentions, and tapback reactions. The service also exposes query endpoints for fetching message history, counting totals, and a complete scheduling system for one-time and recurring future messages.

Access the service via your initialized client:

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

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

***

## Sending messages

### `sendText()`

Send a plain text iMessage to a chat.

```typescript theme={null}
sendText({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
```

<ParamField body="chatGuid" type="string" required>
  The GUID of the chat to send the message to, e.g. `"iMessage;+;+15550001234"`.
</ParamField>

<ParamField body="message" type="string" required>
  The text content of the message.
</ParamField>

<ParamField body="tempGuid" type="string">
  A client-generated unique identifier used to deduplicate messages and prevent duplicates.
</ParamField>

<ParamField body="method" type="string">
  Send method. One of `"apple-script"` (default) or `"private-api"`. Using `subject`, `effectId`, or `selectedMessageGuid` forces `"private-api"` automatically.
</ParamField>

<ParamField body="subject" type="string">
  Optional message subject line. Requires Private API.
</ParamField>

<ParamField body="effectId" type="string">
  iMessage effect identifier (e.g. `"com.apple.MobileSMS.expressivesend.invisibleink"`). Requires Private API.
</ParamField>

<ParamField body="selectedMessageGuid" type="string">
  GUID of the message to reply to. Requires Private API.
</ParamField>

<ParamField body="partIndex" type="number">
  The part index of the message to reply to when using threaded replies. Minimum `0`. Requires macOS Big Sur or newer and BlueBubbles Server v1.4.0+.
</ParamField>

<Note>
  `partIndex` requires macOS Big Sur or newer and BlueBubbles Server v1.4.0+. `subject`, `effectId`, and `selectedMessageGuid` each require the Private API to be enabled on your server.
</Note>

```typescript theme={null}
const response = await client.messages.sendText({
  requestBody: {
    chatGuid: 'iMessage;+;+15550001234',
    tempGuid: crypto.randomUUID(),
    message: 'Hello from the SDK!',
    method: 'apple-script',
  },
});
```

***

### `sendAttachment()`

Send a file attachment via iMessage.

```typescript theme={null}
sendAttachment({ requestBody }: { requestBody?: any }): CancelablePromise<any>
```

<ParamField body="requestBody" type="any">
  Multipart form data body containing the attachment file. Supports the `method`, `subject`, `effectId`, and `selectedMessageGuid` Private API parameters in the same way as `sendText()`.
</ParamField>

<Note>
  Using `method: "private-api"`, `subject`, `effectId`, or `selectedMessageGuid` in the body will route the request through the Private API. `partIndex` requires macOS Big Sur+ and server v1.4.0+.
</Note>

```typescript theme={null}
const formData = new FormData();
formData.append('chatGuid', 'iMessage;+;+15550001234');
formData.append('attachment', fileBlob, 'photo.jpg');

const response = await client.messages.sendAttachment({
  requestBody: formData,
});
```

***

### `sendMultipartMessage()`

Send a multipart message that combines text, inline mentions, and pre-uploaded attachments in a single message.

```typescript theme={null}
sendMultipartMessage({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
```

<ParamField body="chatGuid" type="string" required>
  The GUID of the target chat.
</ParamField>

<ParamField body="parts" type="array" required>
  An ordered array of message parts. Each part must include a `partIndex` and either a `text` string or an `attachment` UUID (from a prior `/attachment/upload` call) with a `name`. Mention parts must include a `mention` field (email or phone) alongside `text`.
</ParamField>

<ParamField body="subject" type="string">
  Optional subject line for the message.
</ParamField>

<ParamField body="effectId" type="string">
  iMessage effect identifier.
</ParamField>

<ParamField body="selectedMessageGuid" type="string">
  GUID of the message this is a reply to.
</ParamField>

<ParamField body="partIndex" type="number">
  Part index of the message to reply to. Defaults to `0`.
</ParamField>

<Tip>
  You must upload each attachment with `AttachmentsService.uploadAttachment()` first and use the returned UUID hash as the `attachment` value in each part.
</Tip>

```typescript theme={null}
const response = await client.messages.sendMultipartMessage({
  requestBody: {
    chatGuid: 'iMessage;+;+15550001234',
    parts: [
      { partIndex: 0, text: 'Hey, ' },
      { partIndex: 1, text: 'Tim Apple', mention: 'tim@apple.com' },
      { partIndex: 2, text: ' check out this photo!' },
      { partIndex: 3, attachment: '<uploaded-uuid>', name: 'photo.jpg' },
    ],
  },
});
```

***

### `sendReaction()`

Send a tapback reaction to a specific message. Requires the Private API.

```typescript theme={null}
sendReaction({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
```

<ParamField body="chatGuid" type="string" required>
  The GUID of the chat containing the message to react to.
</ParamField>

<ParamField body="selectedMessageGuid" type="string" required>
  The GUID of the message you want to react to.
</ParamField>

<ParamField body="reaction" type="string" required>
  The reaction type. Must be one of: `"love"`, `"like"`, `"dislike"`, `"laugh"`, `"emphasize"`, `"question"`, or the removal prefix variants: `"-love"`, `"-like"`, `"-dislike"`, `"-laugh"`, `"-emphasize"`, `"-question"`.
</ParamField>

<ParamField body="partIndex" type="number">
  The part index of the message to react to. Useful for messages with multiple parts (e.g. mixed text and images). Defaults to `0`. Requires macOS Big Sur+.
</ParamField>

<Warning>
  `sendReaction()` requires the Private API to be enabled on your BlueBubbles Server. Minimum server version: 0.3.0.
</Warning>

```typescript theme={null}
const response = await client.messages.sendReaction({
  requestBody: {
    chatGuid: 'iMessage;+;+15550001234',
    selectedMessageGuid: 'message-guid-here',
    reaction: 'love',
    partIndex: 0,
  },
});
```

***

## Querying messages

### `list()`

Query messages from the database with filtering, pagination, and sorting.

```typescript theme={null}
list({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
```

<ParamField body="limit" type="number">
  Maximum number of messages to return. Defaults to `1000`.
</ParamField>

<ParamField body="offset" type="number">
  Number of records to skip. Use with `limit` for pagination. Defaults to `0`.
</ParamField>

<ParamField body="with" type="array">
  Related data to include. Accepted values: `"chat"`, `"chat.participants"`, `"attachment"`, `"handle"`, `"sms"`, `"attributed-body"`, `"message-info-summary"`, `"payload-data"`.
</ParamField>

<ParamField body="where" type="array">
  TypeORM WHERE expression clauses for granular filtering. Each entry is an object with a `statement` string and an `args` dictionary.
</ParamField>

<ParamField body="after" type="number">
  Return only messages after this UNIX timestamp (seconds since epoch).
</ParamField>

<ParamField body="before" type="number">
  Return only messages before this UNIX timestamp (seconds since epoch).
</ParamField>

<ParamField body="sort" type="string">
  Sort direction for results. One of `"ASC"` or `"DESC"`.
</ParamField>

```typescript theme={null}
const response = await client.messages.list({
  requestBody: {
    limit: 50,
    offset: 0,
    with: ['chat', 'attachment', 'handle'],
    after: 1700000000,
    sort: 'DESC',
  },
});
```

***

### `get()`

Fetch a single message's full database record by its GUID.

```typescript theme={null}
get({ guid }: { guid: string }): CancelablePromise<any>
```

<ParamField path="guid" type="string" required>
  The GUID of the message to retrieve.
</ParamField>

```typescript theme={null}
const response = await client.messages.get({
  guid: 'message-guid-here',
});
```

***

### `getUpdatedMessageCount()`

Get the total number of messages stored for your iMessage account on the server device.

```typescript theme={null}
getUpdatedMessageCount(): CancelablePromise<any>
```

This method takes no parameters.

```typescript theme={null}
const response = await client.messages.getUpdatedMessageCount();
console.log(response.data); // total message count
```

***

### `getMySentMessageCount()`

Get the total number of messages you have personally sent from your iMessage account.

```typescript theme={null}
getMySentMessageCount(): CancelablePromise<any>
```

This method takes no parameters.

```typescript theme={null}
const response = await client.messages.getMySentMessageCount();
console.log(response.data); // your sent message count
```

***

## Scheduled messages

### `scheduleAMessage()`

Schedule a message to be sent at a future time, either once or on a recurring interval. Requires BlueBubbles Server v1.4.0+.

```typescript theme={null}
scheduleAMessage({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
```

<ParamField body="type" type="string" required>
  The action type. Currently only `"send-message"` is supported.
</ParamField>

<ParamField body="payload" type="object" required>
  The message data to send at the scheduled time. Mirrors the `sendText()` request body — include `chatGuid`, `message`, and optionally `method`.
</ParamField>

<ParamField body="scheduledFor" type="number" required>
  Milliseconds-since-epoch timestamp for when the message should be sent. Must be a future timestamp.
</ParamField>

<ParamField body="schedule" type="object" required>
  Scheduling configuration. For a one-time message, set `{ "type": "once" }`. For recurring, set `{ "type": "recurring", "intervalType": "daily" | "hourly" | "weekly" | "monthly" | "yearly", "interval": number }`.
</ParamField>

<Warning>
  Missed one-time messages are **not** retried. If the server was offline at the scheduled time, the message will be dropped. Missed recurring messages are rescheduled to the next occurrence.
</Warning>

```typescript theme={null}
// One-time schedule
const response = await client.messages.scheduleAMessage({
  requestBody: {
    type: 'send-message',
    payload: {
      chatGuid: 'iMessage;-;+15550001234',
      message: 'Good morning!',
      method: 'private-api',
    },
    scheduledFor: Date.now() + 60 * 60 * 1000, // 1 hour from now
    schedule: { type: 'once' },
  },
});

// Recurring daily schedule
const recurring = await client.messages.scheduleAMessage({
  requestBody: {
    type: 'send-message',
    payload: {
      chatGuid: 'iMessage;-;+15550001234',
      message: 'Daily check-in!',
      method: 'private-api',
    },
    scheduledFor: Date.now() + 60 * 60 * 1000,
    schedule: { type: 'recurring', intervalType: 'daily', interval: 1 },
  },
});
```

***

### `getScheduledMessages()`

Retrieve all scheduled messages, including past and currently pending ones.

```typescript theme={null}
getScheduledMessages(): CancelablePromise<any>
```

This method takes no parameters. Requires BlueBubbles Server v1.4.0+.

```typescript theme={null}
const response = await client.messages.getScheduledMessages();
console.log(response.data); // array of scheduled message objects
```

***

### `getScheduledMessageById()`

Retrieve a single scheduled message by its ID.

```typescript theme={null}
getScheduledMessageById({ id }: { id: string }): CancelablePromise<any>
```

<ParamField path="id" type="string" required>
  The unique ID of the scheduled message.
</ParamField>

Requires BlueBubbles Server v1.4.0+.

```typescript theme={null}
const response = await client.messages.getScheduledMessageById({
  id: 'scheduled-message-id',
});
```

***

### `updateAScheduledMessageById()`

Update the payload, schedule time, or recurrence configuration of an existing scheduled message.

```typescript theme={null}
updateAScheduledMessageById({
  id,
  requestBody,
}: {
  id: string;
  requestBody?: Record<string, any>;
}): CancelablePromise<any>
```

<ParamField path="id" type="string" required>
  The unique ID of the scheduled message to update.
</ParamField>

<ParamField body="type" type="string">
  Action type. Use `"send-message"`.
</ParamField>

<ParamField body="payload" type="object">
  Updated message payload mirroring the `sendText()` body.
</ParamField>

<ParamField body="scheduledFor" type="number">
  New milliseconds-since-epoch timestamp for when the message should send.
</ParamField>

<ParamField body="schedule" type="object">
  Updated schedule configuration. Same shape as `scheduleAMessage()`.
</ParamField>

Requires BlueBubbles Server v1.4.0+.

```typescript theme={null}
const response = await client.messages.updateAScheduledMessageById({
  id: 'scheduled-message-id',
  requestBody: {
    type: 'send-message',
    payload: {
      chatGuid: 'iMessage;-;+15550001234',
      message: 'Updated message text!',
      method: 'private-api',
    },
    scheduledFor: Date.now() + 2 * 60 * 60 * 1000,
    schedule: { type: 'once' },
  },
});
```

***

### `deleteScheduledMessageById()`

Permanently delete a scheduled message by its ID.

```typescript theme={null}
deleteScheduledMessageById({ id }: { id: string }): CancelablePromise<any>
```

<ParamField path="id" type="string" required>
  The unique ID of the scheduled message to delete.
</ParamField>

Requires BlueBubbles Server v1.4.0+.

```typescript theme={null}
const response = await client.messages.deleteScheduledMessageById({
  id: 'scheduled-message-id',
});
```
