Now launching iMessage API!Learn more

Products

Ships to

iMessage API Flow Framework

AI agents on iMessage.
Blue bubbles, your code.

Put your agent where your customers already text. Build it with Flow Framework, or connect the one you have through the iMessage API.

Free trial: 25 people on the shared line, no card. See pricing

Illustration: Northside Bikes is made up, not a Flow customer.

  • Typing
  • Read receipts
  • Tapbacks
  • Effects
  • Photos and files
  • Voice notes
  • Group chats
  • SMS/RCS fallback

Two ways to build

Build the agent with Flow, or bring the one you have.

Flow Framework open source · TypeScript

Build the whole agent

Write your agent’s jobs once as typed tools.

terminal
$ npx @flow-engineer/flow new my-agent
$ npx @flow-engineer/flow link --channel imessage
$ npm start
  • iMessage, WhatsApp, Telegram, SMS
  • MCP server and CLI
  • Open source, Apache-2.0

iMessage API any language

Connect the agent you already have

Send and receive iMessage from the code you run today.

terminal
$ npm install @flow-engineer/messaging
# or
$ pip install flow-messaging
  • REST, any language
  • TypeScript and Python SDKs
  • No Mac or iPhone

What it can do

Everything people expect from a text.

01

Typing and read receipts

Show typing while your agent works, and mark messages read.

02

Tapbacks

React with tapbacks or any emoji.

03

Effects and text styles

Twelve effects, from confetti to invisible ink, plus text styles.

04

Photos, files and voice notes

Both ways, with files scanned for malware.

05

Group chats

On a dedicated line, your agent replies in groups people add it to.

06

SMS and RCS fallback

People not on iMessage get SMS or RCS from the same number.

  • Threaded replies
  • Edit and unsend
  • Link previews

How it works

Customers text first. Your agent answers.

  1. 01

    Get a line

    Start on Flow’s shared line, or get your own US number.

  2. 02

    People text you

    Customers text your line from their own phone.

  3. 03

    Your agent replies

    Your agent gets each message and answers in the same chat.

Want your agent to text first? Add Outbound to a dedicated line, +$40/mo.

About Outbound

The API

Webhooks in.
Blue bubbles out.

One endpoint per kind of message: what you send is what the person gets.

  • Simulated contacts and groups
  • Hosted MCP server
  • Live event stream
  • Signed webhooks
  • Idempotent sends

agent.ts

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

const flow = new FlowMessaging(); // reads FLOW_MESSAGING_KEY

// live events, no public URL needed (or use signed webhooks)
for await (const event of flow.events.stream({ types: ["message.received"] })) {
  const chat = event.conversation;
  const text = contentText(event.data.message.content);

  if (chat.type !== "group") {
    await chat.react(event.data.message.id, "👍"); // a Like tapback
  }

  const { reply, booked } = await askMyAgent(text); // your agent, any model
  await chat.reply(reply); // typing, then iMessage-sized bubbles (or pass an LLM stream)
  if (booked) await chat.send(effect("You're booked!", "confetti"));
}

app.py

from fastapi import FastAPI, Request, Response
from flow_messaging import (
    WebhookSignatureError, construct_event, content_text, webhook_reply,
)

app = FastAPI()

@app.post("/flow")
async def flow_webhook(request: Request):
    raw = await request.body()  # the raw body, before parsing
    try:
        # checks Flow-Signature with FLOW_MESSAGING_WEBHOOK_SECRET
        event = construct_event(raw, request.headers.get("Flow-Signature"))
    except WebhookSignatureError:
        return Response(status_code=400)
    if event.type == "message.received":
        text = content_text(event.data.message.content)
        return webhook_reply(ask_my_agent(text))  # sent as the reply
    return {}

terminal

# reply in the conversation (202: queued for the channel)
curl https://api.flow.engineer/v0/conversations/$CONVERSATION_ID/basic \
  -H "Authorization: Bearer $FLOW_MESSAGING_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"text": "Thursday 10:00 or 14:00?"}'

# text with an iMessage effect
curl https://api.flow.engineer/v0/conversations/$CONVERSATION_ID/effect \
  -H "Authorization: Bearer $FLOW_MESSAGING_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"text": "Booked: Thursday 14:00", "effect": "confetti"}'

src/tools.ts · src/agent.ts

