Features

Reactions

Reactions

Emoji reactions are a (message_id, user_id, emoji) triple. One reaction per user per emoji per message.

#Endpoints

POST   /api/messages/{message_id}/reactions
DELETE /api/messages/{message_id}/reactions/{emoji}

POST body: {emoji}. Both endpoints require workspace membership for the message's workspace. Adding twice is a no-op that returns HTTP 200 without an event; removing a missing reaction is a no-op. Mutation responses include an event object and the message's complete aggregated reaction summaries. The event fields are empty on a no-op for compatibility with the existing mutation response shape.

Message reads expose reactions as per-emoji summaries:

{"emoji":"lobster","count":3,"reacted_by_me":true}

The API does not include the individual reacting users in message payloads.

#Events

  • reaction.added on add
  • reaction.removed on remove

The event payload contains {message_id, emoji, user_id, count} and inherits the message's channel_seq. count is the authoritative total for that emoji after the mutation, so realtime clients do not need to refetch the message.

#Storage

Reactions are stored verbatim — there's no allowlist or canonical shortcode table. Pass any string the UI is willing to render. Crustacean reactions like :lobster: and :claw: are intended in the reaction pack but not enforced server-side.