Skip to content
Inkbox

Inkbox

DocsPricingBlogContact
GuidesAPI ReferenceChangelog

Ctrl K

GuidesAPI ReferenceChangelog

Jump to

iMessage

Agents can chat with humans over iMessage — blue bubbles, tapbacks, read receipts, typing indicators, and media — through the shared Inkbox iMessage router or a dedicated number.

iMessage number types have distinct capabilities:

  • Outbound: Can start new conversations.
  • Inbound: Can reply in existing conversations.
  • Shared: Dynamically assigned when someone connects to your agent.

With the shared service, a human connects by texting the router. Inkbox assigns the conversation to your identity without exposing the shared number in API responses. Dedicated numbers belong to your organization and can be attached to an iMessage-enabled identity. The number's typededicated_inbound or dedicated_outbound — is the sole source of its capabilities.

Conversations remain the stable key in every setup. Agent-facing APIs identify threads by conversation_id and the human's E.164 number. Every conversation is private to its connection — one human, one agent identity, in your organization — and an identity-scoped API key only sees that identity's threads.

Conversations are 1:1 today — group iMessage threads are not supported.

Enabling iMessage on an identity

iMessage reachability is opt-in per identity and defaults to off. Enable it at create time or later:

You can also claim and attach a dedicated number while creating or updating an identity. See Dedicated numbers and Manage identities for the raw REST contract.

While an identity is disabled, the router will not connect new recipients to it, sends from it are rejected, and inbound traffic for it is not delivered.

Connecting a human to your agent

Humans connect by texting a command to the router. Resolve the router number at runtime — it can change, so never hardcode it:

Tell your human: text connect @my-agent to the router number. The router replies, the connection is created, and everything the human sends after that lands in your agent's conversation. A human can be connected to more than one agent at the same time; each connection is its own conversation.

Here's what that looks like from the human's side — they text the connect command to the router, and the router confirms the connection and shares the agent's contact card:

An iMessage thread with the Inkbox iMessage router: the human texts the connect command, and the router confirms the connection and sends the agent's contact card

Reading and replying

Once a recipient has messaged your agent, list conversations, read messages, and reply. Replies can target the conversation by ID or the recipient by number:

When sending to a number without an active conversation, the remediation depends on the setup. On the shared service, a 404 tells the recipient to text the connect command to the router. On a dedicated inbound number, the 404 tells them to iMessage the attached number directly. A dedicated outbound number can start a new conversation. If a previous conversation is no longer active, sends into it return 409 with the corresponding first-contact instructions. Conversation reads carry an assignment_status field ("active" or "released") so you can spot a disconnect before sending, and GET /assignments lists who is currently connected.

Each identity can send up to 100 iMessages per rolling 24-hour window. When the cap is reached, 429 responses carry Retry-After and X-RateLimit-* headers.

Tapbacks

Agents can react to the human's messages with the classic tapbacks: love, like, dislike, laugh, emphasize, question. (iMessage has no concept of reacting to your own messages, so an agent can't tapback its own.)

Tapbacks follow Apple's semantics: one live tapback per sender per message. Sending a second tapback to the same message replaces your first, and when the human swaps or removes theirs, message reads reflect it. Humans can also react with any emoji — those arrive as reaction: "custom" with the emoji in custom_emoji. Custom-emoji tapbacks are receive-only; sends accept the classic six.

Read receipts, typing, and media

Round out the native feel: send a read receipt when your agent has read the thread, show a typing indicator while it works, and attach media.

Expressive send styles are supported too — pass send_style on a send with values like slam, confetti, lasers, or invisible (invisible ink). See the Messages reference for the full list.

Filtering who can reach your agent

iMessage contact rules work just like phone and mail rules — all three are scoped to the agent identity and interpreted against a per-identity filter_mode. The identity remains the policy owner whether it uses the shared service or a dedicated number.

Each identity has an iMessage filter_mode:

  • blacklist (default) — everyone can reach the agent except numbers with an active block rule.
  • whitelist — nobody can reach the agent except numbers with an active allow rule.

Blocked inbound messages are stored for review but never reach the agent: identity-scoped API keys never see them, no webhooks fire for them, and outbound sends to a blocked number return 403 before anything leaves Inkbox. Admin API keys and the Inkbox Console can audit blocked rows with is_blocked=true filters. Blocked humans are not told they're blocked — the router gives them the same generic response as for an unknown agent.

Reacting to events in real time

Inbound messages and tapbacks are delivered through webhook subscriptions owned by the agent identity, regardless of whether it uses the shared service or a dedicated number. The same subscription can also carry the outbound delivery-lifecycle events — imessage.sent, imessage.delivered, and imessage.delivery_failed — so your agent knows when a reply actually landed:

See iMessage webhooks for payload shapes and Signing keys for signature verification.

How messages are delivered

Inkbox always tries iMessage first. If a recipient isn't reachable over iMessage, delivery can fall back to SMS — the message's service field reports the transport actually used ("imessage", "sms", or "rcs"), and was_downgraded is set when a fallback happened.

Next steps

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Y CombinatorBacked by Y Combinator
iMessage