API Reference
REST API for programmatic access to feedback data.
Base URL
https://api.feedboon.com/api/v1Authentication
Every request needs an API key in the Authorization header:
Authorization: Bearer fbk_your_api_keyCreate API keys in the Feedboon dashboard under Account → API Keys.
Endpoints
/meWhat this key can do: its permissions and the projects it can currently reach. A useful first call — a project missing here is served by no other endpoint.
/projectsList the projects this key can reach.
/feedbackList bugs in one project. Requires project_id; optional status, priority, page and per_page.
/feedback/:idGet one bug with its description, page context, metadata and console errors.
/feedback/:idUpdate title, description, status, priority or assignee. Accepts the bug id, the reference the dashboard shows, or the external_id it was imported with.
/feedback/:id/commentsList the comments on a bug.
/feedback/:id/commentsAdd a comment to a bug.
/feedback/bulkImport up to 50 bugs at once. Two steps: preview shows where they would land, confirm writes them.
/imports/:batch_id/undoTake back one import. The bugs are archived and can be restored from the dashboard.
Example request
curl -X GET "https://api.feedboon.com/api/v1/feedback?project_id=YOUR_PROJECT_ID&status=new" \
-H "Authorization: Bearer fbk_your_api_key"Project ids come from GET /projects.
Response
{
"data": {
"items": [
{
"id": "8f14e45f-ceea-467a-9f0c-2b1a3d5e7c91",
"feedback_number": 7,
"feedback_prefix": "FB",
"title": "Checkout button does nothing",
"status": "new",
"priority": "high",
"page_url": "https://acme.com/checkout",
"browser": "Chrome 120",
"has_screenshot": true,
"has_console_errors": true,
"created_at": "2026-01-25T10:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1
}
},
"error": null
}feedback_prefix and feedback_number are the reference a human reads on the card — "FB-7" above. id is the one to pass back to the API.
Importing bugs in bulk
Bulk import is two calls on purpose, so a batch can never land in the wrong project unnoticed. The first writes nothing and tells you where the items would go; the second writes them.
Step 1 — preview
curl -X POST https://api.feedboon.com/api/v1/feedback/bulk \
-H "Authorization: Bearer fbk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"project": "acme",
"items": [{
"external_id": "BUG-042",
"title": "Checkout button does nothing",
"page_url": "https://acme.com/checkout",
"found_in": "pre_release"
}]
}'The response names the project, counts what is new versus what would be updated, and returns confirm_token together with next_step — the exact call to make next.
Step 2 — confirm
curl -X POST https://api.feedboon.com/api/v1/feedback/bulk \
-H "Authorization: Bearer fbk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"project": "acme",
"mode": "confirm",
"confirm_token": "<from the preview response>",
"items": [ ... the same items, unchanged ... ]
}'Two things the token enforces: it belongs to one project, and it is bound to the exact items it previewed. Editing an item between the calls invalidates it, as does letting it expire — the window is returned as confirm_token_expires_in.
Two fields are worth getting right. external_id is your own id for the bug, and re-sending it updates that bug instead of creating a duplicate. found_in is required and says where the bug was found — pre_release, staging or production.
Keys, rotation and revocation
A key reaches only the projects it was created for, and only while its owner still has access to them — remove someone from a project and their keys stop reaching it on the next request.
Revoking takes effect immediately, because every request re-checks the key. Replacing one is different: a long-running process reads its environment once at start, so a new key takes effect after that process restarts. Rotation issues the replacement while the previous key keeps working for 24 hours, which is what makes changing keys a non-event.
Responses and limits
Every response — success or error — is JSON shaped { data, error }, and the HTTP status carries the outcome: 401 for a missing or invalid key, 400 for input the API rejected, with error.message naming the field.
Requests are rate limited per key, reads more generously than writes. Over the limit the API answers 429 with code RATE_LIMITED; wait and retry. Batch your work where you can — one bulk import of 50 bugs costs a single call.
Troubleshooting
A response that is not JSON. If you receive HTML or plain text, the request was answered before it reached Feedboon — it is not about your API key or your project permissions. Send a User-Agent that identifies your application and retry.
An import that keeps previewing. The write happens only with mode: "confirm" and the token from the preview. Other spellings are rejected rather than silently previewed, and the preview response carries the call to make in next_step.
OpenAPI specification
The full machine-readable description, for generating a client or importing into Postman and Insomnia:
curl https://api.feedboon.com/api/v1/openapi.json