Skip to content

AI Reactions ​

React to AI runs and messages with 10 reaction types. Reactions use toggle semantics -- the same endpoint adds or removes a reaction.

Endpoints ​

MethodPathDescriptionAuthRate Limit
POST/ai/reactions/toggleToggle a reactionJWT + Entitlement30/min
GET/ai/reactions/runs/:runIdGet reactions for a runJWT + Entitlement60/min
GET/ai/reactions/messages/:messageIdGet reactions for a messageJWT + Entitlement60/min
GET/ai/reactions/runs/:runId/statsAggregate stats for a runJWT + Entitlement60/min
GET/ai/reactions/messages/:messageId/statsAggregate stats for a messageJWT + Entitlement60/min
DELETE/ai/reactions/:idRemove a reaction by IDJWT + Entitlement30/min

Reaction Types ​

TypeDescription
likeGeneral positive signal
dislikeGeneral negative signal
accurateFactually correct
creativeNovel or surprising
fastQuick response
helpfulDirectly useful
inspiringMotivating content
confusingHard to understand
wrongFactually incorrect
slowResponse took too long

POST /ai/reactions/toggle ​

Toggle a reaction on a run or message. If the reaction already exists, it is removed. If it does not exist, it is added.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 30/min

Request ​

FieldTypeRequiredDescription
reactionTypestringYesOne of the 10 reaction types
runIdstring (uuid)NoTarget run ID (at least one of runId/messageId required)
messageIdstring (uuid)NoTarget message ID
commentstringNoOptional comment (max 1000 chars, only for like/dislike)

Response ​

Response Example (Added) ​
json
{
  "data": {
    "action": "added",
    "reaction": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "chainerId": "u1234567-abcd-ef01-2345-6789abcdef00",
      "reactionType": "helpful",
      "comment": null,
      "createdAt": "2026-03-17T14:00:00.000Z"
    }
  }
}
Response Example (Removed) ​
json
{
  "data": {
    "action": "removed"
  }
}
Response Fields ​
FieldTypeDescription
action"added" | "removed"Whether the reaction was created or deleted
reactionobject | undefinedThe created reaction (only when action is "added")
reaction.idstringReaction UUID
reaction.chainerIdstringUser who reacted
reaction.reactionTypestringThe reaction type
reaction.commentstring | nullOptional comment
reaction.createdAtstringISO 8601 timestamp

Code Examples ​

Use the id of an existing AI run as $RUN_ID.

bash
curl -X POST https://api.chainabit.com/api/v1/ai/reactions/toggle \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "reactionType": "helpful",
    "runId": "'"$RUN_ID"'"
  }'
javascript
const runId = process.env.RUN_ID; // id of the AI run you're reacting to

const res = await fetch(`${BASE_URL}/ai/reactions/toggle`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    reactionType: "helpful",
    runId,
  }),
});
const { data } = await res.json();
python
import os
import requests

run_id = os.environ["RUN_ID"]  # id of the AI run you're reacting to

res = requests.post(
    f"{BASE_URL}/ai/reactions/toggle",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={
        "reactionType": "helpful",
        "runId": run_id,
    },
)
data = res.json()["data"]

GET /ai/reactions/runs/:runId ​

Get aggregate reaction stats and the current user's reactions for a run.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min

Request ​

  • Path params: runId

Response ​

Response Example ​
json
{
  "data": {
    "stats": [
      { "reactionType": "helpful", "count": 12 },
      { "reactionType": "accurate", "count": 8 },
      { "reactionType": "like", "count": 5 }
    ],
    "userReactions": ["helpful", "like"]
  }
}
Response Fields ​
FieldTypeDescription
statsarrayAggregate counts per reaction type, sorted by count descending
stats[].reactionTypestringReaction type name
stats[].countnumberTotal reactions of this type
userReactionsstring[]Reaction types the current user has applied

Code Examples ​

Use the id of an existing AI run as $RUN_ID.

bash
curl https://api.chainabit.com/api/v1/ai/reactions/runs/$RUN_ID \
  -H "Authorization: Bearer $TOKEN"
javascript
const runId = process.env.RUN_ID; // id of the AI run

const res = await fetch(
  `${BASE_URL}/ai/reactions/runs/${runId}`,
  { headers: { Authorization: `Bearer ${TOKEN}` } }
);
const { data } = await res.json();
python
import os
import requests

run_id = os.environ["RUN_ID"]  # id of the AI run

res = requests.get(
    f"{BASE_URL}/ai/reactions/runs/{run_id}",
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]

GET /ai/reactions/runs/:runId/stats ​

Get aggregate reaction counts for a run without user-specific data.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min

Request ​

  • Path params: runId

Response ​

Response Example ​
json
{
  "data": {
    "stats": [
      { "reactionType": "helpful", "count": 12 },
      { "reactionType": "accurate", "count": 8 }
    ],
    "userReactions": []
  }
}

Code Examples ​

Use the id of an existing AI run as $RUN_ID.

bash
curl https://api.chainabit.com/api/v1/ai/reactions/runs/$RUN_ID/stats \
  -H "Authorization: Bearer $TOKEN"
javascript
const runId = process.env.RUN_ID; // id of the AI run

const res = await fetch(
  `${BASE_URL}/ai/reactions/runs/${runId}/stats`,
  { headers: { Authorization: `Bearer ${TOKEN}` } }
);
const { data } = await res.json();
python
import os
import requests

run_id = os.environ["RUN_ID"]  # id of the AI run

res = requests.get(
    f"{BASE_URL}/ai/reactions/runs/{run_id}/stats",
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]

DELETE /ai/reactions/:id ​

Remove a specific reaction by its ID. Only the reaction owner can delete it.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 30/min

Request ​

  • Path params: id

Response ​

Response Example ​
json
{
  "data": {
    "deleted": true
  }
}

Code Examples ​

Use the id from Toggle Reaction's "added" response (data.reaction.id) as $REACTION_ID.

bash
curl -X DELETE https://api.chainabit.com/api/v1/ai/reactions/$REACTION_ID \
  -H "Authorization: Bearer $TOKEN"
javascript
const reactionId = process.env.REACTION_ID; // id from the "added" response of POST /ai/reactions/toggle

const res = await fetch(
  `${BASE_URL}/ai/reactions/${reactionId}`,
  {
    method: "DELETE",
    headers: { Authorization: `Bearer ${TOKEN}` },
  }
);
const { data } = await res.json();
python
import os
import requests

reaction_id = os.environ["REACTION_ID"]  # id from the "added" response of POST /ai/reactions/toggle

res = requests.delete(
    f"{BASE_URL}/ai/reactions/{reaction_id}",
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]

Built with purpose.