Skip to content
iMessage APIs
Operations10 min read

How to send an iMessage programmatically

There is no `POST /imessage` from Apple. There are four workarounds, they are not equivalent, and the one that shows up first in search results is the one that breaks first.

The question is simple: a thing happened in your system — an order shipped, an appointment was booked, a lead filled in a form — and you want an iMessage to go out without a human opening Messages and typing it.

Apple does not sell that. There is no endpoint, no SDK, no entitlement you can apply for. The full explanation of why is here, but the practical consequence is that every method below is a workaround of some kind, and they differ enormously in how much weight they will hold.

The four methods, ranked by durability

MethodSetupHolds up in production?Cost
AppleScript on a Mac you ownMinutesNo — single point of failure, no delivery signalFree (plus a Mac)
Self-hosted bridge (BlueBubbles)An afternoonPersonal projects onlyFree (plus a Mac and your attention)
Third-party REST APIAn hourYes — this is what the category exists for$20–$250 per line, per month
Apple Messages for BusinessWeeks to monthsYes, but customer must message firstVia a CSP contract
Ranked by how long they keep working once real volume hits them.

Method 1: AppleScript on a Mac

The answer every search returns first. macOS exposes the Messages app to AppleScript, so a script can hand it a recipient and a body and tell it to send.

applescript
on run argv
  set recipientNumber to item 1 of argv
  set messageBody to item 2 of argv

  tell application "Messages"
    set targetService to 1st account whose service type = iMessage
    set targetBuddy to participant recipientNumber of targetService
    send messageBody to targetBuddy
  end tell
end run

Save as send.applescript and call it with osascript send.applescript "+15551234567" "Your table is ready".

Call it from Node with child_process, from Python with subprocess, from cron, from anything. It genuinely works, and for sending yourself a build notification it is the correct answer.

Why it stops being the correct answer

It sends from your personal Apple ID, so replies land in your own Messages app and nowhere else. It returns no delivery confirmation — the script succeeds whether or not the message arrived. It needs the Mac awake, unlocked, signed in and on the network. macOS updates change Automation permissions and silently break it. And sending business volume from a personal Apple ID is the fastest known route to getting the account flagged.

Method 2: a self-hosted bridge

Projects like BlueBubbles turn a Mac you control into a small server with a real HTTP API and webhook callbacks in front of the Messages database. It is a genuine upgrade over raw AppleScript: you get message IDs, inbound events and a queryable history.

It is still your Apple ID, your hardware, your uptime and your problem at 2am. The full comparison against a paid API is here, along with the wider open-source landscape.

Method 3: a third-party REST API

This is what people mean by "an iMessage API". A provider runs the Apple infrastructure — real accounts, real devices, in a data centre — assigns you a phone number, and puts an HTTP interface in front of it. You send a request; a blue bubble arrives.

bash
curl --request POST 'https://api.sendblue.co/api/send-message' \
  --header 'sb-api-key-id: YOUR_SB_API_KEY_ID' \
  --header 'sb-api-secret-key: YOUR_SB_API_SECRET_KEY' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "number": "+19998887777",
    "content": "Your 2pm window is confirmed.",
    "status_callback": "https://acme.co/webhooks/imessage"
  }'

Sendblue's documented request shape. Every provider's differs in field names, but the structure — auth header, recipient, body, callback URL — is the same everywhere.

What you are buying is not the HTTP call — you could write that yourself. It is the number, the delivery signal, the inbound webhook, the SMS fallback when the recipient is on Android, and somebody else being responsible for keeping the line alive. Which provider and what it costs are separate questions.

Ridge Auto

iMessage

POST /send-message → arrives here, blue, from your assigned number.

Reply → webhook fires against your endpoint

The whole model in two bubbles.

Method 4: Apple Messages for Business

Apple's own programme, and the only officially sanctioned way to hold an iMessage conversation as a business. The catch is structural rather than technical: the customer has to start the conversation. You cannot send the first message. The full guide to what it does and does not allow is here.

Choosing between them

Pick method 3 if any of these are true

  • Delivery failures need to be visible to your system, not silently swallowed.
  • Replies must reach your application, not one person's laptop.
  • The volume is more than a handful of messages a day.
  • Somebody other than you needs it to keep working while you are on holiday.
  • You need the sending number to be a business asset rather than a personal Apple ID.

If none of them are true, AppleScript is free and you should use it. The cost of a paid line is not the message — it is buying out of the failure modes above.

The first thing to build

  1. Open a free sandbox with any provider that offers one — four of the five we cover do.
  2. Send one message to your own phone with curl. Confirm it is blue.
  3. Point status_callback at a request-bin URL and watch the delivery events arrive.
  4. Reply to yourself from the phone and watch the inbound webhook fire.
  5. Only then wire it into your application — from Node or Python.

Four curl commands tell you more about a provider than an hour on their marketing site. Do them before you write an integration, not after.

developerscodegetting started