Skip to content
Linq Copy agent prompt

Move a sticker already on a message

client.Messages.UpdateStickerPlacement(ctx, reactionID, params) (*MessageUpdateStickerPlacementResponse, error)
PATCH/v3/messages/{messageId}/reactions/{reactionId}

Move, resize or rotate a sticker that has already been peeled onto a message. The change is sent to every device in the conversation, exactly as dragging the sticker by hand would.

Only stickers can be repositioned — a tapback has no placement, so a non-sticker reactionId is rejected. Any field omitted from placement keeps its current value.

reactionId is the id from the reaction on the message, or from the reaction.added webhook. Stickers stack, so this id is what distinguishes one sticker from another on the same message.

Stickers peeled before this endpoint existed cannot be moved: addressing one requires an identifier that was not recorded at the time, and it returns 404.

ParametersExpand Collapse
reactionID string
formatuuid
params MessageUpdateStickerPlacementParams
MessageID param.Field[string]

Path param: The message the sticker sits on

formatuuid

Body param: 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 float64Optional

Clockwise rotation in degrees.

formatdouble
minimum-180
maximum180
Scale float64Optional

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 float64Optional

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

formatdouble
minimum-1
maximum1
Y float64Optional

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

formatdouble
minimum-1
maximum1
ReturnsExpand Collapse
type MessageUpdateStickerPlacementResponse struct{…}
Status stringOptional
Success boolOptional
TraceID stringOptional

Move a sticker already on a message

package main

import (
  "context"
  "fmt"

  "github.com/linq-team/linq-go"
  "github.com/linq-team/linq-go/option"
)

func main() {
  client := linqgo.NewClient(
    option.WithAPIKey("My API Key"),
  )
  response, err := client.Messages.UpdateStickerPlacement(
    context.TODO(),
    "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
    linqgo.MessageUpdateStickerPlacementParams{
      MessageID: "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
      Placement: linqgo.MessageUpdateStickerPlacementParamsPlacement{
        X: linqgo.Float(0.6),
        Y: linqgo.Float(0.5),
        Scale: linqgo.Float(0.75),
      },
    },
  )
  if err != nil {
    panic(err.Error())
  }
  fmt.Printf("%+v\n", response.TraceID)
}
{
  "status": "accepted",
  "success": true,
  "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": 404,
    "code": 2001,
    "message": "Resource not found",
    "doc_url": "https://docs.linqapp.com/channel/imessage/error/codes/2xxx/2001/"
  },
  "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
{
  "status": "accepted",
  "success": true,
  "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": 404,
    "code": 2001,
    "message": "Resource not found",
    "doc_url": "https://docs.linqapp.com/channel/imessage/error/codes/2xxx/2001/"
  },
  "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
}