Inbox
What you can send and receive on iMessage: media, voice notes, effects, reactions, edit and unsend, group chats and the SMS/RCS fallback
iMessage conversations live in the unified inbox. Sending is the same POST /v1/inbox/conversations/{conversationId}/messages call as every other channel, with accountId set to the sender's account; iMessage adds a few fields of its own.
What you can send
| Feature | Supported |
|---|---|
| Text | Yes, up to 10,000 characters. Inline markup renders as rich text: *bold*, _italic_, __underline__, ~strikethrough~ |
| Images, videos, files | Yes, up to 10 attachments per message, each a public https URL of at most 256 characters |
| Voice notes | Yes with voiceNote: true on an audio attachment; dashboard recordings are transcoded to what Apple plays natively |
| Location pin | Yes via location; renders as a native map bubble |
| Contact card | Yes with contactCard: true; shares the sender's own card, set on the sender first |
| Subject | Yes, subject renders as a bold title line above the text |
| Effects | Yes, effect plays an Apple screen or bubble animation: slam, loud, gentle, invisibleInk, echo, spotlight, balloons, confetti, love, lasers, fireworks, shootingStar, celebration |
| Replies | Yes via replyTo |
| Link previews | On by default; linkPreview: false sends links as plain text |
| Channel override | channel forces imessage, sms, rcs or whatsapp for one send; leave it unset so the provider picks per contact |
| Typing indicator and read receipts | Yes, inside an active two-way conversation |
subject, effect, contactCard and channel are accepted on the JSON body only and return 400 on other platforms.
Edit and unsend
An outbound message can be edited within 15 minutes and unsent within 2 minutes of sending, Apple's own limits. PATCH …/messages/{messageId} with text edits it and keeps the edit history on the stored message; DELETE …/messages/{messageId} unsends it and leaves a tombstone. Outside the window the calls return 409 with edit_window_expired or unsend_window_expired.
Reactions
Apple's six tapbacks (❤️ 👍 👎 😂 ‼️ ❓) render natively; any other emoji is sent as a custom emoji tapback, which iOS 18 and later display. Inbound reactions arrive on the reaction.received webhook and on the message's reactions, keyed per reactor, with the attachment index when the reaction targeted one attachment of a multi-attachment message. See Add message reaction.
What you receive
Inbound messages fire message.received and carry, in metadata, the channel the message arrived on, the message type (text, audio, attachments, sticker, location), the reply thread id, a detected language code, the transcript of a voice message, and any rich-text markup as markdownText. A shared location or sticker arrives without coordinates; a Maps link in the text is parsed into a location when present. A FaceTime call attempt shows up in the thread as a call-typed message. Inbound media is copied to Zernio storage so the URLs outlive the provider's retention.
Delivery follows message.delivered and message.failed; a send the provider defers to respect sending intervals sits at queued until it goes out.
Group chats
Group threads arrive on their own conversation with isGroup: true; replying uses the normal send call. GET /v1/imessage/groups/{conversationId} returns the participants, PATCH renames the group or changes its photo, and POST / DELETE …/participants add and remove people. Starting a group from a sender is POST /v1/imessage/groups: it is asynchronous, so the thread appears on the first group webhook. Group writes are applied by the provider in the background; a 200 means accepted.
Messaging new contacts
A sender you order through Zernio can message contacts who never wrote to it. Apple paces those: keep about 15 minutes between messages to different new contacts, and keep the first message free of links, phone numbers, emails, prices and attachments, or it is rejected. Contacts who have written to you can be replied to without any interval. A send to a contact who has opted out returns 409 with recipient_opted_out; see Opt-in & Audience.