Blog

Announcement

Supercharge Your Agents With iMessage Apps

June 30, 2026·5 min read

Linq developers can now build iMessage Apps: interactive mini-apps that run inside a Messages conversation.

Users can shop, play games, date, book appointments, fill out forms, or complete other workflows without leaving the thread. There is no deep link to an external browser. There is no "tap here to finish in the app." The experience renders inside the bubble, where the conversation is already happening.

The thread is the most-used surface on the phone. Until now, the best API-level option was to drop a link into a conversation and hope the user followed it somewhere else. iMessage Apps remove that handoff. The action happens in the message.

What you can build

An iMessage App is a tappable card that opens an interactive experience in place. Here are a few examples.

Games. Send a move, redraw the board, and run a full turn-based match inside the thread. Since a card can be updated in place, a live game session becomes a sequence of updates to the same bubble.

Dating. Profiles, prompts, and matches can live where people are already talking. The interaction stays in the conversation instead of sending the user back to a standalone app.

Payments. Send a checkout or request-to-pay as a card. The recipient can complete it in the thread, without a redirect or copied payment link.

Tickets. RSVPs, event passes, and order status can update as state changes. A card can move from "Going / Not going" to a confirmed ticket, or from Reserved to Confirmed, in the same bubble.

Flight booking. Surface a fare, let the user pick and confirm, then update the card to a boarding pass in the same conversation.

Music. Drop a track into the thread and let people play it inline. The card is a player, not a link to another app.

These are examples, not a fixed menu. If your product has an interactive moment, it can happen inside the message.

How it works

iMessage Apps are sent as a new message part with type: "imessage_app". This replaces the text, media, and link parts you already use.

The card becomes your app inside the bubble. An installed Messages extension draws rich, interactive content from a URL you provide.

Sending a card

Send a card as the first message in a new chat with Create Chat, or post the same part into an existing chat with Send Message:

curl -X POST https://api.linqapp.com/api/partner/v3/chats \
  -H "Authorization: Bearer $LINQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+12052535597",
    "to": ["+12052532136"],
    "message": {
      "parts": [
        {
          "type": "imessage_app",
          "app": {
            "name": "Example App",
            "team_id": "A1B2C3D4E5",
            "bundle_id": "com.example.app.MessageExtension"
          },
          "url": "https://app.example.com/card?id=abc123",
          "fallback_text": "Open in Example App",
          "layout": {
            "caption": "Example App",
            "subcaption": "You said: hello"
          }
        }
      ]
    }
  }'

Three details matter before your first send.

1. The app identity is the rendering key

The app object, specifically team_id and bundle_id, tells Messages which extension renders the card. The card is drawn by that extension, so you usually pass your own app's identity.

app_store_id is optional. If you set it, recipients who do not have the app installed see a Get the app affordance.

One common failure mode: an unrecognized identity silently renders as plain text. If team_id and bundle_id do not match a Messages extension installed by the recipient, the card falls back to your caption text with no error. If your card only shows text, verify the identity against your shipping app.

2. You control captions; the app controls the image

The layout object defines the text you can put directly on the card:

FieldPosition
captiontop-left, bold primary label
subcaptionleft, below caption
trailing_captiontop-right
trailing_subcaptionright, below trailing_caption

At least one field must be set, or the card renders as an empty bubble.

There is no image field. The photo, icon, and interactive UI come from your app's extension, drawn from the url. Messages treats the url as opaque. Your extension interprets it and renders from it. Change the url to change what the card shows.

If you need an image that everyone can see, regardless of whether they have your app installed, use a rich link or media attachment instead. That is a different tool.

Install state determines what the recipient sees:

Recipient stateResult
Has your appThe extension renders a rich card from your url.
Does not have your appThe recipient sees your layout captions, plus the Get the app affordance if you set app_store_id.

3. Cards update in place

A delivered card can be replaced in place by referencing the original message. This is the primitive behind a game move redrawing the board, or an order changing from Reserved to Confirmed.

curl -X POST https://api.linqapp.com/api/partner/v3/messages/{messageId}/update \
  -H "Authorization: Bearer $LINQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://app.example.com/card?game=7f3a&move=2",
    "fallback_text": "Score update",
    "layout": { "caption": "Score: 2 - 1" }
  }'

Rules to account for:

  • The update replaces the delivered card instead of posting a second bubble.
  • Only url, fallback_text, and layout can change.
  • The app identity is fixed for the life of the card.
  • The card must already be delivered.
  • A 409 means you should retry after the message.delivered webhook.
  • Each update is a new message with its own ID and lifecycle.
  • To update the card again, reference the new message ID.

You can also receive cards. Inbound messages include an imessage_app part in the message.received webhook. Your handler can read the app identity, url, and layout from a card the user sends you.

Constraints to plan around

iMessage App parts have stricter rules than other message parts.

  • iMessage only. They never fall back to SMS or RCS.
  • No mixed fallback request. If you request SMS or RCS alongside an iMessage App part, the send is rejected with 2018.
  • Async failure for unreachable recipients. If the recipient is not reachable over iMessage, the send is accepted and then fails asynchronously with a 4005 message.failed webhook. Check capability before sending.
  • Must be the only part. An imessage_app part cannot be combined with text, media, or link in the same message.

Get started

The full guide covers send, receive, update, webhooks, and capability checks:

docs.linqapp.com/guides/messaging/imessage-apps

Your Cart
Your cart's looking a little light.Looks like your cart is empty—it's time to add your
gears and make it unforgettable.
Shop our best sellers
Digital Card
Digital Card$14.99
Hub
Hub$29.99
Badge
Badge$19.99
Mini Card
Mini Card$12.99