Skip to content
Linq Copy agent prompt

Add or remove a reaction to a message

POST/v3/messages/{messageId}/reactions

Add or remove emoji reactions to messages. Reactions let users express their response to a message without sending a new message.

Supported Reactions:

  • love ❤️
  • like 👍
  • dislike 👎
  • laugh 😂
  • emphasize ‼️
  • question ❓
  • custom - any emoji (use custom_emoji field to specify)
  • sticker - an image peeled onto the message (use url or attachment_id)

Stickers are iMessage-only and cannot be removed — iMessage has no unpeel operation, so operation: "remove" with type: "sticker" is rejected. Position, size and rotation are optional via placement, and can be changed afterwards with PATCH /v3/messages/{messageId}/reactions/{reactionId}.

Path ParametersExpand Collapse
messageId: string
formatuuid
Body ParametersJSONExpand Collapse
operation: "add" or "remove"

Whether to add or remove the reaction

One of the following:
"add"
"remove"

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type “custom” with the actual emoji in the custom_emoji field. Sticker reactions have type “sticker” with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
attachment_id: optional string

Reference to a sticker image pre-uploaded via POST /v3/attachments. Only valid when type is “sticker”.

Either url or attachment_id must be provided when type is “sticker”, but not both.

formatuuid
custom_emoji: optional string

Custom emoji string. Required when type is “custom”.

part_index: optional number

Optional index of the message part to react to. If not provided, reacts to the entire message (part 0).

placement: optional object { rotation, scale, x, y }

Optional position, size and rotation of a sticker on the target bubble. Only valid when type is “sticker”.

Every field is independent and optional — omit the object entirely, or any field within it, to keep the default (centred, default size, unrotated).

rotation: optional number

Clockwise rotation in degrees.

formatdouble
minimum-180
maximum180
scale: optional number

Size relative to the default, where 1 matches the size a sticker gets natively.

Values outside 0.5–1.5 are clamped rather than rejected. The upper bound keeps a sticker within the size range iMessage itself displays: its own limit is larger, but that allowance assumes the transparent padding Apple’s stickers carry, which a full-bleed image does not have.

Scale is linear, so 1.5 is a little over twice the area.

formatdouble
minimum0.5
maximum1.5
x: optional number

Horizontal position on the target bubble, from -1 (far left) to 1 (far right). 0 is centred.

formatdouble
minimum-1
maximum1
y: optional number

Vertical position on the target bubble, from -1 (top) to 1 (bottom). 0 is centred.

formatdouble
minimum-1
maximum1
url: optional string

Linq attachment URL of the sticker image — the download_url returned by POST /v3/attachments. Only valid when type is “sticker”.

Unlike a media part, this does not accept an arbitrary host: reactions have no download step, so the image must already be stored. To send a sticker from elsewhere, upload it with POST /v3/attachments first and pass attachment_id.

Either url or attachment_id must be provided when type is “sticker”, but not both.

formaturi
ReturnsExpand Collapse
message: optional string
status: optional string
trace_id: optional string

Add or remove a reaction to a message

curl https://api.linqapp.com/api/partner/v3/messages/$MESSAGE_ID/reactions \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $LINQ_API_V3_API_KEY" \
    -d '{
          "operation": "add",
          "type": "love",
          "attachment_id": "550e8400-e29b-41d4-a716-446655440000",
          "part_index": 1,
          "url": "https://cdn.linqapp.com/attachments/example/sticker.png"
        }'
{
  "message": "Reaction processed",
  "status": "accepted",
  "trace_id": "trace_id"
}
{
  "error": {
    "status": 400,
    "code": 1002,
    "message": "Phone number must be in E.164 format",
    "doc_url": "https://docs.linqapp.com/channel/imessage/error/codes/1xxx/1002/"
  },
  "success": false
}
{
  "error": {
    "status": 401,
    "code": 2004,
    "message": "Unauthorized - missing or invalid authentication token",
    "doc_url": "https://docs.linqapp.com/channel/imessage/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/channel/imessage/error/codes/2xxx/2005/"
  },
  "success": false
}
{
  "error": {
    "status": 500,
    "code": 3006,
    "message": "Internal server error",
    "doc_url": "https://docs.linqapp.com/channel/imessage/error/codes/3xxx/3006/"
  },
  "success": false
}
Returns Examples
{
  "message": "Reaction processed",
  "status": "accepted",
  "trace_id": "trace_id"
}
{
  "error": {
    "status": 400,
    "code": 1002,
    "message": "Phone number must be in E.164 format",
    "doc_url": "https://docs.linqapp.com/channel/imessage/error/codes/1xxx/1002/"
  },
  "success": false
}
{
  "error": {
    "status": 401,
    "code": 2004,
    "message": "Unauthorized - missing or invalid authentication token",
    "doc_url": "https://docs.linqapp.com/channel/imessage/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/channel/imessage/error/codes/2xxx/2005/"
  },
  "success": false
}
{
  "error": {
    "status": 500,
    "code": 3006,
    "message": "Internal server error",
    "doc_url": "https://docs.linqapp.com/channel/imessage/error/codes/3xxx/3006/"
  },
  "success": false
}