On this page
Reports
Reports are how you tell us something is broken or missing. Filing one stores it against your organization and notifies us; listing them shows you everything your organization has filed and where each one stands.
For the workflow, including what makes a report actionable, see Support.
All endpoints require an organization API key. A read-only key is enough to file — reporting a problem is not a change to your content.
File a report
POST /v1/reports
curl -s -X POST "$DOCSARY_API/v1/reports" \
-H "authorization: Bearer $DOCSARY_KEY" \
-H "content-type: application/json" \
-d '{
"kind": "bug",
"title": "Search returns nothing for hyphenated terms",
"body": "Searching for drop-in on our site returns zero results, but drop in finds the page. Reproduced on two versions.",
"page_url": "https://docs.acme.com/guide/search",
"contact": "docs@acme.com",
"meta": { "client": "ci", "version": "2.4.1" }
}'
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
string | yes | bug or feature. Nothing else is accepted. |
title |
string | yes | 3–200 characters after trimming. One line; the detail goes in body. |
body |
string | yes | 10–10000 characters after trimming. Plain text. |
page_url |
string | no | The page the report is about. An http/https URL, a site-relative path, or a #fragment. |
contact |
string | no | An email address, at most 200 characters. We reply to it. |
meta |
object | no | Anything that helps — client name, version, browser. At most 2000 characters once serialized. |
{
"id": "rep_9f2c4a1b7e6d8035c1a4b9e2f7d60a83",
"kind": "bug",
"title": "Search returns nothing for hyphenated terms",
"status": "open",
"created_at": 1756300000000,
"email": { "status": "sent" }
}
201 on success. The report is stored before we try to notify ourselves, so the id in this response is a record that exists whatever the email block says.
The email block
Every report is stored first and notified second. This block reports what the second step did, so you never have to guess whether it happened.
status |
Meaning |
|---|---|
sent |
We were notified. |
skipped |
Notifications are not configured right now, with a reason. |
failed |
The notification could not be delivered, with an error. |
A skipped or failed notification does not lose your report. It is stored, it has an id, it appears in your list, and we work from the stored record. This block exists so the response tells you exactly what happened rather than implying more than did.
Errors
| Response | Cause |
|---|---|
400 {"error":"kind must be one of: bug, feature"} |
kind missing or not one of the two |
400 {"error":"title required (string)"} |
title missing or not a string |
400 containing title must be 3..200 characters |
Title too short or too long |
400 {"error":"body required (string)"} |
body missing or not a string |
400 containing body must be 10..10000 characters |
Body too short or too long |
400 containing unsafe page_url |
page_url is not an allowed URL shape |
400 {"error":"contact must look like an email address"} |
contact is not an email address |
400 {"error":"meta must be an object"} |
meta is an array or a scalar |
400 containing meta is too large |
meta serializes to more than 2000 characters |
401 {"error":"missing bearer token"} |
No key. There is no anonymous filing path |
403 {"error":"org API key required (not admin token)"} |
A report belongs to an organization |
429 containing reports per hour |
Your organization's hourly filing limit |
The page_url allow-list is the one used for site settings and markdown links: http:, https:, mailto:, a path beginning with a single /, or a #fragment. javascript:, data:, protocol-relative //host, and schemeless relative paths are refused:
{"error":"unsafe page_url (allowed: http:, https:, mailto:, or a /site-relative path)"}
Filing limit
An organization may file 20 reports per hour. The 21st is refused with 429:
{
"error": "too many reports: this organization may file 20 reports per hour. Add the detail to an existing report, or wait and file again.",
"limit": 20,
"window": "hour"
}
Nothing is stored, and the reports you already filed are untouched. The limit is per organization and counted over the preceding hour rather than reset on the clock hour. If you have a real reason to exceed it — a batch of findings from an audit, say — ask us rather than looping.
List your reports
GET /v1/reports
curl -s -H "authorization: Bearer $DOCSARY_KEY" \
"$DOCSARY_API/v1/reports?status=open&limit=20"
{
"reports": [
{
"id": "rep_9f2c4a1b7e6d8035c1a4b9e2f7d60a83",
"kind": "bug",
"title": "Search returns nothing for hyphenated terms",
"body": "Searching for drop-in on our site returns zero results...",
"page_url": "https://docs.acme.com/guide/search",
"contact": "docs@acme.com",
"meta": { "client": "ci", "version": "2.4.1" },
"status": "open",
"created_at": 1756300000000
}
],
"next_offset": null
}
Newest first. You see your own organization's reports and nothing else — the organization is taken from your key, never from the request.
| Parameter | Default | Notes |
|---|---|---|
status |
all | open, triaged, or closed. Any other value is a 400. |
limit |
50 |
Capped at 200. |
offset |
0 |
Rows to skip. |
next_offset is the offset to pass for the next page, or null once you have reached the end — the same paging shape as rerender.
status |
Meaning |
|---|---|
open |
Received, not yet looked at |
triaged |
Read and understood, and on a list |
closed |
Done, or decided against |
Status is set by us. There is no endpoint for an organization to change it; to reopen something, file a new report and quote the old id in the body.
Errors
| Response | Cause |
|---|---|
400 containing unknown status |
status is not one of the three |
400 {"error":"limit must be a positive number"} |
limit is zero, negative, or not a number |
400 {"error":"offset must be zero or a positive number"} |
offset is negative or not a number |
401 {"error":"missing bearer token"} |
No key |
403 {"error":"org API key required (not admin token)"} |
The list is scoped to an organization |