Skip to content
iMessage APIs
All answers

For developers

How do you send an iMessage programmatically?

Through a third-party REST provider, which is the only route that survives production. The alternatives are AppleScript on a Mac you own, a self-hosted bridge such as BlueBubbles, or Apple Messages for Business — which is official but can only answer conversations the customer starts.

The four routes

MethodSetupHolds up in production?Cost
Third-party REST APIAbout an hourYes — this is what the category is for$20–$250/line/month
Self-hosted bridge (BlueBubbles)An afternoonPersonal projects onlyFree, plus your uptime
AppleScript on a MacMinutesNo — no delivery signal, no repliesFree
Apple Messages for BusinessWeeks to monthsYes, but inbound-onlyVia a CSP contract

The one-request version

bash
curl --request POST 'https://api.sendblue.co/api/send-message' \\
  --header 'sb-api-key-id: YOUR_KEY_ID' \\
  --header 'sb-api-secret-key: YOUR_SECRET' \\
  --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 shape. Every provider differs in field names and matches in structure.

Why AppleScript stops being the answer

It sends from your personal Apple ID, so replies land in your own Messages app and nowhere else. It returns no delivery confirmation. It needs the Mac awake, unlocked and online. And business volume from a personal Apple ID is the fastest route to getting that account restricted — which affects far more than Messages.

The full guide with working code for each route.

Two responses, not one

StageWhat you getWhat it means
SynchronousA message handle and a statusThe provider accepted it. Nothing has reached a phone.
Webhook: sentHanded to AppleIn flight
Webhook: deliveredApple confirmed the deviceThis is the one worth counting
Webhook: readRecipient opened itOnly if they have read receipts on — never a reliable metric
Webhook: failedWrong number, not on iMessage, or line troubleAlert if the rate moves

Count delivered, not 200 OK

A throttled line usually still returns 200. Your dashboard stays green while delivery quietly collapses. Track delivered events as a ratio of sends and alert on a floor you pick in advance. What to instrument.

Handling the failures correctly

A 429 or a 5xx will very likely succeed in four seconds. A 422 for a recipient not on iMessage will fail identically forever — retrying it wastes your rate limit and never delivers. Route those to SMS fallback instead. Retry logic that works.

This page also answers

  • send imessage api