Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/photon-hq/advanced-imessage-kit/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Advanced iMessage Kit SDK supports sending and receiving various types of attachments including images, videos, documents, stickers, and audio messages.

Sending Attachments

1

Prepare the file

Ensure the file exists on your filesystem.
import fs from "fs";
import path from "path";

const filePath = path.join(__dirname, "test-image.png");

if (!fs.existsSync(filePath)) {
  console.error("File not found!");
  process.exit(1);
}
2

Send the attachment

Use the attachments.sendAttachment() method.
const message = await sdk.attachments.sendAttachment({
  chatGuid: "iMessage;-;+1234567890",
  filePath: filePath
});

console.log(`Sent: ${message.guid}`);
3

Check the response

Verify the attachment was sent successfully.
if (message.attachments && message.attachments.length > 0) {
  const attachment = message.attachments[0];
  console.log(`Filename: ${attachment.transferName}`);
  console.log(`MIME type: ${attachment.mimeType}`);
  console.log(`Size: ${(attachment.totalBytes / 1024).toFixed(2)} KB`);
}

Complete Attachment Example

import fs from "fs";
import path from "path";
import { AdvancedIMessageKit } from "@photon-ai/advanced-imessage-kit";

const sdk = new AdvancedIMessageKit({
  serverUrl: "http://localhost:1234",
  apiKey: "your-api-key"
});

const CHAT_GUID = "iMessage;-;+1234567890";
const filePath = path.join(__dirname, "test-image.png");

sdk.on("ready", async () => {
  if (!fs.existsSync(filePath)) {
    console.error(`File not found: ${filePath}`);
    await sdk.close();
    process.exit(1);
  }

  const fileName = path.basename(filePath);
  const fileSize = (fs.statSync(filePath).size / 1024).toFixed(2);
  console.log(`Sending ${fileName} (${fileSize} KB)`);

  try {
    const message = await sdk.attachments.sendAttachment({
      chatGuid: CHAT_GUID,
      filePath: filePath
    });

    console.log(`Sent: ${message.guid}`);
    
    if (message.attachments && message.attachments.length > 0) {
      const att = message.attachments[0];
      console.log(`${att.transferName} (${att.mimeType || "unknown"})`);
    }
  } catch (error) {
    console.error("Failed to send attachment:", error.message);
  }

  await sdk.close();
  process.exit(0);
});

await sdk.connect();

Audio Messages

Send audio files as voice messages with the audio message flag.
import path from "path";

const audioPath = path.join(__dirname, "voice-memo.mp3");

const message = await sdk.attachments.sendAttachment({
  chatGuid: "iMessage;-;+1234567890",
  filePath: audioPath,
  isAudioMessage: true // Renders as audio message in iMessage
});

console.log(`Audio message sent: ${message.guid}`);
console.log(`Created: ${new Date(message.dateCreated).toLocaleString()}`);
Setting isAudioMessage: true automatically enables Private API method for proper audio message rendering in iMessage.

Stickers

Send stickers as standalone messages or attached to existing messages.
Send a sticker as its own message (like sending an image).
import path from "path";

const stickerPath = path.join(__dirname, "sticker.png");

const message = await sdk.attachments.sendSticker({
  chatGuid: "iMessage;-;+1234567890",
  filePath: stickerPath
});

console.log(`Sticker sent: ${message.guid}`);
console.log(`Attachments: ${message.attachments?.length || 0}`);

if (message.attachments?.[0]) {
  const att = message.attachments[0];
  console.log(`MIME type: ${att.mimeType}`);
  console.log(`Is sticker: ${att.isSticker}`);
}
Stickers require Private API to be enabled on your server. They will not work with standard API.

Attachment Replies

Send attachments as replies to specific messages.
import path from "path";

// Original message GUID
const originalMessageGuid = "guid-of-message-to-reply-to";
const imagePath = path.join(__dirname, "reply-image.jpg");

const reply = await sdk.attachments.sendAttachment({
  chatGuid: "iMessage;-;+1234567890",
  filePath: imagePath,
  selectedMessageGuid: originalMessageGuid
});

