---
title: "React to a message"
method: POST
path: "/messages/{message_id}/reactions"
---

# React to a message

`POST /messages/{message_id}/reactions`

## Request

- Base URL: `https://osis.co/api/v1/comms`
- URL: `https://osis.co/api/v1/comms/messages/{message_id}/reactions`
- Auth: HTTP bearer

Add, change, or remove a reaction. It comes from the line that owns the conversation. Custom emoji need a compatible iMessage or RCS line. RCS reactions never fall back to SMS. On SMS, a reaction is sent as a text. Use a new idempotency key for each change. Scope: comms_send.

## Path parameters

- `message_id` string, required

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `type` string, required: love, like, dislike, laugh, emphasize, or question for a standard reaction. custom (with emoji) for any emoji. You can also pass a single emoji or a shortcode like :saluting_face: here.
  - `emoji` string: Only for type custom. Send one emoji, like 🫡 or ✅. Shortcodes don't work here. To remove a custom reaction, send the same emoji you added.
  - `action` 'added' | 'removed': added adds a reaction or replaces the line's current one. removed takes it off.
  - `replace_type` string: The reaction to remove before adding this one. Only works with action added.
  - `idempotency_key` string: Same as the Idempotency-Key header. If you send both, the header wins. Use a new key for each change and the same key to retry it. Reusing a key for a different request returns idempotency_conflict.

## Response `200`

Already done with this idempotency key

- ReactionResult
  - `reaction` object, required: The reaction. Its transport is how it was first sent. When you remove it, the transport for that request can be different.
    - `id` string
    - `type` string
    - `emoji` string
    - `transport` 'imessage_native' | 'imessage_text' | 'rcs_native' | 'rcs_text' | 'sms_intercept' | 'unknown' | 'whatsapp_native': How the reaction was sent. This doesn't confirm the recipient got it.
  - `duplicate` boolean, required
  - `transport` 'imessage_native' | 'imessage_text' | 'rcs_native' | 'rcs_text' | 'sms_intercept' | 'unknown' | 'whatsapp_native', required: How the reaction was sent. This doesn't confirm the recipient got it.
  - `capabilities` ReactionCapabilities, required: Which reactions work where. Custom emoji need WhatsApp or a compatible iMessage or RCS line. On SMS, a reaction is sent as a text. Check native_custom_emoji_channels to see which channels support custom emoji. None of this confirms delivery.
    - `native_types` string[]
    - `native_channels` string[]
    - `native_custom_emoji` true
    - `native_custom_emoji_channels` string[]
    - `native_multiple_per_sender` false
    - `custom_emoji` 'imessage_native': Old field, kept so existing code keeps working. Use native_custom_emoji_channels instead.
    - `compatibility_channels` string[]

## Other responses

- `202`: Reaction accepted
- `400`: invalid_request (body missing or not a JSON object), invalid_tapback, invalid_reaction_emoji, or invalid_reaction_action
- `404`: message_not_found
- `409`: The reaction isn't supported, the key was reused, or the message or conversation isn't available
- `502`: reaction_delivery_failed

---

[API](https://skmtc.dev/osis/apis/comms-api.md) · [All operations](https://skmtc.dev/osis/apis/comms-api/llms.txt) · [OpenAPI document](https://skmtc.dev/osis/apis/comms-api/revisions/59a4c0ba8936?raw)