// src/tools.ts: what the agent can do, written once
import { tool, z } from "@flow-engineer/flow";

export const tools = [
  tool({
    name: "book_tune_up",
    description: "Book a bike tune-up at the time the customer chose.",
    input: z.object({ day: z.string(), time: z.string() }),
    run: ({ day, time }, { idempotencyKey }) =>
      shop.book({ day, time, idempotencyKey }),
  }),
];

// src/agent.ts: the same agent on iMessage, WhatsApp and Telegram
import { createAgent } from "@flow-engineer/flow";
import { flowMessaging } from "@flow-engineer/flow/flow-messaging";

const fm = flowMessaging(); // reads FLOW_MESSAGING_KEY
const agent = createAgent({
  dir: "./agent", model, tools,
  channels: [fm.imessage(), fm.whatsapp(), fm.telegram()],
});
await agent.resume();
fm.start(agent, { cursorFile: ".flow/flow-messaging-cursor" });

Flow Framework + Flow Cloud

One agent. iMessage and every other chat.

  • No channel plumbingFlow handles each chat app’s webhooks, retries and media.
  • Tested before it shipsSimulated people try every release first.
  • Hosted and tracedDeploy, promote and trace on Flow Cloud.
  • Or self-hostedRun the agent anywhere; Flow keeps the iMessage line.
test, deploy, promote
$ npx @flow-engineer/flow test --synthetic
$ npx @flow-engineer/flow deploy
$ npx @flow-engineer/flow deploy promote

Pricing

Start free. Pay for people, not messages.

Each person counts once a day and once a month, however many messages you exchange.

Free trial

$0

Try your agent on iMessage today.

Start free
  • 25 people, ever, on the shared line
  • SMS/RCS fallback
  • Customers text first
  • Typing, tapbacks and read receipts

Shared

Launch discount: $5 off

Was $30 now $25 /mo

Your agent on our shared line.

Get started
  • 300 people a month, 200 a day
  • SMS/RCS fallback
  • Customers text first
  • Typing, tapbacks and read receipts

Dedicated

Recommended

$100$140 /mo

Your agent on its own US number.

Get started Get started
  • Your own number, with group chats
  • 1,000 people a day (250 at first, ramping over 14 days)
  • SMS/RCS fallback and call forwarding

No per-message fees. Separate from Cloud plans. All pricing questions

FAQ

iMessage questions,
answered.

More in the iMessage guide and on pricing.

Is there an official iMessage API?

Apple has no public iMessage API. Apple Messages for Business is a separate channel run by Apple-approved providers, and Flow is not one of them. Flow gives your agent a real iMessage line that your code reaches through an API.

Do I need a Mac or an iPhone to run it?

No. Flow runs the line and your agent calls an API. Test with simulated conversations, or text the line from any iPhone or Mac.

Can my agent message people first?

Only on a dedicated line with the Outbound add-on ($40 a month): 2 new conversations a day at first, 40 a day from day 22. Otherwise people text first. Message only people who gave you their number.

Does iMessage have a 24-hour window like WhatsApp?

iMessage has no 24-hour window: once someone has texted your line, your agent can message them any time. The only timing rule is that typing indicators and read receipts work for 5 minutes after your line’s last message to that person. The person writes first, unless a dedicated line has the Outbound add-on.

What happens when someone is not on iMessage?

They get SMS or RCS from the same number, on every plan. Effects and text styles do not show there.

Can the agent join group chats?

Yes, on a dedicated line through the iMessage API, in groups people add it to. It cannot create, rename or manage groups, and groups have no tapbacks, typing or read receipts. The shared line and Flow Framework agents do not answer in groups.

How do typing indicators and read receipts work?

Once the person has written, both work for 5 minutes after your line’s last message to them. Not in group chats.

Do I have to use Flow Framework?

No. The iMessage API works from any language, with SDKs on npm (@flow-engineer/messaging) and PyPI (flow-messaging). Flow Framework is the open-source way to build the agent itself.

How much does it cost?

Free for 25 people on the shared line, ever. Shared is $25 a month (launch discount: $5 off $30), for 300 people a month and 200 a day. Dedicated is $100 a month for your own US number and 1,000 people a day (250 a day at first, ramping over 14 days). Outbound adds $40 a month. No per-message fees.

Put your agent in people’s blue bubbles.

Start free on the shared line. The same code runs on your own number.