Skip to content
Get Started

Update an App Card

POST/api/messages/{message_handle}/update-app-card

Continues an existing App Card by sending a new Apple message in the same iMessage session, from the same sender line and inline-reply context. The continuation receives its own message handle and delivery/read status updates.

Path ParametersExpand Collapse
message_handle: string
Body ParametersJSONExpand Collapse
fallback_text: optional string

Replacement fallback text for notifications and non-rendering surfaces.

maxLength1024
idempotency_key: optional string

Reusing this key for the same App Card target returns the original update instead of sending again.

minLength1
maxLength255
interactive: optional boolean
layout: optional object { caption, imageSubtitle, imageTitle, 5 more }

Visible card fields mirroring Apple’s MSMessageTemplateLayout.

caption: optional string
imageSubtitle: optional string

Secondary text overlaid on the preview image. Requires imageUrl.

maxLength1024
imageTitle: optional string

Text overlaid on the preview image. Requires imageUrl.

maxLength1024
imageUrl: optional string

HTTPS preview image fetched by the worker and sent as a hidden card attachment. JPEG, PNG, HEIC, HEIF, and WebP are supported up to 10 MB.

formaturi
maxLength2048
subcaption: optional string
summary: optional string

Fallback text used in notifications and non-rendering surfaces.

maxLength1024
trailingCaption: optional string
trailingSubcaption: optional string
send_style: optional "celebration" or "shooting_star" or "fireworks" or 10 more

The iMessage expressive message style for this update.

One of the following:
"celebration"
"shooting_star"
"fireworks"
"lasers"
"love"
"confetti"
"balloons"
"spotlight"
"echo"
"invisible"
"gentle"
"loud"
"slam"
url: optional string
ReturnsExpand Collapse
MessageResponse object { account_email, app_card, content, 17 more }
account_email: optional string

Email of the account that sent the message

app_card: optional object { appName, extensionBundleId, layout, 7 more } or object { balloonBundleId, extensionBundleId, revision, 3 more }

App Card data sent or received with this message.

One of the following:
AppCard object { appName, extensionBundleId, layout, 7 more }

A Sendblue App Card rendered with Apple’s Messages framework. App Cards require a V2 Mac line and an iMessage-capable recipient; they never fall back to SMS. The URL is delivered to the identified Messages extension when the recipient taps the card. An initial App Card may include reply_to to create an inline reply. Later state changes use the update endpoint, which sends a new Apple message in the same App Card session. The feature is unavailable on the free plan.

appName: string
extensionBundleId: string
layout: object { caption, imageSubtitle, imageTitle, 5 more }

Visible card fields mirroring Apple’s MSMessageTemplateLayout.

caption: optional string
imageSubtitle: optional string

Secondary text overlaid on the preview image. Requires imageUrl.

maxLength1024
imageTitle: optional string

Text overlaid on the preview image. Requires imageUrl.

maxLength1024
imageUrl: optional string

HTTPS preview image fetched by the worker and sent as a hidden card attachment. JPEG, PNG, HEIC, HEIF, and WebP are supported up to 10 MB.

formaturi
maxLength2048
subcaption: optional string
summary: optional string

Fallback text used in notifications and non-rendering surfaces.

maxLength1024
trailingCaption: optional string
trailingSubcaption: optional string
teamId: string
url: string

URL delivered to the iMessage extension on tap. HTTPS URLs are limited to 2048 characters; data URLs carrying inline app state are limited to 16384.

formaturi
maxLength16384
appStoreId: optional number

Optional numeric App Store ID for recipients without the extension.

minimum1
fallbackText: optional string

Fallback text for notifications and surfaces that cannot render the card.

maxLength1024
interactive: optional boolean

Use Apple’s live layout when the extension is installed; false always sends the static template layout.

sessionIdentifier: optional string

Optional caller-supplied App Card session UUID. Generated automatically when omitted.

formatuuid
updateMessageHandle: optional string

Original message handle for an App Card continuation returned by the update endpoint.

InboundAppCard object { balloonBundleId, extensionBundleId, revision, 3 more }

App Card session metadata received from an iMessage contact.

balloonBundleId: string
extensionBundleId: string
revision: number

Retry-stable occurrence revision assigned to this inbound App Card state.

minimum1
sessionIdentifier: string
teamId: string
url: string
content: optional string

Message content

date_created: optional string

When the message was created

formatdate-time
date_updated: optional string

When the message was last updated

formatdate-time
error_code: optional number

Numeric error code if message failed

error_message: optional string

Error message if message failed

from_number: optional string

Sending phone number

is_outbound: optional boolean

Whether this is an outbound message

location: optional object { latitude, longitude, accuracy, 3 more }

Decoded Find My location share coordinates.

latitude: number
longitude: number
accuracy: optional number

Horizontal accuracy in meters

formatdouble
altitude: optional number

Altitude in meters

formatdouble
duration: optional string

Share duration selected by the recipient

timestamp: optional string
media_url: optional string

URL of attached media

message_handle: optional string

Unique identifier for tracking the message

message_type: optional "message" or "group" or "location"
One of the following:
"message"
"group"
"location"
number: optional string

Recipient phone number

reply_to: optional object { message_handle, part_index }

Immediate parent of an iMessage inline reply. The target must belong to the same account, conversation, and sending line.

message_handle: string

Public handle of the immediate parent message

