## 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 Parameters - `message_handle: string` ### Body Parameters - `fallback_text: optional string` Replacement fallback text for notifications and non-rendering surfaces. - `idempotency_key: optional string` Reusing this key for the same App Card target returns the original update instead of sending again. - `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. - `imageTitle: optional string` Text overlaid on the preview image. Requires imageUrl. - `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. - `subcaption: optional string` - `summary: optional string` Fallback text used in notifications and non-rendering surfaces. - `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. - `"celebration"` - `"shooting_star"` - `"fireworks"` - `"lasers"` - `"love"` - `"confetti"` - `"balloons"` - `"spotlight"` - `"echo"` - `"invisible"` - `"gentle"` - `"loud"` - `"slam"` - `url: optional string` ### Returns - `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. - `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. - `imageTitle: optional string` Text overlaid on the preview image. Requires imageUrl. - `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. - `subcaption: optional string` - `summary: optional string` Fallback text used in notifications and non-rendering surfaces. - `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. - `appStoreId: optional number` Optional numeric App Store ID for recipients without the extension. - `fallbackText: optional string` Fallback text for notifications and surfaces that cannot render the card. - `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. - `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. - `sessionIdentifier: string` - `teamId: string` - `url: string` - `content: optional string` Message content - `date_created: optional string` When the message was created - `date_updated: optional string` When the message was last updated - `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 - `altitude: optional number` Altitude in meters - `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"` - `"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. - `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. - `send_style: optional "celebration" or "shooting_star" or "fireworks" or 10 more` The iMessage expressive message style - `"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`. - `status: optional "QUEUED" or "SENT" or "DELIVERED" or "ERROR"` - `"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 ### Example ```http 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 '{}' ``` #### Response ```json { "account_email": "user@example.com", "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": "rep@example.com", "status": "QUEUED", "thread_originator": { "message_handle": "msg_root456", "part": "0:0" } } ```