> ## Documentation Index
> Fetch the complete documentation index at: https://inkbox.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Reactions

> Add or remove whole-message WhatsApp reactions without confusing acceptance with application

Paths are relative to `https://inkbox.ai/api/v1/whatsapp`. Select the authorized `agent_identity_id` as a query parameter where required. Every reaction mutation requires its own stable `Idempotency-Key`.

Reactions work in direct conversations and [existing groups](https://inkbox.ai/docs/api/whatsapp/groups.md). Group reactions require the same incoming-message prerequisite as text and media; reacting is not a way to initiate communication in a newly joined group.

## Add a reaction

```text theme={null}
POST /reactions
```

Provide a target `message_id` and exactly one of `reaction` or `custom_emoji`:

```json theme={null}
{
  "message_id": "33333333-3333-4333-8333-333333333333",
  "reaction": "like"
}
```

| Name | Emoji |
| :- | :- |
| `love` | ❤️ |
| `like` | 👍 |
| `dislike` | 👎 |
| `laugh` | 😂 |
| `emphasize` | ‼️ |
| `question` | ❓ |
| `eyes` | 👀 |

For a custom reaction, replace `reaction` with `custom_emoji`, containing 1–32 Unicode code points without whitespace or control characters. Reactions apply to the whole message. There is no `part_index` field.

The response is `201` with `{ "reaction": ... }`. Read the receipt's status before presenting it as applied.

```python Python theme={null}
receipt = identity.send_whatsapp_reaction(
    message_id=incoming.id, reaction="like", idempotency_key="milestone-reaction",
)
current = identity.get_whatsapp_reaction(receipt.id)
```

```typescript TypeScript theme={null}
const receipt = await identity.sendWhatsAppReaction({
  messageId: incoming.id, reaction: "like", idempotencyKey: "milestone-reaction",
});
const current = await identity.getWhatsAppReaction(receipt.id);
```

```bash CLI theme={null}
inkbox whatsapp react 33333333-3333-4333-8333-333333333333 \
  --identity my-agent --reaction like --idempotency-key milestone-reaction
```

## Read or remove a reaction

```text theme={null}
GET /reactions/{reaction_id}
DELETE /reactions/{reaction_id}
```

Both return `200` with `{ "reaction": ... }`. DELETE requires a stable removal key. It removes only your selected reaction version. Deleting an older or superseded receipt does not remove a newer reaction on the same message.

Python uses `identity.remove_whatsapp_reaction(receipt.id, idempotency_key="milestone-reaction-removal")`. TypeScript uses `identity.removeWhatsAppReaction(receipt.id, "milestone-reaction-removal")`. The CLI uses `whatsapp remove-reaction <reaction-id> --identity my-agent --idempotency-key milestone-reaction-removal`.

## Receipt fields and status

A receipt contains `id`, `target_message_id`, `conversation_id`, `agent_identity_id`, `direction`, nullable `remote_number`, `reaction`, nullable `custom_emoji`, `emoji`, `status`, positive `revision`, `created_at`, `updated_at`, and nullable `removed_at`. `remote_number` identifies the actor when known; null is not an invented phone number. Custom receipts use `reaction: "custom"`.

Statuses are `queued`, `sending`, `applied`, `removed`, `failed`, `uncertain`, and `superseded`. Message objects include only currently `applied` reactions. Keep pending and uncertain operations separate from live reaction chips. If a request times out, retry the same exact body and key. If a receipt is uncertain, inspect the original receipt instead of replacing it under a new key.

If two changes to the same reaction cannot be ordered against each other, the receipt remains `uncertain`; it is not reported as applied. Stale-version removals and automatic retries remain blocked.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.