part_index: optional number

Advanced override for a known part of a multipart target. Omit this in normal reply requests and never guess it; requests default to 0. When replying to an attachment represented by its own webhook, use that webhook’s message_handle and omit part_index so Sendblue can use the stored authoritative part. Responses omit it when no authoritative immediate-parent part is available.

minimum0
maximum50
seat_id: optional string

UUID of the seat that sent the message. Present when seat_id was provided on send, or for dashboard-originated group messages.

formatuuid
send_style: optional "celebration" or "shooting_star" or "fireworks" or 10 more

The iMessage expressive message style

One of the following:
"celebration"
"shooting_star"
"fireworks"
"lasers"
"love"
"confetti"
"balloons"
"spotlight"
"echo"
"invisible"
"gentle"
"loud"
"slam"
sender_email: optional string

Email of the seat (user) that sent the message. Auto-populated when a seat_id is provided on send. null for messages sent without a seat_id.

formatemail
status: optional "QUEUED" or "SENT" or "DELIVERED" or "ERROR"
One of the following:
"QUEUED"
"SENT"
"DELIVERED"
"ERROR"
thread_originator: optional object { message_handle, part }

Message that originated an iMessage inline-reply thread.

message_handle: string

Public handle of the thread’s root message

part: optional string

Opaque Apple thread-originator part descriptor

Update an App Card

curl https://api.sendblue.co/api/messages/$MESSAGE_HANDLE/update-app-card \
    -H 'Content-Type: application/json' \
    -H "sb-api-key-id: $SENDBLUE_API_API_KEY" \
    -H "sb-api-secret-key: $SENDBLUE_API_API_SECRET" \
    -d '{}'
{
  "account_email": "[email protected]",
  "app_card": {
    "appName": "My App",
    "extensionBundleId": "com.example.myapp.MessagesExtension",
    "layout": {
      "caption": "Check this out",
      "imageSubtitle": "imageSubtitle",
      "imageTitle": "imageTitle",
      "imageUrl": "https://example.com",
      "subcaption": "Tap to open",
      "summary": "summary",
      "trailingCaption": "trailingCaption",
      "trailingSubcaption": "trailingSubcaption"
    },
    "teamId": "ABCDE12345",
    "url": "https://example.com/deep-link",
    "appStoreId": 1234567890,
    "fallbackText": "fallbackText",
    "interactive": true,
    "sessionIdentifier": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
    "updateMessageHandle": "updateMessageHandle"
  },
  "content": "Hello, World!",
  "date_created": "2023-10-01T12:00:00Z",
  "date_updated": "2023-10-01T12:00:01Z",
  "error_code": 0,
  "error_message": "error_message",
  "from_number": "+19998887777",
  "is_outbound": true,
  "location": {
    "latitude": 37.7749,
    "longitude": -122.4194,
    "accuracy": 12,
    "altitude": 8,
    "duration": "oneHour",
    "timestamp": "2026-06-23T12:00:00.000Z"
  },
  "media_url": "https://cdn.sendblue.co/media/abc123.jpg",
  "message_handle": "msg_abc123def456",
  "message_type": "message",
  "number": "+18887776666",
  "reply_to": {
    "message_handle": "msg_parent123",
    "part_index": 0
  },
  "seat_id": "550e8400-e29b-41d4-a716-446655440000",
  "send_style": "celebration",
  "sender_email": "[email protected]",
  "status": "QUEUED",
  "thread_originator": {
    "message_handle": "msg_root456",
    "part": "0:0"
  }
}
Returns Examples
{
  "account_email": "[email protected]",
  "app_card": {
    "appName": "My App",
    "extensionBundleId": "com.example.myapp.MessagesExtension",
    "layout": {
      "caption": "Check this out",
      "imageSubtitle": "imageSubtitle",
      "imageTitle": "imageTitle",
      "imageUrl": "https://example.com",
      "subcaption": "Tap to open",
      "summary": "summary",
      "trailingCaption": "trailingCaption",
      "trailingSubcaption": "trailingSubcaption"
    },
    "teamId": "ABCDE12345",
    "url": "https://example.com/deep-link",
    "appStoreId": 1234567890,
    "fallbackText": "fallbackText",
    "interactive": true,
    "sessionIdentifier": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
    "updateMessageHandle": "updateMessageHandle"
  },
  "content": "Hello, World!",
  "date_created": "2023-10-01T12:00:00Z",
  "date_updated": "2023-10-01T12:00:01Z",
  "error_code": 0,
  "error_message": "error_message",
  "from_number": "+19998887777",
  "is_outbound": true,
  "location": {
    "latitude": 37.7749,
    "longitude": -122.4194,
    "accuracy": 12,
    "altitude": 8,
    "duration": "oneHour",
    "timestamp": "2026-06-23T12:00:00.000Z"
  },
  "media_url": "https://cdn.sendblue.co/media/abc123.jpg",
  "message_handle": "msg_abc123def456",
  "message_type": "message",
  "number": "+18887776666",
  "reply_to": {
    "message_handle": "msg_parent123",
    "part_index": 0
  },
  "seat_id": "550e8400-e29b-41d4-a716-446655440000",
  "send_style": "celebration",
  "sender_email": "[email protected]",
  "status": "QUEUED",
  "thread_originator": {
    "message_handle": "msg_root456",
    "part": "0:0"
  }
}