---
title: "Report a wrong or missing record"
method: POST
path: "/v2/feedback"
tags: ["feedback"]
---

# Report a wrong or missing record

`POST /v2/feedback`

## Request

- Base URL: `https://api.cardog.app`
- URL: `https://api.cardog.app/v2/feedback`
- Auth: one of:
  - API key in header `x-api-key`
  - HTTP bearer

Tell us a record is wrong or missing, for example a VIN that decodes `valid: false` when you know what the vehicle is. Costs 0 credits. Returns a receipt whose `id` you can read back at GET /v2/feedback/{id}. A report is an observation: it never changes a record by itself. The same report from the same caller within 24 hours returns the original receipt with 200 instead of storing a second one. Limited to 60 reports a minute and 1,000 a day per key.

## Request body

- FeedbackCreateRequest
  - `kind` 'decode_miss' | 'decode_dispute' | 'recall_dispute' | 'spec_dispute' | 'listing_report' | 'resolve_miss' | 'other', required: What is being reported. "decode_miss": a VIN we could not decode. "decode_dispute": a VIN we decoded to the wrong vehicle. "recall_dispute", "spec_dispute", "listing_report", "resolve_miss" and "other" are accepted and stored; their resolution reads "queued" until they are routed.
  - `subject` object, required: What the report is about: exactly one of vin, ref, or listing_id
    - `vin` string: 17-character VIN the report is about
    - `ref` string: A ref the report is about, e.g. "model-year:honda/cr-v/2026" or "recall:tc/2024-123"
    - `listing_id` string: Listing id the report is about
  - `request_id` string: X-Request-Id (or cf-ray) of the response being disputed, when there is one
  - `claim` object: What you believe is true. Every field is optional; send the ones that apply to the kind.
    - `year` integer: Model year you believe is correct
    - `make` string: Make you believe is correct, e.g. "Toyota"
    - `model` string: Model you believe is correct, e.g. "Sienna"
    - `trim` string: Trim you believe is correct, e.g. "XSE"
    - `field` string: The field in dispute, e.g. "gvwr" (required for spec_dispute)
    - `expected` string: The value you expected
    - `observed` string: The value the API returned
  - `evidence` object[]: Up to 5 supporting links or excerpts
    - `type` 'url' | 'text', required: "url" for a link, "text" for a quoted excerpt
    - `value` string, required
  - `note` string: Free text, up to 2000 characters (required for resolve_miss)
  - `contact` boolean: Whether we may email the key owner about this report. Stored; not acted on yet.

## Response `200`

This caller filed the same report in the last 24 hours. The original receipt; nothing new is stored.

- Feedback
  - `id` string, required: Report id, e.g. "fb_01J8Z3K5V6W7X8Y9Z0A1B2C3D4"
  - `kind` 'decode_miss' | 'decode_dispute' | 'recall_dispute' | 'spec_dispute' | 'listing_report' | 'resolve_miss' | 'other', required: What is being reported. "decode_miss": a VIN we could not decode. "decode_dispute": a VIN we decoded to the wrong vehicle. "recall_dispute", "spec_dispute", "listing_report", "resolve_miss" and "other" are accepted and stored; their resolution reads "queued" until they are routed.
  - `subject` object, required: The subject as submitted
    - `vin` string
    - `ref` string
    - `listing_id` string
  - `status` 'received' | 'triaged' | 'accepted' | 'rejected' | 'shipped', required: "received" on submit. "triaged" once an operator has looked at it. "accepted" or "rejected" is the verdict. "shipped" means the fix is live; `resolution.fixed_in` names the version.
  - `received_at` string, required: When the report was received (ISO 8601)
  - `resolution` object, nullable, required: Null until triaged, except for kinds no lane acts on yet, which read outcome "queued"
    - `outcome` 'queued' | 'accepted' | 'rejected' | 'shipped', required: "queued" while no lane acts on this kind yet; otherwise the triage verdict
    - `note` string, nullable, required: Operator note, when there is one
    - `fixed_in` string, nullable, required: Version that carries the fix, e.g. a decoder release. Null until shipped.
    - `resolved_at` string, nullable, required: When the verdict was reached (ISO 8601)
  - `links` object, required: Server-relative paths. Always includes "self"; includes "subject" when the subject has a v2 resource.

## Other responses

- `202`: Received. The report is stored with status `received`.
- `400`: Invalid request — grammar failure or unknown-but-well-formed refs, NAMED in `refs`/`details`, with nearest-ref `suggestions` where computable. Never a fuzzy fallback.
- `401`: No valid credential (API key, session, or internal token)
- `403`: Credential lacks the scope for this route group (`forbidden`)
- `429`: Per-minute rate limit exceeded
- `500`: Internal error

---

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