## Add or remove a reaction to a message

`client.Messages.AddReaction(ctx, messageID, body) (*MessageAddReactionResponse, error)`

**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}`.

### Parameters

- `messageID string`

- `body MessageAddReactionParams`

  - `Operation param.Field[MessageAddReactionParamsOperation]`

    Whether to add or remove the reaction

    - `const MessageAddReactionParamsOperationAdd MessageAddReactionParamsOperation = "add"`

    - `const MessageAddReactionParamsOperationRemove MessageAddReactionParamsOperation = "remove"`

  - `Type param.Field[ReactionType]`

    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.

  - `AttachmentID param.Field[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.

  - `CustomEmoji param.Field[string]`

    Custom emoji string. Required when type is "custom".

  - `PartIndex param.Field[int64]`

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

  - `Placement param.Field[MessageAddReactionParamsPlacement]`

    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 float64`

      Clockwise rotation in degrees.

    - `Scale float64`

      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.

    - `X float64`

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

    - `Y float64`

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

  - `URL param.Field[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.

### Returns

- `type MessageAddReactionResponse struct{…}`

  - `Message string`

  - `Status string`

  - `TraceID string`

### Example

```go
package main

import (
  "context"
  "fmt"

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

func main() {
  client := linqgo.NewClient(
    option.WithAPIKey("My API Key"),
  )
  response, err := client.Messages.AddReaction(
    context.TODO(),
    "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
    linqgo.MessageAddReactionParams{
      Operation: linqgo.MessageAddReactionParamsOperationAdd,
      Type: shared.ReactionTypeLove,
    },
  )
  if err != nil {
    panic(err.Error())
  }
  fmt.Printf("%+v\n", response.TraceID)
}
```

#### Response

```json
{
  "message": "Reaction processed",
  "status": "accepted",
  "trace_id": "trace_id"
}
```