console.log(`Reply with attachment sent: ${reply.guid}`);
console.log(`Replying to: ${originalMessageGuid}`);

Receiving Attachments

Download and process incoming attachments.
1

Find messages with attachments

Query messages and filter for those with attachments.
const messages = await sdk.messages.getMessages({
  chatGuid: "iMessage;-;+1234567890",
  limit: 50,
  with: ["attachment"]
});

const withAttachments = messages.filter(
  m => m.attachments && m.attachments.length > 0
);

console.log(`Found ${withAttachments.length} messages with attachments`);
2

Get attachment details

Retrieve metadata for a specific attachment.
const firstMsg = withAttachments[0];
const attachment = firstMsg?.attachments?.[0];

if (attachment) {
  console.log(`Attachment: ${attachment.transferName}`);
  console.log(`Type: ${attachment.mimeType || "unknown"}`);
  console.log(`Size: ${(attachment.totalBytes / 1024).toFixed(2)} KB`);
  console.log(`GUID: ${attachment.guid}`);
}
3

Download the attachment

Download the file to your local filesystem.
import fs from "fs";
import path from "path";

const buffer = await sdk.attachments.downloadAttachment(attachment.guid, {
  original: true // Get original quality
});

const outputPath = path.join("/tmp", attachment.transferName);
fs.writeFileSync(outputPath, buffer);

console.log(`Saved to: ${outputPath}`);

Complete Download Example

import fs from "fs";
import path from "path";

const CHAT_GUID = "iMessage;-;+1234567890";
const OUTPUT_DIR = "/tmp";

sdk.on("ready", async () => {
  try {
    // Get recent messages with attachments
    const messages = await sdk.messages.getMessages({
      chatGuid: CHAT_GUID,
      limit: 50,
      with: ["attachment"]
    });

    const messagesWithAttachments = messages.filter(
      m => m.attachments && m.attachments.length > 0
    );

    if (messagesWithAttachments.length === 0) {
      console.log("No messages with attachments found");
      await sdk.close();
      process.exit(0);
    }

    console.log(`Found ${messagesWithAttachments.length} messages with attachments\n`);

    // Download the first attachment
    const firstMsg = messagesWithAttachments[0];
    const attachment = firstMsg?.attachments?.[0];

    if (!attachment) {
      console.log("No attachment found");
      await sdk.close();
      process.exit(0);
    }

    console.log(`Attachment: ${attachment.transferName}`);
    console.log(`Type: ${attachment.mimeType || "unknown"}`);
    console.log(`Size: ${(attachment.totalBytes / 1024).toFixed(2)} KB`);
    console.log(`GUID: ${attachment.guid}\n`);

    // Get attachment info
    const info = await sdk.attachments.getAttachment(attachment.guid);
    console.log(`Info retrieved: ${info.transferName}`);

    // Download attachment
    console.log("Downloading...");
    const buffer = await sdk.attachments.downloadAttachment(attachment.guid, {
      original: true
    });

    const outputPath = path.join(OUTPUT_DIR, attachment.transferName);
    fs.writeFileSync(outputPath, buffer);
    console.log(`Saved to: ${outputPath}`);

    // Get blurhash if it's an image
    if (attachment.mimeType?.startsWith("image/")) {
      try {
        const blurhash = await sdk.attachments.getAttachmentBlurhash(attachment.guid);
        console.log(`Blurhash: ${blurhash}`);
      } catch {
        console.log("Blurhash not available");
      }
    }

    // Check for Live Photo
    if (attachment.hasLivePhoto) {
      console.log("\nDownloading Live Photo video...");
      const liveBuffer = await sdk.attachments.downloadAttachmentLive(attachment.guid);
      const livePath = path.join(OUTPUT_DIR, `${path.parse(attachment.transferName).name}_live.mov`);
      fs.writeFileSync(livePath, liveBuffer);
      console.log(`Live Photo saved to: ${livePath}`);
    }

    // Get total attachment count
    const totalCount = await sdk.attachments.getAttachmentCount();
    console.log(`\nTotal attachments in database: ${totalCount}`);
  } catch (error) {
    console.error("Failed to download attachment:", error);
  }

  await sdk.close();
  process.exit(0);
});

