Feedback

Set feedback on <ChatWidget> to show thumbs up/down under completed assistant messages. The client always fires its local onFeedback callback and makes a best-effort POST to ${apiBase}/v1/feedback.

code
<ChatWidget
  apiBase="/api/chat"
  config={{
    schemaVersion: 1,
    runtime: { model: 'anthropic/claude-sonnet-4-5' },
    client: { feedback: true },
  }}
  onFeedback={(event) => analytics.track('chat_feedback', event)}
/>

Persist on the server

The mounted handler validates the payload, resolves the user again through getUserId, and calls its server-side onFeedback seam. Browser identity is never authoritative.

code
import { createHostedFeedback }
  from '@mordn/chat-widget/server/hosted';
 
createChatHandler({
  getUserId: getChatUserId,
  model,
  store,
  onFeedback: createHostedFeedback({
    apiKey: process.env.MORDN_CHAT_KEY!,
  }),
});

Without a server onFeedback, the handler acknowledges valid submissions but does not persist them. Recording failures are logged and still return { ok: true }; feedback must not break chat.

The submitted shape is:

code
interface FeedbackEvent {
  userId: string; // added by the verified server handler
  conversationId?: string;
  messageId: string;
  rating: 'up' | 'down';
  reason?: string;
}

Hosted summary

code
curl "https://api.mordn.com/v1/feedback/summary?from=2026-07-01" \
  -H "Authorization: Bearer $MORDN_CHAT_KEY"

The current response is the aggregate count only:

code
{
  "up": 1601,
  "down": 239,
  "total": 1840
}

from and to are optional. The endpoint does not currently return upRate or recent reason text; compute the rate client-side and use a separate authorized surface if reason inspection is required.