Advanced iMessage Kit is a full-featured iMessage SDK for reading, sending, and automating iMessage conversations on macOS. Perfect for building AI agents, automation tools, and chat applications.
Advanced iMessage Kit is the enterprise edition provided by Photon.
- Provisioned iMessage Numbers – Dedicated numbers ready for production use
- Managed Hosting – Fully managed infrastructure for reliability and scale
- DevOps & Deployment Support – Production setup, monitoring, and scaling
- Enterprise Support – Direct support and custom integrations
📩 Enterprise inquiries:
Contact daniel@photon.codes
🌐 Book a Demo:
https://photon.codes
If you're looking for the free/open-source version, please use iMessage Kit instead.
| Feature | Description | Method | Example |
|---|---|---|---|
| Send Messages | Send text messages to any contact | messages.sendMessage() |
message-send.ts |
| Reply to Messages | Reply inline to a specific message | messages.sendMessage() |
message-reply.ts |
| Message Effects | Send with effects (confetti, fireworks, etc.) | messages.sendMessage() |
message-effects.ts |
| Text Styles | Bold, italic, underline, strikethrough | messages.sendMessage() |
message-styled.ts |
| Text Animations | Per-character animations (shake, ripple, etc.) | messages.sendMessage() |
message-styled.ts |
| Send Rich Links | Send URLs with rich link previews | messages.sendMessage() |
message-rich-link.ts |
| Schedule Messages | Send once or on a recurring schedule | scheduledMessages.createScheduledMessage() |
scheduled-message-once.ts |
| Unsend Messages | Retract a sent message | messages.unsendMessage() |
message-unsend.ts |
| Edit Messages | Edit a sent message | messages.editMessage() |
message-edit.ts |
| Send Tapbacks | React with ❤️ 👍 👎 😂 |
messages.sendReaction() |
message-reaction.ts |
| Query Messages | Search and filter message history | messages.getMessages() |
message-search.ts |
| Destination Caller ID | See which of your addresses sent/received | messages.getMessages() |
message-destination-caller-id.ts |
| Message History | View messages, reactions, polls, stickers | chats.getChatMessages() |
message-history.ts |
| Send Attachments | Send images, files, documents | attachments.sendAttachment() |
message-attachment.ts |
| Send Audio Messages | Send voice messages | attachments.sendAttachment() |
message-audio.ts |
| Send Stickers | Send sticker as standalone message | attachments.sendSticker() |
message-sticker.ts |
| Reply Stickers | Attach sticker to a message bubble | attachments.sendSticker() |
message-reply-sticker.ts |
| Download Attachments | Download received files and media | attachments.downloadAttachment() |
attachment-download.ts |
| Get Chats | List all conversations | chats.getChats() |
chat-fetch.ts |
| Get Chat Participants | View group chat participants | chats.getChat() |
chat-participants.ts |
| Manage Group Chats | Add/remove members, rename groups | chats.addParticipant() |
chat-group.ts |
| Typing Indicators | Show "typing..." status | chats.startTyping() |
message-typing.ts |
| Get Contacts | Fetch device contacts | contacts.getContacts() |
contact-list.ts |
| Share Contact Card | Share your contact info in chat | contacts.shareContactCard() |
message-contact-card.ts |
| Check iMessage Availability | Verify if contact uses iMessage | handles.getHandleAvailability() |
service-check.ts |
| Server Info | Get server status and config | server.getServerInfo() |
server-info.ts |
| Message Statistics | Get message counts and analytics | server.getMessageStats() |
message-stats.ts |
| Create Polls | Create interactive polls in chat | polls.create() |
poll-create.ts |
| Vote on Polls | Vote or unvote on poll options | polls.vote() |
poll-vote.ts |
| Add Poll Options | Add options to existing polls | polls.addOption() |
poll-add-option.ts |
| Find My Friends | Get friends' locations | icloud.refreshFindMyFriends() |
findmy-friends.ts |
| Find My Watch | Watch friends' location changes in real-time | icloud.refreshFindMyFriends() |
findmy-watch.ts |
| Set Chat Background | Set custom background image for chat | chats.setBackground() |
background-set.ts |
| Remove Chat Background | Remove background from chat | chats.removeBackground() |
background-remove.ts |
| Real-time Events | Listen for new messages, typing, etc. | sdk.on() |
listen-simple.ts |
| Auto Reply | Build automated reply bots | sdk.on() |
auto-reply-hey.ts |
npm install @photon-ai/advanced-imessage-kit
# or
bun add @photon-ai/advanced-imessage-kitimport { SDK } from "@photon-ai/advanced-imessage-kit";
const sdk = SDK({
serverUrl: "http://localhost:1234",
});
await sdk.connect();
sdk.on("new-message", (message) => {
console.log("New message:", message.text);
});
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Hello World!",
});
await sdk.close();interface ClientConfig {
serverUrl?: string; // Server URL, defaults to "http://localhost:1234"
apiKey?: string; // API key (if server requires authentication)
logLevel?: "debug" | "info" | "warn" | "error"; // Log level, defaults to "info"
logToFile?: boolean; // Enable writing logs to ~/Library/Logs/AdvancedIMessageKit (default true)
}chatGuid is the unique identifier for a conversation. The format is service;-;address:
- iMessage DM:
iMessage;-;+1234567890oriMessage;-;email@example.com - SMS DM:
SMS;-;+1234567890 - Group chat:
iMessage;+;chat123456789 - Auto-detect:
any;-;+1234567890(SDK automatically detects the service type)
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Phone / Email │────▶│ Build chatGuid │────▶│ Send Message │
│ +1234567890 │ │ any;-;+123... │ │ sendMessage() │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ getChats() │────▶│ Get chat.guid │────▶│ Use for other │
│ List chats │ │ │ │ operations │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ sendMessage() │────▶│ Get message.guid│────▶│ edit/unsend │
│ Send message │ │ │ │ sendReaction │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Examples: message-send.ts | message-unsend.ts | message-edit.ts | message-reaction.ts | message-rich-link.ts | message-search.ts
// Send a text message
const message = await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Hello!",
});
// With subject and effect
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Happy Birthday!",
subject: "Wishes",
effectId: "com.apple.messages.effect.CKConfettiEffect",
});
// Reply to a message
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "This is a reply",
selectedMessageGuid: "original-message-guid",
});
// Send a rich link preview
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "https://photon.codes/",
richLink: true,
});Message Effects:
| Effect | effectId |
|---|---|
| Confetti | com.apple.messages.effect.CKConfettiEffect |
| Fireworks | com.apple.messages.effect.CKFireworksEffect |
| Balloons | com.apple.messages.effect.CKBalloonEffect |
| Hearts | com.apple.messages.effect.CKHeartEffect |
| Lasers | com.apple.messages.effect.CKHappyBirthdayEffect |
| Shooting Star | com.apple.messages.effect.CKShootingStarEffect |
| Sparkles | com.apple.messages.effect.CKSparklesEffect |
| Echo | com.apple.messages.effect.CKEchoEffect |
| Spotlight | com.apple.messages.effect.CKSpotlightEffect |
| Gentle | com.apple.MobileSMS.expressivesend.gentle |
| Loud | com.apple.MobileSMS.expressivesend.loud |
| Slam | com.apple.MobileSMS.expressivesend.impact |
| Invisible Ink | com.apple.MobileSMS.expressivesend.invisibleink |
Example: message-effects.ts
Apply per-range text formatting and whole-message character animations (requires Private API):
// Bold a portion of text
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "This is bold text",
textStyles: [{ start: 8, end: 12, bold: true }],
});
// Multiple styles in one message
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Bold here, italic there",
textStyles: [
{ start: 0, end: 9, bold: true },
{ start: 11, end: 23, italic: true },
],
});
// Character animation (applies to whole message)
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Ripple wave!",
textAnimation: "ripple",
});
// Combine all three layers
await sdk.messages.sendMessage({
chatGuid: "iMessage;-;+1234567890",
message: "Bold shaking fireworks!",
textStyles: [{ start: 0, end: 4, bold: true }],
textAnimation: "shake",
effectId: "com.apple.messages.effect.CKFireworksEffect",
});Text Style Properties (per range):
| Property | Type | Description |
|---|---|---|
start |
number | Start index |
end |
number | End index |
bold |
boolean | Bold |
italic |
boolean | Italic |
underline |
boolean | Underline |
strikethrough |
boolean | Strikethrough |
Text Animations (whole message):
textAnimation |
Description |
|---|---|
"big" |
Big |
"small" |
Small |
"shake" |
Shake |
"nod" |
Nod |
"explode" |
Explode |
"ripple" |
Ripple |
"bloom" |
Bloom |
"jitter" |
Jitter |
Example: message-styled.ts
// Get a single message
const message = await sdk.messages.getMessage("message-guid");
// Query messages
const messages = await sdk.messages.getMessages({
chatGuid: "iMessage;-;+1234567890",
limit: 50,
offset: 0,
sort: "DESC", // DESC = newest first, ASC = oldest first
before: Date.now(),
after: Date.now() - 86400000, // Last 24 hours
});
// Search messages
const results = await sdk.messages.searchMessages({
query: "keyword",
chatGuid: "iMessage;-;+1234567890", // Optional
limit: 20,
});
// Get counts
const total = await sdk.messages.getMessageCount();
const sent = await sdk.messages.getSentMessageCount();
const updated = await sdk.messages.getUpdatedMessageCount();await sdk.messages.unsendMessage({
messageGuid: "message-guid-to-unsend",
partIndex: 0, // Optional
});Example: message-unsend.ts
const editedMessage = await sdk.messages.editMessage({
messageGuid: "message-guid-to-edit",
editedMessage: "New text content",
backwardsCompatibilityMessage: "New text content", // Optional, defaults to editedMessage
partIndex: 0, // Optional, defaults to 0
});
console.log(`Edited: ${editedMessage.guid}`);
console.log(`New text: ${editedMessage.text}`);
console.log(`Date edited: ${editedMessage.dateEdited}`);Example: message-edit.ts
await sdk.messages.sendReaction({
chatGuid: "iMessage;-;+1234567890",
messageGuid: "target-message-guid",
reaction: "love", // love, like, dislike, laugh, emphasize, question
partIndex: 0, // Optional
});
// Remove a Tapback (prefix with -)
await sdk.messages.sendReaction({
chatGuid: "iMessage;-;+1234567890",
messageGuid: "target-message-guid",
reaction: "-love", // -love, -like, -dislike, -laugh, -emphasize, -question
});Example: message-reaction.ts
// Trigger message notification
await sdk.messages.notifyMessage("message-guid");
// Get embedded media
const media = await sdk.messages.getEmbeddedMedia("message-guid");Examples: scheduled-message-once.ts | scheduled-message-recurring.ts | scheduled-message-manage.ts
const scheduled = await sdk.scheduledMessages.createScheduledMessage({
type: "send-message",
payload: {
chatGuid: "any;-;+1234567890",
message: "This is a scheduled message!",
method: "apple-script",
},
scheduledFor: Date.now() + 3 * 1000,
schedule: { type: "once" },
});const tomorrow9am = new Date();
tomorrow9am.setDate(tomorrow9am.getDate() + 1);
tomorrow9am.setHours(9, 0, 0, 0);
const daily = await sdk.scheduledMessages.createScheduledMessage({
type: "send-message",
payload: {
chatGuid: "any;-;+1234567890",
message: "Good morning!",
method: "apple-script",
},
scheduledFor: tomorrow9am.getTime(),
schedule: {
type: "recurring",
intervalType: "daily", // hourly, daily, weekly, monthly, yearly
interval: 1,
},
});const scheduledMessages = await sdk.scheduledMessages.getScheduledMessages();
const updated = await sdk.scheduledMessages.updateScheduledMessage(
"scheduled-id",
{
type: "send-message",
payload: {
chatGuid: "any;-;+1234567890",
message: "Updated message!",
method: "apple-script",
},
scheduledFor: Date.now() + 10 * 60 * 1000,
schedule: { type: "once" },
},
);
await sdk.scheduledMessages.deleteScheduledMessage("scheduled-id");Examples: chat-fetch.ts | chat-group.ts | message-typing.ts | background-set.ts | background-remove.ts
const chats = await sdk.chats.getChats({
withLastMessage: true, // Include last message
withArchived: false, // Include archived chats
offset: 0,
limit: 50,
});
// Get chat count
const count = await sdk.chats.getChatCount();const chat = await sdk.chats.getChat("chat-guid", {
with: ["participants", "lastMessage"],
});Get participants from group chats and display them with contact names:
const chats = await sdk.chats.getChats();
const groups = chats.filter((chat) => chat.style === 43); // Filter group chats
// Get contacts for name mapping
const contacts = await sdk.contacts.getContacts();
const nameMap = new Map<string, string>();
for (const c of contacts) {
const name = c.displayName || c.firstName || "";
if (!name) continue;
for (const p of c.phoneNumbers || []) nameMap.set(p.address, name);
for (const e of c.emails || []) nameMap.set(e.address, name);
}
// Display participants
groups.forEach((group) => {
console.log(`Group: ${group.displayName || group.chatIdentifier}`);
group.participants?.forEach((p) => {
const name = nameMap.get(p.address);
const display = name ? `${name} <${p.address}>` : p.address;
console.log(` - ${display} (${p.service})`);
});
});Example: chat-participants.ts
const newChat = await sdk.chats.createChat({
addresses: ["+1234567890", "+0987654321"],
message: "Hello everyone!", // Optional initial message
service: "iMessage", // "iMessage" or "SMS"
method: "private-api", // "apple-script" or "private-api"
});// Mark as read/unread
await sdk.chats.markChatRead("chat-guid");
await sdk.chats.markChatUnread("chat-guid");
// Delete chat
await sdk.chats.deleteChat("chat-guid");// Show "typing..."
await sdk.chats.startTyping("chat-guid");
// Stop showing
await sdk.chats.stopTyping("chat-guid");Example: message-typing.ts
const messages = await sdk.chats.getChatMessages("chat-guid", {
limit: 100,
offset: 0,
sort: "DESC",
before: Date.now(),
after: Date.now() - 86400000,
});// Rename group
await sdk.chats.updateChat("chat-guid", {
displayName: "New Group Name",
});
// Add participant
await sdk.chats.addParticipant("chat-guid", "+1234567890");
// Remove participant
await sdk.chats.removeParticipant("chat-guid", "+1234567890");
// Leave group
await sdk.chats.leaveChat("chat-guid");// Set group icon
await sdk.chats.setGroupIcon("chat-guid", "/path/to/image.jpg");
// Get group icon
const iconBuffer = await sdk.chats.getGroupIcon("chat-guid");
// Remove group icon
await sdk.chats.removeGroupIcon("chat-guid");Example: chat-group.ts
Set, get, or remove custom background images for individual chats:
// Get current background info
const bgInfo = await sdk.chats.getBackground("chat-guid");
console.log(`Has background: ${bgInfo.hasBackground}`);
if (bgInfo.hasBackground) {
console.log(`Background ID: ${bgInfo.backgroundId}`);
console.log(`Image URL: ${bgInfo.imageUrl}`);
}
// Set a background image (using file path)
await sdk.chats.setBackground("chat-guid", {
filePath: "/path/to/image.png",
});
// Set a background image (using base64)
import fs from "node:fs";
const imageBuffer = fs.readFileSync("/path/to/image.png");
await sdk.chats.setBackground("chat-guid", {
fileData: imageBuffer.toString("base64"),
});
// Remove background
await sdk.chats.removeBackground("chat-guid");Examples: background-set.ts | background-remove.ts
Examples: message-attachment.ts | message-audio.ts | message-reply-sticker.ts | attachment-download.ts
const message = await sdk.attachments.sendAttachment({
chatGuid: "iMessage;-;+1234567890",
filePath: "/path/to/file.jpg",
fileName: "custom-name.jpg", // Optional
});const message = await sdk.attachments.sendAttachment({
chatGuid: "iMessage;-;+1234567890",
filePath: "/path/to/audio.m4a",
isAudioMessage: true,
});Example: message-audio.ts
Stickers can be sent in two ways:
Standalone Sticker - Sends as its own message (like sending an image, but with sticker styling):
await sdk.attachments.sendSticker({
chatGuid: "iMessage;-;+1234567890",
filePath: "/path/to/sticker.png",
});Example: message-sticker.ts
Reply Sticker (Tapback Sticker) - Attaches to an existing message bubble:
await sdk.attachments.sendSticker({
chatGuid: "iMessage;-;+1234567890",
filePath: "/path/to/sticker.png",
selectedMessageGuid: "target-message-guid", // Required for reply sticker
stickerX: 0.5, // Position X (0-1), default: 0.5
stickerY: 0.5, // Position Y (0-1), default: 0.5
stickerScale: 0.75, // Scale (0-1), default: 0.75
stickerRotation: 0, // Rotation in radians, default: 0
stickerWidth: 300, // Width in pixels, default: 300
});Example: message-reply-sticker.ts
// Get attachment details
const attachment = await sdk.attachments.getAttachment("attachment-guid");
// Get total count
const count = await sdk.attachments.getAttachmentCount();// Download attachment
const buffer = await sdk.attachments.downloadAttachment("attachment-guid", {
original: true, // Download original file
force: false, // Force re-download
width: 800, // Image width (for thumbnails)
height: 600, // Image height
quality: 80, // Image quality
});
// Download Live Photo video
const liveBuffer =
await sdk.attachments.downloadAttachmentLive("attachment-guid");
// Get blurhash (for placeholders)
const blurhash = await sdk.attachments.getAttachmentBlurhash("attachment-guid");Example: attachment-download.ts
Example: contact-list.ts
const contacts = await sdk.contacts.getContacts();// Get contact card by phone or email
const card = await sdk.contacts.getContactCard("+1234567890");
// {
// firstName: "John",
// lastName: "Doe",
// emails: ["john@example.com"],
// phones: ["+1234567890"],
// ...
// }Share your contact card with a chat:
// chatGuid is the chat identifier (e.g. the `guid` field you get from chat APIs/events)
// Check whether the SDK recommends sharing your contact card in this chat.
//
// Returns:
// - true: sharing is recommended (typically when the other side shared theirs and you haven't shared yours yet)
// - false: NOT recommended (e.g. you've already shared, OR the other side hasn't shared theirs yet)
const shouldShare = await sdk.contacts.shouldShareContact("chat-guid");
if (shouldShare) {
// Share your contact card (iMessage "Share Name and Photo")
await sdk.contacts.shareContactCard("chat-guid");
}Example: message-contact-card.ts
Examples: service-check.ts | handle-query.ts
A Handle represents a messaging address (phone number or email).
// Query handles
const result = await sdk.handles.queryHandles({
address: "+1234567890", // Optional, filter by address
with: ["chats"], // Optional, include related chats
offset: 0,
limit: 50,
});
// Get single handle
const handle = await sdk.handles.getHandle("handle-guid");
// Get total count
const count = await sdk.handles.getHandleCount();Check if a phone/email supports iMessage or FaceTime:
// First parameter is the address (phone or email), not handle guid
const hasIMessage = await sdk.handles.getHandleAvailability(
"+1234567890",
"imessage",
);
const hasFaceTime = await sdk.handles.getHandleAvailability(
"+1234567890",
"facetime",
);
// Choose service based on availability
const chatGuid = hasIMessage ? `iMessage;-;+1234567890` : `SMS;-;+1234567890`;Example: service-check.ts
const focusStatus = await sdk.handles.getHandleFocusStatus("handle-guid");Examples: message-stats.ts | server-info.ts
const info = await sdk.server.getServerInfo();
// {
// os_version: "14.0",
// server_version: "1.0.0",
// private_api: true,
// helper_connected: true,
// detected_icloud: "user@icloud.com",
// ...
// }const stats = await sdk.server.getMessageStats();
// {
// total: 12345,
// sent: 5000,
// received: 7345,
// last24h: 50,
// last7d: 300,
// last30d: 1000,
// }// All media stats
const mediaStats = await sdk.server.getMediaStatistics();
// Per-chat media stats
const chatMediaStats = await sdk.server.getMediaStatisticsByChat();const logs = await sdk.server.getServerLogs(100); // Get last 100 logsExamples: poll-create.ts | poll-vote.ts | poll-unvote.ts | poll-add-option.ts
const pollMessage = await sdk.polls.create({
chatGuid: "iMessage;-;+1234567890",
title: "What should we do?", // Optional
options: ["Option A", "Option B", "Option C"],
});
console.log("Poll GUID:", pollMessage.guid);Example: poll-create.ts
await sdk.polls.addOption({
chatGuid: "iMessage;-;+1234567890",
pollMessageGuid: "poll-message-guid",
optionText: "New Option D",
});Example: poll-add-option.ts
// Vote on a poll option
await sdk.polls.vote({
chatGuid: "iMessage;-;+1234567890",
pollMessageGuid: "poll-message-guid",
optionIdentifier: "option-uuid", // UUID of the option to vote for
});
// Remove your vote
await sdk.polls.unvote({
chatGuid: "iMessage;-;+1234567890",
pollMessageGuid: "poll-message-guid",
optionIdentifier: "option-uuid",
});Examples: poll-vote.ts | poll-unvote.ts
Use the poll-utils helper functions to parse and display poll messages:
import {
isPollMessage,
isPollVote,
parsePollDefinition,
parsePollVotes,
getPollSummary,
getOptionTextById,
} from "@photon-ai/advanced-imessage-kit";
sdk.on("new-message", (message) => {
if (isPollMessage(message)) {
if (isPollVote(message)) {
// Parse vote data
const voteData = parsePollVotes(message);
console.log("Votes:", voteData?.votes);
// Get option text for each vote
voteData?.votes.forEach((vote) => {
const optionText = getOptionTextById(vote.voteOptionIdentifier);
console.log(`${vote.participantHandle} voted for "${optionText}"`);
});
} else {
// Parse poll definition
const pollData = parsePollDefinition(message);
console.log("Poll title:", pollData?.title);
console.log("Options:", pollData?.options);
}
// Or get a formatted summary
console.log(getPollSummary(message));
}
});Note: Poll definitions are automatically cached when received. When a vote arrives, the SDK looks up the corresponding option text from the cache. If you receive a vote for a poll that was created before the SDK started, the option text won't be available and will show the UUID instead.
Examples: findmy-friends.ts | findmy-watch.ts
// Refresh and get friends' locations
const locations = await sdk.icloud.refreshFindMyFriends();
// Each location contains:
// - handle: phone number or email
// - coordinates: [latitude, longitude]
// - long_address: street address (optional)
// - expiry: timestamp when location expires (optional)
// Find specific friend
const friend = locations.find((loc) => loc.handle === "+1234567890");
if (friend) {
console.log(
`Coordinates: ${friend.coordinates[0]}, ${friend.coordinates[1]}`,
);
console.log(
`Maps: https://maps.google.com/?q=${friend.coordinates[0]},${friend.coordinates[1]}`,
);
if (friend.long_address) console.log(`Address: ${friend.long_address}`);
}
// List all friends
console.log(`All Friends (${locations.length}):`);
for (const loc of locations) {
console.log(`${loc.handle}: ${loc.coordinates[0]}, ${loc.coordinates[1]}`);
}Example: findmy-friends.ts
Watch friends' location changes in real-time. Fetches initial locations on connect, then listens for live updates via the new-findmy-location event (server auto-refreshes every 30s):
import type { FindMyLocationItem } from "@photon-ai/advanced-imessage-kit";
// Fetch initial locations on ready
sdk.on("ready", async () => {
const locations = await sdk.icloud.refreshFindMyFriends();
for (const loc of locations) {
console.log(`${loc.handle}`);
console.log(` Coordinates: ${loc.coordinates[0]}, ${loc.coordinates[1]}`);
console.log(
` Maps: https://maps.google.com/?q=${loc.coordinates[0]},${loc.coordinates[1]}`,
);
if (loc.long_address) console.log(` Address: ${loc.long_address}`);
}
});
// Listen for real-time location updates
sdk.on("new-findmy-location", (location: FindMyLocationItem) => {
console.log(`${location.handle} updated:`);
console.log(
` Coordinates: ${location.coordinates[0]}, ${location.coordinates[1]}`,
);
});Example: findmy-watch.ts
Examples: listen-simple.ts | listen-advanced.ts | auto-reply-hey.ts
The SDK receives real-time events from the server via Socket.IO.
sdk.on("ready", () => {
console.log("SDK connected and ready");
});
sdk.on("disconnect", () => {
console.log("Disconnected");
});
sdk.on("error", (error) => {
console.error("Error:", error);
});// New message
sdk.on("new-message", (message) => {
console.log("New message:", message.text);
console.log("From:", message.handle?.address);
console.log("From me:", message.isFromMe);
});
// Message status update (delivered, read, etc.)
sdk.on("updated-message", (message) => {
if (message.dateRead) console.log("Message read");
else if (message.dateDelivered) console.log("Message delivered");
});
// Send failed
sdk.on("message-send-error", (data) => {
console.error("Send failed:", data);
});// Chat read status changed
sdk.on("chat-read-status-changed", ({ chatGuid, read }) => {
console.log(`Chat ${chatGuid} marked as ${read ? "read" : "unread"}`);
});sdk.on("typing-indicator", ({ display, guid }) => {
console.log(`${guid} ${display ? "is typing" : "stopped typing"}`);
});sdk.on("group-name-change", (message) => {
console.log("Group renamed to:", message.groupTitle);
});
sdk.on("participant-added", (message) => {
console.log("Someone joined the group");
});
sdk.on("participant-removed", (message) => {
console.log("Someone was removed from the group");
});
sdk.on("participant-left", (message) => {
console.log("Someone left the group");
});
sdk.on("group-icon-changed", (message) => {
console.log("Group icon changed");
});
sdk.on("group-icon-removed", (message) => {
console.log("Group icon removed");
});sdk.on("new-findmy-location", (location) => {
console.log(`${location.handle} location updated:`, location.coordinates);
});const handler = (message) => console.log(message);
sdk.on("new-message", handler);
// Remove specific listener
sdk.off("new-message", handler);
// Remove all listeners
sdk.removeAllListeners("new-message");// Graceful shutdown
process.on("SIGINT", async () => {
await sdk.close();
process.exit(0);
});The SDK includes built-in message deduplication to prevent processing duplicates during network instability:
// Clear processed messages (prevent memory leaks)
sdk.clearProcessedMessages(1000);
// Get processed message count
const count = sdk.getProcessedMessageCount();try {
await sdk.messages.sendMessage({
chatGuid: "invalid-guid",
message: "test",
});
} catch (error) {
if (error.response?.status === 404) {
console.error("Chat not found");
} else {
console.error("Send failed:", error.message);
}
}When sending to a contact you've never messaged before, the SDK automatically creates the chat:
// Works even without existing chat history
await sdk.messages.sendMessage({
chatGuid: "any;-;+1234567890",
message: "Hi, this is John",
});
// SDK detects the chat doesn't exist, creates it, then sendsRun any example with Bun:
bun run examples/<filename>.ts| File | Description |
|---|---|
| listen-simple.ts | Listen with formatted output |
| listen-advanced.ts | Listen with full JSON and startup info |
| message-send.ts | Send text messages |
| message-attachment.ts | Send attachments |
| message-audio.ts | Send audio messages |
| File | Description |
|---|---|
| message-reply.ts | Reply to messages |
| message-unsend.ts | Unsend messages |
| message-edit.ts | Edit messages |
| message-reaction.ts | Send Tapbacks |
| message-effects.ts | Message effects |
| message-styled.ts | Text styles & animations |
| message-search.ts | Search messages |
| message-history.ts | Message history |
| message-destination-caller-id.ts | Destination caller ID |
| File | Description |
|---|---|
| chat-fetch.ts | Get chat list |
| chat-participants.ts | Get group participants |
| chat-group.ts | Manage groups |
| message-typing.ts | Typing indicators |
| background-set.ts | Set chat background |
| background-remove.ts | Remove chat background |
| File | Description |
|---|---|
| contact-list.ts | Get contacts |
| message-contact-card.ts | Share contact card |
| service-check.ts | Check iMessage availability |
| message-service-check.ts | Monitor message service types |
| File | Description |
|---|---|
| attachment-download.ts | Download attachments |
| message-sticker.ts | Send standalone stickers |
| message-reply-sticker.ts | Send reply stickers |
| File | Description |
|---|---|
| poll-create.ts | Create polls |
| poll-vote.ts | Vote on polls |
| poll-unvote.ts | Unvote on polls |
| poll-add-option.ts | Add poll options |
| File | Description |
|---|---|
| server-info.ts | Server info and logs |
| message-stats.ts | Message statistics |
| findmy-friends.ts | Find My Friends |
| findmy-watch.ts | Find My Watch |
| auto-reply-hey.ts | Auto reply bot |
Download llms.txt for language model context:
MIT License
