---
title: "Submit Line Feedback"
method: POST
path: "/v1/feedback"
tags: ["Accuracy Feedback"]
---

# Submit Line Feedback

`POST /v1/feedback`

## Request

- Base URL: `https://api.vectelos.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.vectelos.com/v1/feedback`
- Auth: none declared

Record one signal from one reader.

Authenticated so only signed-in users can post, and then the identity is
dropped: `current_user` is not passed to `record_line_feedback`, so the
feedback row itself carries nothing that ties it to an account or a shipment.

The one deliberate exception: a "flagged" signal bumps an opaque per-tenant
counter in `vectelos_activation` (via `note_thumbs_down`) so a marketing
cohort's flag rate is visible. That store holds counts only — no feedback
content, no HTS code, nothing joinable back to what was flagged. See
`GTM_plan.md` §4.4.

## Headers

- `authorization` string, nullable: Bearer <JWT session token>

## Cookies

- `vx_session` string, nullable

## Request body

- LineFeedback: One signal from the person reading a report. ZERO DOC STORE. This is the only route by which anything derived from a customer's document reaches durable storage, and it exists because the engine cannot grade itself: a stored HTSUS code is what we decided, not whether we were right. Feedback is the grade. Three rules hold it to the claim on the site: 1. Nothing is written unless the reader submits it. We do not sample reports, and no background process reads a stored report. 2. No `user_id`, no `job_id`, no tenant identifier is recorded. The request is authenticated so only signed-in users can post, and then who they are is deliberately dropped. 3. Money and quantities never travel. Not the entered value, not the duty assessed, not the line total. WHY THERE IS NO "THIS IS CORRECT" SIGNAL. A thumbs-up cannot distinguish "I checked this against my broker's last entry" from "I clicked the green one because the red one asked me questions" -- but it looks like data, and at low volume it would manufacture an accuracy denominator we have not earned. Silence is allowed to mean silence. The one exception is `description_confirmed`, which answers a specific question about a specific line ("is this roughly what it is?") and so carries actual information.
  - `signal` 'flagged' | 'extraction_error' | 'description_confirmed' | 'description_wrong', required: What the reader is telling us
  - `hts_code` string: The code the engine selected
  - `confidence` number, nullable: Engine confidence, 0-1
  - `duty_rate_pct` number, nullable: Effective rate applied
  - `chapter99_codes` string[]: Remedy headings applied, e.g. 9903.82.02
  - `caveats_fired` integer: How many determinations the engine declined to make
  - `engine_reasoning` string, nullable: The engine's own stated reasoning for this classification
  - `origin_country` string, nullable
  - `port_city` string, nullable
  - `port_state` string, nullable
  - `what_is_wrong` string, nullable: Which part looks wrong, from a fixed list the UI offers
  - `suggested_hts_code` string, nullable
  - `comment` string, nullable
  - `include_description` boolean: True only when the reader chose to send the item description
  - `item_description` string, nullable: Sent only when include_description is true; dropped otherwise

## Response `201`

Successful Response

- FeedbackAck
  - `recorded` boolean, required
  - `description_included` boolean, required: Echoes back whether the description was stored, so the UI can tell the reader what actually left their browser
  - `message` string, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/vectelos/apis/vectelos-api.md) · [All operations](https://skmtc.dev/vectelos/apis/vectelos-api/llms.txt) · [OpenAPI document](https://skmtc.dev/vectelos/apis/vectelos-api/revisions/8e68c96f24fa?raw)
