Skip to main content
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:
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.
sendText({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
chatGuid
string
required
The GUID of the chat to send the message to, e.g. "iMessage;+;+15550001234".
message
string
required
The text content of the message.
tempGuid
string
A client-generated unique identifier used to deduplicate messages and prevent duplicates.
method
string
Send method. One of "apple-script" (default) or "private-api". Using subject, effectId, or selectedMessageGuid forces "private-api" automatically.
subject
string
Optional message subject line. Requires Private API.
effectId
string
iMessage effect identifier (e.g. "com.apple.MobileSMS.expressivesend.invisibleink"). Requires Private API.
selectedMessageGuid
string
GUID of the message to reply to. Requires Private API.
partIndex
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+.
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.
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.
sendAttachment({ requestBody }: { requestBody?: any }): CancelablePromise<any>
requestBody
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().
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+.
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.
sendMultipartMessage({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
chatGuid
string
required
The GUID of the target chat.
parts
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.
subject
string
Optional subject line for the message.
effectId
string
iMessage effect identifier.
selectedMessageGuid
string
GUID of the message this is a reply to.
partIndex
number
Part index of the message to reply to. Defaults to 0.
You must upload each attachment with AttachmentsService.uploadAttachment() first and use the returned UUID hash as the attachment value in each part.
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.
sendReaction({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
chatGuid
string
required
The GUID of the chat containing the message to react to.
selectedMessageGuid
string
required
The GUID of the message you want to react to.
reaction
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".
partIndex
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+.
sendReaction() requires the Private API to be enabled on your BlueBubbles Server. Minimum server version: 0.3.0.
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.
list({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
limit
number
Maximum number of messages to return. Defaults to 1000.
offset
number
Number of records to skip. Use with limit for pagination. Defaults to 0.
with
array
Related data to include. Accepted values: "chat", "chat.participants", "attachment", "handle", "sms", "attributed-body", "message-info-summary", "payload-data".
where
array
TypeORM WHERE expression clauses for granular filtering. Each entry is an object with a statement string and an args dictionary.
after
number
Return only messages after this UNIX timestamp (seconds since epoch).
before
number
Return only messages before this UNIX timestamp (seconds since epoch).
sort
string
Sort direction for results. One of "ASC" or "DESC".
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.
get({ guid }: { guid: string }): CancelablePromise<any>
guid
string
required
The GUID of the message to retrieve.
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.
getUpdatedMessageCount(): CancelablePromise<any>
This method takes no parameters.
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.
getMySentMessageCount(): CancelablePromise<any>
This method takes no parameters.
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+.
scheduleAMessage({ requestBody }: { requestBody?: Record<string, any> }): CancelablePromise<any>
type
string
required
The action type. Currently only "send-message" is supported.
payload
object
required
The message data to send at the scheduled time. Mirrors the sendText() request body — include chatGuid, message, and optionally method.
scheduledFor
number
required
Milliseconds-since-epoch timestamp for when the message should be sent. Must be a future timestamp.
schedule
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 }.
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.
// 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.
getScheduledMessages(): CancelablePromise<any>
This method takes no parameters. Requires BlueBubbles Server v1.4.0+.
const response = await client.messages.getScheduledMessages();
console.log(response.data); // array of scheduled message objects

getScheduledMessageById()

Retrieve a single scheduled message by its ID.
getScheduledMessageById({ id }: { id: string }): CancelablePromise<any>
id
string
required
The unique ID of the scheduled message.
Requires BlueBubbles Server v1.4.0+.
const response = await client.messages.getScheduledMessageById({
  id: 'scheduled-message-id',
});

updateAScheduledMessageById()

Update the payload, schedule time, or recurrence configuration of an existing scheduled message.
updateAScheduledMessageById({
  id,
  requestBody,
}: {
  id: string;
  requestBody?: Record<string, any>;
}): CancelablePromise<any>
id
string
required
The unique ID of the scheduled message to update.
type
string
Action type. Use "send-message".
payload
object
Updated message payload mirroring the sendText() body.
scheduledFor
number
New milliseconds-since-epoch timestamp for when the message should send.
schedule
object
Updated schedule configuration. Same shape as scheduleAMessage().
Requires BlueBubbles Server v1.4.0+.
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.
deleteScheduledMessageById({ id }: { id: string }): CancelablePromise<any>
id
string
required
The unique ID of the scheduled message to delete.
Requires BlueBubbles Server v1.4.0+.
const response = await client.messages.deleteScheduledMessageById({
  id: 'scheduled-message-id',
});