---
title: "File structured feedback: bug, improvement, complaint, praise, or question"
method: POST
path: "/api/feedback"
---

# File structured feedback: bug, improvement, complaint, praise, or question

`POST /api/feedback`

## Request

- Base URL: `https://api.signalbureau.ai`
- URL: `https://api.signalbureau.ai/api/feedback`
- Auth: none declared

The desk's feedback window (also the MCP send_feedback tool). Free, no contact details required; include ref (a quoteId/ticketId/orderId) to tie the report to a specific interaction. A complaint that names a real defect becomes our work order. Plan ONE request per report. Caps: summary 4,000 characters (overflow moves to detail), detail 40,000 characters, the report's text 64,000 bytes, up to 5 text attachments (text/markdown, text/plain, application/json) of 64,000 bytes each stored with the report — an attachment over its cap refuses the request with the reason named, never cut. A report larger than that is split: later parts carry continues (part 1's feedbackId) and part/of, and the parts merge into one work order. reporter (product, developer, model, version — any may be "unexposed") labels the work order by product. The response is honest about durability: recorded:true only when the store accepted the row; on store trouble you get a 503 asking for a retry rather than a silent loss. Every receipt carries stored (sent vs stored character counts, sha256 of the stored detail, each attachment's bytes and sha256), resend (the exact instruction when anything did not fit) and workOrder (linked at the next sweep, 07:46 / 19:46 UTC). Limits: 5/minute burst, 20/day per network address (shared egress shares the allowance).

## Request body

- object
  - `kind` 'bug' | 'improvement' | 'complaint' | 'praise' | 'question', required
  - `summary` string, required: One sentence: what happened or what you want
  - `detail` string: Reproduction steps, expected vs observed (optional)
  - `about` string: Which tool/endpoint/page this concerns (optional)
  - `ref` string: A quoteId, ticketId, or orderId to tie this to (optional)
  - `reporter` object: Who is reporting (optional; every field optional, any may be "unexposed")
    - `product` string
    - `developer` string
    - `model` string
    - `version` string
  - `attachments` object[]: Up to 5 text files stored with the report, each at most 64,000 bytes of UTF-8 content (optional). One over its cap or of another type refuses the request with the reason named.
    - `name` string
    - `mimeType` 'text/markdown' | 'text/plain' | 'application/json'
    - `content` string, required: The file's text (not base64)
  - `continues` string, uuid: Part 1's feedbackId, when this request carries a later part of a split report (optional)
  - `part` integer: This part's number (optional)
  - `of` integer: How many parts the report has (optional)

## Response `200`

{ok, feedbackId, recorded:true, truncated, movedToDetail, notFiled, stored, resend, reporter, workOrder, note}

## Other responses

- `413`: Too large: the report's text over 64,000 bytes, the whole request over its ceiling, or an attachment over 64,000 bytes (code attachment_too_large, naming the attachment). Nothing was stored.
- `422`: Missing/invalid kind or summary, or an attachment of an unaccepted type or shape, or more than 5 (the code and message name which).
- `429`: Faster than the stated limits.
- `503`: recorded:false — store briefly down; retry rather than silent loss.

---

[API](https://skmtc.dev/sigb/apis/signal-bureau-api.md) · [All operations](https://skmtc.dev/sigb/apis/signal-bureau-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sigb/apis/signal-bureau-api/revisions/290c9c6ca0d0?raw)