await sdk.connect();

Download Options

Customize how attachments are downloaded.
const buffer = await sdk.attachments.downloadAttachment(attachmentGuid, {
  original: true
});

Live Photos

Download the video component of Live Photos.
import fs from "fs";
import path from "path";

const attachment = message.attachments?.[0];

if (attachment?.hasLivePhoto) {
  console.log("This is a Live Photo!");
  
  // Download the image
  const imageBuffer = await sdk.attachments.downloadAttachment(attachment.guid, {
    original: true
  });
  fs.writeFileSync("live-photo.jpg", imageBuffer);
  
  // Download the video
  const videoBuffer = await sdk.attachments.downloadAttachmentLive(attachment.guid);
  fs.writeFileSync("live-photo.mov", videoBuffer);
  
  console.log("Live Photo downloaded (image + video)");
}

Blurhash

Generate blurhash strings for image placeholders.
const attachment = message.attachments?.[0];

if (attachment?.mimeType?.startsWith("image/")) {
  try {
    const blurhash = await sdk.attachments.getAttachmentBlurhash(attachment.guid);
    console.log(`Blurhash: ${blurhash}`);
    
    // Use blurhash for placeholder while loading full image
  } catch (error) {
    console.log("Blurhash not available for this image");
  }
}
Blurhash is a compact representation of an image placeholder. It’s useful for showing a preview while the full image loads.

Attachment Count

Get the total number of attachments in your database.
const totalAttachments = await sdk.attachments.getAttachmentCount();
console.log(`Total attachments: ${totalAttachments}`);

Listening for New Attachments

Receive attachments in real-time as they arrive.
import fs from "fs";
import path from "path";

sdk.on("new-message", async (message) => {
  // Check if message has attachments
  if (!message.attachments || message.attachments.length === 0) {
    return;
  }

  console.log(`\nNew message with ${message.attachments.length} attachment(s)`);
  
  for (const attachment of message.attachments) {
    console.log(`  - ${attachment.transferName} (${attachment.mimeType})`);
    
    try {
      // Auto-download image attachments
      if (attachment.mimeType?.startsWith("image/")) {
        const buffer = await sdk.attachments.downloadAttachment(attachment.guid, {
          original: true
        });
        
        const savePath = path.join("/tmp/downloads", attachment.transferName);
        fs.writeFileSync(savePath, buffer);
        
        console.log(`    Saved to: ${savePath}`);
      }
    } catch (error) {
      console.error(`    Failed to download: ${error.message}`);
    }
  }
});

Custom Filenames

Specify custom filenames when sending attachments.
import path from "path";

const filePath = path.join(__dirname, "image.jpg");

const message = await sdk.attachments.sendAttachment({
  chatGuid: "iMessage;-;+1234567890",
  filePath: filePath,
  fileName: "vacation-photo.jpg" // Custom filename
});

console.log(`Sent as: ${message.attachments?.[0]?.transferName}`);

Supported File Types

The SDK supports all file types that iMessage supports:
  • Images: JPG, PNG, GIF, HEIC, HEIF
  • Videos: MOV, MP4, M4V
  • Audio: MP3, M4A, WAV, AAC
  • Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX
  • Archives: ZIP, RAR
  • Other: Any file type iMessage can handle
Large files may take longer to upload. Consider showing upload progress to users in production applications.

Error Handling

Handle common attachment errors gracefully.
try {
  const message = await sdk.attachments.sendAttachment({
    chatGuid: CHAT_GUID,
    filePath: filePath
  });
  
  console.log("Attachment sent successfully");
} catch (error) {
  if (error.code === "ENOENT") {
    console.error("File not found");
  } else if (error.response?.status === 413) {
    console.error("File too large");
  } else if (error.response?.status === 415) {
    console.error("Unsupported file type");
  } else {
    console.error("Failed to send attachment:", error.message);
  }
}

Next Steps

Sending Messages

Learn more about message sending features

Best Practices

Optimize your attachment handling

Build docs developers (and LLMs) love