- Sending and reading reports is free. It never uses the API wallet or the plan pool.
- On REST, an API key with any scope can send and read reports, and so can any OAuth token.
- Each account can send 60 reports in any rolling hour.
When to send a report
Report a problem when:- An endpoint or tool failed, or returned the wrong result.
- An error did not say how to fix the request.
- The docs were missing, wrong, or unclear.
- You needed something the API does not do.
- A call was too slow, timed out, or hit a rate limit sooner than you expected.
Report fields
Send a JSON object with asummary. Every other field is optional, but each one you include helps the team reproduce the problem.
How intake handles imperfect reports
Intake fixes what it can instead of refusing, so a stuck agent is not stopped by its own report. The report’sadjustments array lists every change.
- Text over its field’s limit is trimmed.
- An unknown
categoryis filed asother. Common words map to a category:errorbecomesbug,documentationbecomesdocs, andslowbecomesperformance. - An unknown
impactis left empty. Common words map here too, such asblockingtoblockedandworkaroundtoworked_around. - In
categoryandimpact, case does not matter, and spaces or hyphens count as underscores.Worked aroundis filed asworked_around. - A value that looks like a credential is replaced with
[redacted:<kind>].
- A value that is not a string, such as a number or an object, is stored as its JSON text.
- Fields intake does not recognize are kept with the report. If their JSON is over 4,000 characters, they are dropped instead, so put long text in
details.
The only refusal is a report with no
summary and no details. It returns 400 invalid_feedback, and the message shows a valid body.
Limits and cost
- Reports never use the API wallet or the plan pool, so an account with an empty wallet or a spent plan pool can still send one.
- On REST, each report counts as one request against your rate limits. Reading reports does not.
- On MCP, each
send_feedbackorlist_feedbackcall counts as one request. - An account can send 60 reports in any rolling hour. The next one returns
429 feedback_rate_limitedwith aRetry-Afterheader in seconds. Wait that long, or combine what is left into one report.
Send a report over REST
POST /api/developers/v1/feedback stores the report and returns 201:
guidance, which says where the reply will appear:
fb_ id to read the reply.
Send a report with the SDK
Since SDK 0.5.0,client.feedback sends reports and reads the team’s replies.
client.feedback.send takes the report fields in camelCase: errorCode and requestId send error_code and request_id. It is never retried automatically, because a retry could file the report twice. If a send fails without a response, check client.feedback.list before you send the report again.
client.feedback.list({ status, limit }) and client.feedback.get(feedbackId) are reads, so the SDK retries them like other reads.
Send a report with the CLI
Since CLI 0.5.0,sb feedback sends reports and reads the team’s replies. By default, it prints JSON on stdout, like other sb commands.
sb feedback send also takes --details, --suggestion, --tool, --error-code, --request-id, and --agent. For a longer report, put the JSON body in a file and pass --input report.json, or --input - to read standard input. The file uses the REST field names, and flags override its fields. The CLI skips any other field and warns on stderr.
If sb feedback send fails after a server error or a timeout, the report may already be filed. Check sb feedback list before you run it again. Add --pretty for readable text instead of JSON.
Send a report over MCP
The StefanBrain MCP server instructions tell your assistant to callsend_feedback when a tool or endpoint fails, returns the wrong thing, or lacks something it needs.
send_feedback takes the same fields as the REST body, and summary is required. category and impact accept any text and are mapped the same way as on REST.
list_feedback returns your reports with the team’s replies. It takes an optional status and a limit from 1 to 50, 20 by default:
Read the team’s reply
Each report starts asopen. A reply from the team sets one of the other statuses:
The reply reaches your agent in three ways:
- REST, SDK, and CLI:
GET /api/developers/v1/feedback/{feedback_id}returns one report withreplyandreplied_at.GET /api/developers/v1/feedbacklists your reports, newest first, and acceptsstatusandlimit(1–100, default 20). - MCP tool:
list_feedbackreturns the same reports. - MCP connection: the next connection’s server instructions end with up to 3 replies to this account’s reports from the last 14 days, newest first. Each reply is shortened to 300 characters there;
list_feedbackshows the full text.
404 feedback_not_found.
Keep secrets out of reports
Never put API keys, OAuth tokens, or passwords in a report. Intake replaces values that look like credentials, such asstefan_sk_ keys, bearer tokens, and JWTs, and notes each one in adjustments. It cannot recognize every secret, such as a short password.
Each report also carries your account email and plan, and your client’s name and version or user agent. It names the API key, by name and last four characters, or the OAuth connector.
Errors
On MCP,
send_feedback returns failures as a tool error with isError: true. A blank summary with no details gets an invalid-input message that shows a valid body. A rate limit says how many milliseconds to wait.
Authentication, scope, and request-limit failures use the shared codes in Errors and retries. The generated REST reference has the exact request and response schemas.
