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

# React

> POST /v1/theses/reactions: add or remove a like or emoji reaction in the name of one of your users.

Adds or removes a reaction on a thesis or reply in the name of one of your users. A `like` also counts towards the post's likes, which `sort=top` uses. A `thesis.reaction` event with the new counts goes out on the [stream](/cabalspy-id/stream#thesis-events).

Reactions: `like`, 🔥, 🚀, 💎, 👀, 😂, 🤝, 💀, 🐂, 🐻. Each user can add each reaction once per post.

## Body

<ParamField body="thesis_id" type="string" required>
  The thesis or reply.
</ParamField>

<ParamField body="emoji" type="string" required>
  `like` or one of the emoji above.
</ParamField>

<ParamField body="on" default="true" type="boolean">
  `true` adds the reaction, `false` removes it.
</ParamField>

<ParamField body="csid_id" type="string" required>
  The user, one of your users.
</ParamField>

<ParamField query="api_key" type="string" required>
  Your API key. Alternatively pass it as an Authorization Bearer header.
</ParamField>

## Usage Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api-id.cabalspy.xyz/v1/theses/reactions" \
    -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
    -d '{"thesis_id":"8d1f5a2e-6c4b-4e0f-9a7d-1b2c3d4e5f60","emoji":"like","on":true,"csid_id":"5e2d8c41-7a9b-4c3e-b1f0-6d5e4c3b2a19"}'
  ```

  ```python Python theme={null}
  import requests

  r = requests.post("https://api-id.cabalspy.xyz/v1/theses/reactions",
                    headers={"Authorization": "Bearer YOUR_KEY"},
                    json={"thesis_id": thesis_id, "emoji": "🚀", "on": True, "csid_id": session_user_sub})
  print(r.json()["data"]["reactions"])
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://api-id.cabalspy.xyz/v1/theses/reactions", {
    method: "POST",
    headers: { Authorization: "Bearer YOUR_KEY", "Content-Type": "application/json" },
    body: JSON.stringify({ thesis_id: thesisId, emoji: "like", on: false, csid_id: session.userSub }),
  });
  const { data } = await res.json();
  ```
</CodeGroup>

## Response

<ResponseField name="success" type="boolean">
  True on success.
</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="data">
    <ResponseField name="id" type="string">
      The post.
    </ResponseField>

    <ResponseField name="reactions" type="object">
      The new count per reaction.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "id": "8d1f5a2e-6c4b-4e0f-9a7d-1b2c3d4e5f60",
      "reactions": { "like": 5, "🚀": 2 }
    },
    "meta": { "request_id": "req_5162c7cf7f87", "cached": false, "cache_age_seconds": 0, "version": "v1", "timestamp": "2026-10-13T09:30:00Z" }
  }
  ```
</ResponseExample>

## Errors

| Status | Code | Meaning |
| - | - | - |
| 400 | missing\_parameter | thesis\_id, emoji or csid\_id is missing. |
| 400 | invalid\_parameter | Unknown reaction or invalid csid\_id. |
| 401 | missing\_api\_key | API key missing. |
| 403 | invalid\_api\_key | API key invalid or not enabled for CabalSpy ID. |
| 403 | consent\_required | The user has not granted your app the scope thesis. |
| 403 | plan\_user\_limit | The user is beyond your plan's user limit. |
| 403 | sandbox\_user | Sandbox test users cannot write. |
| 403 | posting\_paused | The user is paused from writing and reacting. |
| 404 | not\_found | The post does not exist, was hidden or deleted. |
| 429 | rate\_limited | The user reacts too fast: 120 reactions per hour. |
| 429 | rate\_limit\_exceeded | Your API key's request rate is exceeded. |


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