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: a fixed tapback set, typing only soon after the person's last message, edits for 15 minutes and unsend for two. Keep a plain-text fallback on.

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. iMessage has a fixed set, so Flow maps what you send to the closest one. 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));
}

With fallback: "auto", which react() sets, Flow uses the closest tapback or skips the reaction and says so in delivered_as. Keep the fallback on because the exact set of reactions a line can send may vary.

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 within five minutes of the contact’s last message. 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. Mark the conversation read when your agent starts work, which is what a person would do.

On Flow, typing indicators are iMessage-only, need an existing conversation and are best-effort. They work within five minutes of the person’s last message.

Effects

Effects send text with an iMessage bubble or screen effect:

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

await event.conversation.send({ content: effect("Your order is confirmed!", "confetti"), fallback: "auto" });

Flow lists these effects: slam, loud, gentle, invisible_ink, echo, spotlight, balloons, confetti, love, lasers, fireworks, shooting_star and celebration. Which ones a line can send may vary, so keep fallback: "auto", which sends plain text instead.

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. Use the documented fallback behavior so your agent remains useful when a particular effect is unavailable.

Frequently asked questions

Can I send iMessage tapbacks through an API?

Yes. On Flow a reaction becomes a tapback. iMessage has a fixed set, so with fallback set to auto Flow uses the closest tapback, or skips the reaction and says so in the delivered_as field.

Can an API show the typing indicator?

Yes. On Flow it works within five minutes of the contact's last message. 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, shooting star and celebration. Which ones a line can send may vary, so keep a plain-text fallback on.

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