Now launching iMessage API!Learn more

Products

Ships to

Developer guideiMessage API7 min read

iMessage tapbacks, typing indicators and effects via API

How to send iMessage tapbacks, typing indicators, read receipts, effects, edits and unsends from Flow, with the limits that apply.

The short answer

The details that make an agent feel like iMessage are tapbacks, typing, read receipts and effects. Through an API they work with limits: one emoji per reaction and none in groups, typing and read receipts only for 5 minutes after your line's last message, edits for 15 minutes and unsend for two. Flow converts nothing, so have a plain-text reply ready for what a channel refuses.

Building on the iMessage API? Build on iMessage with Flow: one agent for iMessage, WhatsApp and Telegram. New to it? Read the iMessage API guide.

What an API can send

The things that make an iMessage conversation feel native are small: a typing bubble, a thumbs-up on a message, confetti on an order confirmation. A good iMessage API exposes them, and a good agent uses them sparingly.

Flow’s iMessage features cover what the line supports: text up to 9,999 characters, photos, video and audio, documents, voice notes, tapbacks, typing, read receipts and effects. There are no buttons, lists or templates. If you design an iMessage agent, these are the details that matter.

Tapbacks

Reactions become tapbacks. A reaction is any one emoji, and Flow sends it as written, never swapped for another one. Reactions are not available in groups. This example reacts and then replies:

for await (const event of flow.events.stream({ types: ["message.received"] })) {
  const text = contentText(event.data.message.content);
  await event.conversation.react(event.data.message.id, "👍"); // shows as the Like tapback
  await event.conversation.reply(await askMyAgent(text));
}

react() sends the reaction with no fallback. If the conversation does not take it, as in a group, the call answers 422 unsupported_content and nothing is sent.

Use a tapback to say “got it” while the agent works, not as decoration on every message.

Typing and read receipts

Show typing while the model works. On Flow:

  • Typing shows for up to 60 seconds, and works for 5 minutes after your line’s last message to the contact, not in groups. Send a reply first. Outside that, the call answers 409 outside_window, and you can ignore it.
  • Channels clear the indicator after a few seconds, so keep turning it on until you send.
  • reply() does this for you: it turns typing on, sends bubbles as they are ready and turns it off, even if the stream fails.

Read receipts work for the whole conversation. iMessage has no per-message receipt, so up_to has no effect. Like typing, they work only for 5 minutes after your line’s last message to the contact, so mark the conversation read once your reply has gone.

On Flow, iMessage typing needs an existing conversation, works for 5 minutes after your line’s last message to the person (the person’s message alone does not open it), not in group chats, and is best-effort. It clears itself when your next message goes or after a few seconds, so call it again while your agent works.

Effects

Effects send text with an iMessage bubble or screen effect:

import { effect } from "@flow-engineer/messaging";

await event.conversation.send(effect("Your order is confirmed!", "confetti"));

Flow lists these effects: slam, loud, gentle, invisible_ink, echo, spotlight, balloons, confetti, love, lasers, fireworks and celebration: 12 in all. Effects are iMessage only: on another channel the call answers 422 unsupported_content and nothing is sent, so send plain text there.

An effect is a moment, not a style. Use one for a confirmation, a birthday or a small win, and the rest of the time send plain text.

Edit and unsend

On Flow’s iMessage line:

  • Edit. You can replace the text of a sent message within 15 minutes, but not the message that started the conversation.
  • Unsend. You can remove a message within two minutes.

WhatsApp supports neither, so write the agent so a mistake can be corrected with a new message, not only with an edit. The one-agent guide has the table of what each channel can do.

Build expressive replies with Flow

Flow exposes reactions, typing, effects, edits and unsend through the same conversation API. Flow converts nothing: when a channel does not take a kind, it answers 422 unsupported_content with a hint, so your agent can send plain text instead.

Frequently asked questions

Can I send iMessage tapbacks through an API?

Yes. On Flow a reaction becomes a tapback: any one emoji, sent as written. Reactions are not available in group chats.

Can an API show the typing indicator?

Yes. On Flow it works for 5 minutes after your line's last message to the contact, so send a reply first. Outside that, the call answers 409 outside_window and is safe to ignore. Channels clear the indicator after a few seconds, so keep turning it on while your agent works.

Do read receipts work per message?

No. On Flow, iMessage has no per-message read receipt, so the whole conversation is marked read and the up_to value has no effect.

Which iMessage effects can I send?

Flow lists slam, loud, gentle, invisible ink, echo, spotlight, balloons, confetti, love, lasers, fireworks and celebration: 12 in all. Effects are iMessage only: on another channel the call answers 422 unsupported_content and nothing is sent, so send plain text there.

Can I edit or unsend an iMessage from code?

On Flow you can edit within 15 minutes of sending, but not the message that started the conversation, and unsend within two minutes. WhatsApp does not support either.

Start hereiMessage API: a developer’s guideThe overview of how iMessage APIs work, and what to ask a provider. Developer guideSend iMessage programmaticallycurl, TypeScript and Python: get a key, receive a signed webhook, reply once and handle retries.Developer guideiMessage API without a MacWhy a hosted iMessage API removes the Mac, what the DIY relay costs you, and how to choose.Developer guideiMessage MCP serverTwo things people mean by it: a messaging MCP for your coding agent, and your product as an MCP server.Developer guideiMessage API for Node.js and TypeScriptInstall the SDK, stream inbound messages, verify signed webhooks in Express and reply safely.Developer guideiMessage API for PythonStream inbound events, verify signed webhooks in FastAPI and reply with idempotency keys.Developer guideiMessage API for GoPoll events, reply and verify signed webhooks with the standard library, no SDK needed.

All posts: the Flow blog. The Flow docs have the reference.

From reading to building

Your agent, on iMessage and everywhere else.

Flow gives your agent an iMessage line, and the same code answers on WhatsApp and Telegram and works as an MCP server and CLI. See how it works on iMessage.

Build on iMessage with Flow