Technical docs
Message Reactions
Public reference generated from tech docs/message-reactions.md.
Overview
Support reference for the current message feedback and reaction paths.
What the backend actually supports
- Feedback state now lives on the `messages` table itself: - `reaction` - `reaction_at` - `feedback_comment` - `feedback_comment_at` - `feedback_state_updated_at` - `reaction_by_*` - Accepted reactions are: - `like` - `dislike` - `null` to clear feedback - `feedback_comment` is only retained for `dislike`. - Clearing the reaction clears the entire feedback state.
Eligibility and validation
- Backend feedback is rejected for: - `operator` messages - `contact` messages - That means backend eligibility currently allows feedback on assistant-side `ai` and `bot` messages. - `feedback_comment` is capped at `500` characters.
Public webchat API
- Public webchat feedback route is: - `PUT /api/public/webchat/messages/{message_id}/feedback` - Accepted body: - `{ "reaction": "like" | "dislike" | null, "feedback_comment"?: string | null }` - The processor verifies that: - the public API key resolves an organization - the `webchat-token` resolves a webchat session/contact - the message belongs to a conversation accessible through that contact channel - The route returns the full updated webchat message object, not just the reaction value.
Current widget mismatch
- The widget client still calls: - `PUT /api/public/webchat/messages/{message_id}/reaction` - Widget body: - `{ "reaction": "like" | "dislike" | null }` - There is no matching `/reaction` route in the current public webchat router. - If contact-side reactions are failing in the shipped widget, this path mismatch is the first thing to check.
Widget-side behavior
- The widget only shows reaction buttons when: - `message.role === 'ai'` - It does not show them for: - `bot` - `operator` - Clicking the same reaction twice toggles it back to `null`. - The widget updates reaction state optimistically in local component state.
Propagation to Omni and the widget
- Public webchat feedback updates emit: - `conversation.message_updated` to organization websocket clients - Omni consumes that event and reads reaction fields from the updated message payload. - Omni renders feedback as read-only footer state on outgoing messages. - The widget listens for: - `webchat.message_updated` - But its websocket handler currently only patches: - `content` - `updated_at` - It does not reconcile websocket-delivered reaction, comment, or actor fields.
Internal chat feedback path
- Internal chat uses the organization route: - `PUT /api/organizations/{orgId}/conversations/{conversationId}/messages/{messageId}/feedback` - That flow emits: - `internal.message_updated` - Internal chat feedback also adds rate limiting for repeated changes on the same message.
Reporting API
- Aggregate webchat AI feedback stats are available from: - `GET /api/organizations/{orgId}/messages/stats` - Supported `types` query values are: - `total` - `likes` - `dislikes` - Those counts are scoped to: - `role = ai` - `channel = web_chat`