---
title: "Submit in-product feedback"
method: POST
path: "/feedback"
tags: ["Feedback"]
---

# Submit in-product feedback

`POST /feedback`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/feedback`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Mnemom-Api-Key`
  - API key in cookie `mnemom_session`

Ingest a single piece of in-product feedback (compliment / problem / suggestion) from an authenticated user (web app) or agent (MCP/gateway). Reporter-supplied content is redacted (email / API-key / JWT / phone / long-hex shapes replaced with `[redacted:*]`) BEFORE storage, and the sensitive context fields (`ai_prompts`, `diagnostics`) are dropped unless the matching consent flag is set. Idempotent: a replayed request carrying the same `Idempotency-Key` returns the same `feedback_id` and creates no duplicate row. Inherits the standard per-IP REST rate limit.

## Headers

- `Idempotency-Key` string, required

## Request body

- object
  - `category` 'compliment' | 'problem' | 'suggestion', required: Reporter-selected intent.
  - `title` string, required: Short title (redacted before storage).
  - `body` string, required: Feedback body (redacted before storage).
  - `consent_prompts` boolean: When true, `context_bundle.ai_prompts` is stored (redacted); otherwise it is dropped.
  - `consent_diagnostics` boolean: When true, `context_bundle.diagnostics` is stored (redacted); otherwise it is dropped.
  - `consent_contact` boolean: When true, the reporter opts in to a resolution-email notification.
  - `context_bundle` object: Optional diagnostic context. `route_url` and `breadcrumbs` are always redacted-and-stored; `ai_prompts` / `diagnostics` are consent-gated.
    - `route_url` string: App route the reporter was on.
    - `app_version` string: Client app version.
    - `component` string: Inferred UI component/area.
    - `breadcrumbs` unknown[]: Recent UI actions (roles/test-ids only, never raw input).
      - unknown
    - `ai_prompts` unknown
    - `diagnostics` object: Client diagnostics (stored only with consent_diagnostics).
  - `attachment_ids` string[]: IDs of previously-presigned pending attachments to bind to this submission.
  - `company_website` string: Honeypot — must be empty. Any non-empty value silently accepts and persists nothing.

## Response `201`

Feedback accepted and stored (redacted).

- object
  - `feedback_id` string, uuid: The stored submission id (absent on a honeypot-silent accept).
  - `status` 'received', required: Client-facing acknowledgement status.

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Forbidden
- `409`: Resource conflict — the request cannot proceed because of a current state conflict (e.g., resource already exists, version mismatch, in-flight idempotency key with a different body).
- `422`: Request was well-formed but semantically invalid (e.g., business-rule validation failure, malformed YAML inside a JSON payload).
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.

---

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