Feedback¶
The feedback loop captures per-statement accuracy ratings and feeds a rolling template-accuracy aggregate. Use it to surface which templates ring true for your users and which need rewriting.
Submit — POST /v1/feedback¶
Required scope: feedback:write
Request¶
{
"statement_id": "019e32cb-...",
"verdict": "correct",
"role": "subject",
"confidence": 0.9,
"comment": "Spot on — this is exactly how I deal with pressure."
}
| Field | Type | Required | Notes |
|---|---|---|---|
statement_id |
string | yes | The specific statement being rated. The server derives its template, skill, and chart from this. |
verdict |
enum | yes | correct, doubtful, or wrong. |
role |
enum | no, default "subject" |
Who is rating: subject, observer, or hr_admin. |
user_id |
string | no | Optional rater id, for your own attribution. |
organization_id |
string | no | Optional org id, for your own attribution. |
confidence |
float, 0–1 | no | How sure the rater is. |
comment |
string | no, max 2 000 chars | Free-text. Stored for review; not used in the aggregate. |
Response — 201 Created¶
{
"id": "019e32d2-...",
"statement_id": "019e32cb-...",
"chart_id": "019e32b5-...",
"template_id": "resilience-strength-high-en",
"skill_id": "resilience",
"verdict": "correct",
"role": "subject",
"submitted_at": "2026-05-16T22:10:00Z",
"user_id": null,
"organization_id": null,
"comment": "Spot on — this is exactly how I deal with pressure.",
"confidence": 0.9
}
The template_id, skill_id, and chart_id are resolved server-side from the
statement_id and returned for convenience.
Fetch — GET /v1/feedback/{feedback_id}¶
Required scope: feedback:read
Returns the same FeedbackEntry shape as the create response.
Template accuracy aggregate — GET /v1/feedback/templates/{template_id}¶
Required scope: feedback:read
Returns the rolling accuracy aggregate for a single template across the caller's tenant.
{
"template_id": "resilience-strength-high-en",
"sample_size": 142,
"correct_count": 110,
"doubtful_count": 22,
"wrong_count": 10,
"accuracy": 0.82,
"deprecated": false,
"updated_at": "2026-05-16T22:10:00Z"
}
| Field | Type | Notes |
|---|---|---|
sample_size |
int | Total ratings in the window. |
correct_count / doubtful_count / wrong_count |
int | Raw counts per verdict. |
accuracy |
float, 0–1 | (correct + 0.5 × doubtful) / sample_size. |
deprecated |
bool | Whether the template has been flagged for retirement. |
updated_at |
ISO 8601 | When the aggregate was last recomputed. |
The aggregate is recomputed asynchronously after each feedback submission (within ~60 s). Treat it as eventually-consistent.
Operational uses¶
- Drop low-accuracy templates from the eligible set. If a template's
rolling accuracy is below your threshold, exclude it from the
interpretations:writepath. The platform itself usesaccuracy < 0.4as a default suppression cutoff (configurable). - Compare tone variants. When
use_llm_rewrite: trueproduces multiple phrasings of the same template, feedback on the resulting statement-id ties back to the template-id so you can compare across styles. - Surface in admin dashboards. The
GET .../templates/{id}endpoint is the same data the platform exposes in its operator console.
Feedback is per-tenant — your aggregates do not mix with another tenant's. Cross-tenant rollups are an admin-only feature surfaced via a separate internal endpoint, not via this REST surface.