BlueBubbles (iMessage)
iMessage bridge via a self-hosted BlueBubbles server on a Mac. Requires running Mac infrastructure; highest setup cost of all providers.
⚠️ Requires a Mac with BlueBubbles server installed and signed into the iMessage account. Authentication is a single shared password, no HMAC. Best fit when you already operate a Mac as a notification bridge (security team, ops team, etc.).
What you get
- Outbound text via
POST {server}/api/v1/message/text?guid=<password>with{chatGuid, message}. Reply-to (quoted replies) viaselectedMessageGuidis supported. - Inbound webhook at
/webhooks/bluebubblesfor thenew-messageevent. BlueBubbles is a "register-and-receive" model: Minara registers a webhook URL on the BlueBubbles server on first outbound, then receives events for every new message. - Text only. Image and attachment uploads via
/api/v1/message/attachmentare deferred. - 16384-char text limit.
Setup
1. Install BlueBubbles server
Follow the official BlueBubbles server install guide:
- Download the BlueBubbles macOS app
- Sign the Mac into the iMessage Apple ID you want to bridge
- Configure a strong server password (this becomes
BLUEBUBBLES_PASSWORD) - Expose the server publicly. BlueBubbles supports:
- Ngrok (built-in integration)
- Cloudflare Tunnel
- Manual port forwarding on a static IP
- Copy the public URL from the BlueBubbles app's "Status" tab.
That becomes
BLUEBUBBLES_SERVER_URL.
2. Find a default chat GUID
In BlueBubbles desktop UI, open the target conversation. The "Info"
panel shows the chat GUID, formatted like
iMessage;-;+15551234567 (1:1) or
iMessage;+;chat<long hex>@imsgr.icloud.com (group). Save as
BLUEBUBBLES_DEFAULT_CHAT_GUID.
3. Configure Minara
minara auth messaging add
# pick `bluebubbles` from the list.Or set env vars:
BLUEBUBBLES_SERVER_URL=https://your-tunnel.ngrok.app
BLUEBUBBLES_PASSWORD=<server password>
BLUEBUBBLES_DEFAULT_CHAT_GUID=iMessage;-;+155512345674. Test
minara auth messaging test bluebubblesThe target chat receives "✅ Minara gateway test ping". If iMessage fallback to SMS is on, your phone bill picks up the SMS leg.
Inbound webhook
BlueBubbles is the only provider in the registry that uses a pure
shared-password authentication (no HMAC, no JWT). The server sends
the password in either the URL query (?guid=<pw>) or in the JSON
body (password / token field). Minara accepts both shapes and
does a constant-time comparison.
The webhook is set up automatically on the BlueBubbles server side (BlueBubbles' admin UI: "Settings" → "Webhooks" → "Add Webhook"):
URL: https://<your-host>/webhooks/bluebubbles
Events: new-messageInbound payload shape:
{
"type": "new-message",
"data": {
"guid": "<message guid>",
"text": "hello from iMessage",
"handle": { "address": "+15559876543" },
"chats": [{ "guid": "iMessage;-;+15559876543" }],
"dateCreated": 1700000000000,
"isFromMe": false
}
}isFromMe: true events are filtered as self-loops. Other event types
(updated-message, typing-indicator, etc.) are not parsed.
Limits & caveats
- Requires running a Mac with iMessage signed in. Production reliability hinges on Mac uptime and Apple's iMessage service state.
- Password-only auth. Treat
BLUEBUBBLES_PASSWORDas a long shared secret; rotate periodically. No HMAC means a leaked password is full impersonation. - Apple iMessage rate limits apply. Sending too fast triggers carrier or Apple-side throttling; BlueBubbles surfaces these as send failures.
- No attachments yet. Sending images / files via the gateway is a follow-up enhancement.
Troubleshooting
"BlueBubbles server unreachable"
- The tunnel (ngrok / cloudflared) on the Mac side dropped. Restart
the tunnel and refresh
BLUEBUBBLES_SERVER_URLif the public URL changed.
"401 / 403 on outbound"
BLUEBUBBLES_PASSWORDdoes not match the server's saved password. Open BlueBubbles desktop app → Settings → Server Settings → reset password and update env.
"Test message did not arrive on the target phone"
- iMessage is on a per-Apple-ID basis. Confirm the Mac is signed
into the right Apple ID and
Messages.appshows the chat as active. - If the recipient is on a non-Apple device, iMessage falls back to SMS (carrier dependent).
"Inbound webhook not firing"
- BlueBubbles' webhook registration is per-server, not per-client. Open the BlueBubbles admin UI and confirm the webhook URL points at your Minara host.
Reference
- Env vars:
BLUEBUBBLES_* - Outbound:
apps/agent/src/messaging/bluebubbles.ts - Inbound spec:
apps/agent/src/messaging/inbound/specs/bluebubbles.ts - BlueBubbles project: bluebubbles.app
- REST API: docs.bluebubbles.app / REST API & Webhooks