Update an iMessage app card in place
Replaces a previously delivered imessage_app card on the recipient’s screen with new
content, instead of posting a new bubble (like a game move redrawing the board).
The update is delivered as a new message with its own id and delivery lifecycle
(message.sent / message.delivered / message.failed webhooks fire for the new id).
To update the card again, reference the message id returned by this call.
Constraints:
- The referenced message must be an
imessage_appcard sent by you (400otherwise — inbound cards cannot be updated). - The referenced card must already be delivered (
409otherwise — retry after themessage.deliveredwebhook for it). - The app identity (
team_id,bundle_id, name) is inherited from the original card and cannot change; onlyurl,fallback_text, andlayoutare replaced. - iMessage-only, like all app cards.
- Concurrent updates against the same card are not serialized server-side; the last one delivered wins on the recipient’s screen. Serialize updates by always referencing the message id returned by the previous call.
Body ParametersJSON
Text shown on surfaces that cannot render the card (notifications, lock screen). Defaults to the caption when omitted.
Whether the updated card renders as your app’s interactive balloon for recipients who
have your iMessage app installed. true (default) lets your installed extension draw its
live view; false always shows the static layout card. Recipients without your app
always see the static card regardless of this flag.
Defaults to true when omitted — it is not inherited from the original card. To keep a
card static across updates, re-send interactive: false on each update.
Update an iMessage app card in place
curl https://api.linqapp.com/api/partner/v3/messages/$MESSAGE_ID/update \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $LINQ_API_V3_API_KEY" \
-d '{
"layout": {
"caption": "Score: 2 – 1"
},
"fallback_text": "Score update",
"interactive": true,
"url": "https://app.example.com/card?game=7f3a&move=2"
}'{
"chat_id": "550e8400-e29b-41d4-a716-446655440000",
"message": {
"id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
"created_at": "2025-10-23T13:07:55.019-05:00",
"delivery_status": "pending",
"is_read": false,
"parts": [
{
"reactions": [
{
"handle": {
"id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
"handle": "+15551234567",
"joined_at": "2025-05-21T15:30:00.000-05:00",
"service": "iMessage",
"is_me": false,
"left_at": "2019-12-27T18:11:19.117Z",
"status": "active"
},
"is_me": false,
"type": "love",
"custom_emoji": null,
"sticker": {
"file_name": "sticker.png",
"height": 420,
"mime_type": "image/png",
"url": "https://cdn.linqapp.com/attachments/a1b2c3d4/sticker.png?signature=...",
"width": 420
}
}
],
"type": "text",
"value": "Hello!",
"text_decorations": [
{
"range": [
0,
5
],
"animation": "shake",
"style": "bold"
}
]
}
],
"sent_at": null,
"delivered_at": null,
"effect": {
"name": "confetti",
"type": "screen"
},
"from_handle": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"handle": "+15551234567",
"joined_at": "2025-05-21T15:30:00.000-05:00",
"service": "iMessage",
"is_me": false,
"left_at": "2019-12-27T18:11:19.117Z",
"status": "active"
},
"preferred_service": "iMessage",
"reply_to": {
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"part_index": 0
},
"service": "iMessage"
}
}{
"error": {
"status": 400,
"code": 1002,
"message": "Phone number must be in E.164 format",
"doc_url": "https://docs.linqapp.com/error/codes/1xxx/1002/"
},
"success": false
}{
"error": {
"status": 401,
"code": 2004,
"message": "Unauthorized - missing or invalid authentication token",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2004/"
},
"success": false
}{
"error": {
"status": 403,
"code": 2005,
"message": "Access denied - insufficient permissions for this resource",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2005/"
},
"success": false
}{
"error": {
"status": 404,
"code": 2001,
"message": "Resource not found",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2001/"
},
"success": false
}{
"error": {
"status": 409,
"code": 2013,
"message": "This chat is unavailable",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2013/"
},
"success": false
}{
"error": {
"status": 500,
"code": 3006,
"message": "Internal server error",
"doc_url": "https://docs.linqapp.com/error/codes/3xxx/3006/"
},
"success": false
}Returns Examples
{
"chat_id": "550e8400-e29b-41d4-a716-446655440000",
"message": {
"id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
"created_at": "2025-10-23T13:07:55.019-05:00",
"delivery_status": "pending",
"is_read": false,
"parts": [
{
"reactions": [
{
"handle": {
"id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
"handle": "+15551234567",
"joined_at": "2025-05-21T15:30:00.000-05:00",
"service": "iMessage",
"is_me": false,
"left_at": "2019-12-27T18:11:19.117Z",
"status": "active"
},
"is_me": false,
"type": "love",
"custom_emoji": null,
"sticker": {
"file_name": "sticker.png",
"height": 420,
"mime_type": "image/png",
"url": "https://cdn.linqapp.com/attachments/a1b2c3d4/sticker.png?signature=...",
"width": 420
}
}
],
"type": "text",
"value": "Hello!",
"text_decorations": [
{
"range": [
0,
5
],
"animation": "shake",
"style": "bold"
}
]
}
],
"sent_at": null,
"delivered_at": null,
"effect": {
"name": "confetti",
"type": "screen"
},
"from_handle": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"handle": "+15551234567",
"joined_at": "2025-05-21T15:30:00.000-05:00",
"service": "iMessage",
"is_me": false,
"left_at": "2019-12-27T18:11:19.117Z",
"status": "active"
},
"preferred_service": "iMessage",
"reply_to": {
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"part_index": 0
},
"service": "iMessage"
}
}{
"error": {
"status": 400,
"code": 1002,
"message": "Phone number must be in E.164 format",
"doc_url": "https://docs.linqapp.com/error/codes/1xxx/1002/"
},
"success": false
}{
"error": {
"status": 401,
"code": 2004,
"message": "Unauthorized - missing or invalid authentication token",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2004/"
},
"success": false
}{
"error": {
"status": 403,
"code": 2005,
"message": "Access denied - insufficient permissions for this resource",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2005/"
},
"success": false
}{
"error": {
"status": 404,
"code": 2001,
"message": "Resource not found",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2001/"
},
"success": false
}{
"error": {
"status": 409,
"code": 2013,
"message": "This chat is unavailable",
"doc_url": "https://docs.linqapp.com/error/codes/2xxx/2013/"
},
"success": false
}{
"error": {
"status": 500,
"code": 3006,
"message": "Internal server error",
"doc_url": "https://docs.linqapp.com/error/codes/3xxx/3006/"
},
"success": false
}