Introduction

Send and receive iMessage from your own code — one HTTP API, one event stream.

Mapier gives your application a real iMessage presence. You send messages, react to them, start group chats and receive everything people send back — over plain HTTP, from any language, with a sandbox to rehearse against before a real number is involved.

There is no SDK to install. Every example in these docs is a curl command or a fetch call you can run right now, and the whole surface is one OpenAPI document at https://api.mapier.ai/openapi.json for any generator you already use. If a coding agent is writing that code, point it at these docs — every page is also published as plain markdown, and two things about this API reliably trip a model up.

curl https://api.mapier.ai/v1/commands/message.send \
  -H "Authorization: Bearer $MAPIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target": { "kind": "recipient", "channel": "imessage", "recipientExternalId": "+14155550100" },
    "payload": { "text": "Your table is ready." }
  }'

How it works

The API has two halves, and understanding the split makes everything else straightforward.

You send commands. Every action — sending a message, adding a reaction, starting a group — is a POST to one endpoint with a target (who) and a payload (what). The response is 202 Accepted, meaning the command was durably queued.

You read results from one stream. A single server-sent events connection tells you how each command settled and carries every inbound message, and — when you ask — each delivery or read receipt and each "not delivered" verdict. Every frame carries an id:, and reconnecting with Last-Event-ID resumes where you left off, so a drop costs a reconnect and nothing more. That is why the quickstart has you open the stream before sending anything. For message.send, succeeded is the transport's settlement, not a delivery receipt; receipts are their own frames — see Receipts and delivery verdicts.

A 202 means queued, not delivered. That one sentence explains most of the surprises in this API — keep the stream open and you will not be surprised by any of them.

What you can build

  • Support and sales conversations that live where customers already are, with a human or an agent on your side of the thread.
  • Transactional notifications — order updates, appointment reminders, delivery windows — as a real conversation rather than a no-reply channel.
  • Group coordination: start a group chat with everyone a piece of work needs, and its opening message, in one request.
  • Lightweight acknowledgements: a tapback on a customer's message, so they know it was seen before the full answer arrives.

Start here

What the API does today

Being straight about the edges saves you finding them the hard way. A row that reads Not available yet is a row you would otherwise have to establish by absence.

Channels

Eleven channels are named on the wire; one carries traffic today. "Not available yet" is a statement about the live path. In test, a project's sandbox world starts with an iMessage line, and a send on a channel the world holds no line for is refused.

ChannelchannelState
iMessageimessageAvailable
RCSrcsNot available yet
SMSsmsNot available yet
WhatsAppwhatsappNot available yet
VoicevoiceNot available yet
TelegramtelegramNot available yet
SignalsignalNot available yet
Apple Businessapple_businessNot available yet
DiscorddiscordNot available yet
SlackslackNot available yet
MessengermessengerNot available yet

Platform

CapabilityState
Separate live and test keys (mp_live_ / mp_test_), with nothing shared between the twoAvailable
The sandbox: a fake iMessage world per project, with a phone you hold as the contactAvailable
Idempotency-Key on every command in both environments, except group.create, typing.start and message.read on a live lineAvailable
Signed webhooks, with retries and console redeliveryAvailable
Response stream: message and command frames, receipt, delivery_failed, location, moderation and poll on request, resumable with Last-Event-IDAvailable
Sending text; tapback reactions; the typing bubble; marking a conversation read; creating groups; editing and unsending the line's own messages; reading and setting the line's name and photo; sharing the contact card; voting on pollsAvailable
Sending into a group, renaming it, changing its members or leaving itAvailable on an iMessage line, in a group chat the transport has reported: a send reaches every member, and group.update renames the group or adds or removes one member. A leave cannot be undone, and its success means it was sent, not proven. A group photo is not carried yet, and a test line has no group chat. See Groups
Setting and removing a conversation's backgroundAvailable on an iMessage line, from the published presets, in a conversation the transport has confirmed is with one person or a group chat it has reported. On a live line a change in a one-to-one conversation also arrives as a message with no text, which your handler should skip. See chat_background.set
Sending effects, subject lines, threaded replies, rich links and stickers with message.sendAvailable on an iMessage line into a conversation the contact has written into — effects, subjects and replies beside text, a photo or file by https link (media), an emoji sticker, a rich_link, a multipart (text and photos as one message), a location_request and a poll in place of it, and bold, animated or mention ranges with textFormatting. See What a line carries
Receiving messages and their attachments on the stream; new conversations by webhookAvailable. A contact's shared location and their edits and unsends are frames on request, ?events=locations and ?events=moderation, and webhooks you subscribe to by name.
Delivered, read and "not delivered"Available, on request: the stream's receipt and delivery_failed frames, the matching webhooks, and GET /v1/messages/{messageId}/receipts to ask about one message now. succeeded on a send is not a receipt.
Reading a conversation's historyAvailable: GET /v1/conversations/{conversationId}/messages
Message templatesNot available yet
Receiving reactionsAvailable as the reaction.added and reaction.removed webhooks, not a stream frame. Tapbacks in a group chat are not delivered yet

Conventions in these docs

Phone numbers are E.164 (+14155550100) and email addresses are lowercase. Examples use the reserved +1415555xxxx range, so nothing here can dial a real person. Where a detail is not yet settled, you will see a callout saying so rather than a confident guess.

On this page