
Get Bugbot review analytics with the Analytics API
Pull one row per completed Bugbot review with GET https://api.cursor.com/analytics/team/bugbot-reviews. Official reference: Analytics API → Bugbot review analytics.
Authenticate with Basic auth (API key as username, empty password). Create keys at Cursor Dashboard → API Keys. This endpoint requires scope read:*. Other Analytics endpoints typically need admin:*. Availability: Enterprise only. Team-level rate limit: 100 requests per minute per team.
Each item includes the reviewed commit, findings count, billed cost when applicable, and per-finding resolution data. Posted reviews and dry-run reviews both appear. Posted findings use comment_id and resolution_status. Dry-run findings return title, description, and locations instead because nothing is posted to the SCM.
Query parameters
| Parameter | Rules |
|---|---|
startDate |
Optional. Default: 7 days ago. Prefer YYYY-MM-DD, or shortcuts now / today / yesterday / Nd. Max range 30 days. Time is ignored (day-level UTC). |
endDate |
Optional. Default: now. Same formats as startDate. |
repo |
Optional. host/owner/repo. Protocol and .git suffix are optional. |
prNumber |
Optional. Pull request or merge request number. |
page |
Optional. 1-indexed. Default: 1. |
pageSize |
Optional. Reviews per page. Default: 100, max: 250. |
dryRun |
Optional boolean. true = dry-run only; false = posted only. |
Omit both dates for the default window (simplest path for HTTP caching). Prefer day shortcuts or YYYY-MM-DD over ISO timestamps so ETag cache hits stay stable.
Request
curl --get https://api.cursor.com/analytics/team/bugbot-reviews \
-u YOUR_API_KEY: \
--data-urlencode 'startDate=2026-06-01' \
--data-urlencode 'endDate=2026-06-29' \
--data-urlencode 'repo=github.com/your-org/your-repo' \
--data-urlencode 'prNumber=42' \
--data-urlencode 'page=1' \
--data-urlencode 'pageSize=100'
Dry-run reviews only:
curl --get https://api.cursor.com/analytics/team/bugbot-reviews \
-u YOUR_API_KEY: \
--data-urlencode 'dryRun=true' \
--data-urlencode 'repo=github.com/your-org/your-repo' \
--data-urlencode 'prNumber=42'
Example posted-review response:
{
"data": [
{
"request_id": "6e0d261c-86a2-4383-89f0-9162c1c10662",
"timestamp": "2026-06-29T19:42:18.000Z",
"repo": "github.com/your-org/your-repo",
"repo_node_id": "R_kgDOABCDEF",
"pr_number": 42,
"commit_sha": "9f3c2a1b7d8e4f5061728394a5b6c7d8e9f0a1b2",
"bugs_found": 2,
"cost_cents": 42.5,
"dry_run": false,
"publication_status": "posted",
"bugs": [
{
"comment_id": "2147483999",
"resolution_status": "resolved",
"severity": "high"
},
{
"comment_id": "2147484000",
"resolution_status": "unresolved",
"severity": "medium"
}
]
}
],
"pagination": {
"page": 1,
"pageSize": 100,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
},
"params": {
"metric": "bugbot-reviews",
"teamId": 12345,
"startDate": "2026-06-01",
"endDate": "2026-06-29",
"repo": "github.com/your-org/your-repo",
"prNumber": 42,
"page": 1,
"pageSize": 100
}
}
Example dry-run finding fields (when dry_run is true):
{
"comment_id": null,
"resolution_status": null,
"severity": "medium",
"title": "Unbounded retry loop",
"description": "retry() recurses without a ceiling.",
"locations": [
{ "file": "src/net.ts", "start_line": 5, "end_line": 9 }
]
}
repo_node_id, pr_number, commit_sha, cost_cents, bugs[].comment_id, bugs[].resolution_status, and bugs[].severity may be null when unavailable. cost_cents is null when the review is not billed separately. Dry-run findings keep comment_id: null and resolution_status: null because nothing is posted to the SCM.
To trigger a dry-run review, call POST /bugbot/review with "dryRun": true (see Bugbot API docs).
Response fields
| Field | Type | Meaning |
|---|---|---|
request_id |
string | Review request id |
timestamp |
string | Review time (ISO) |
repo / repo_node_id |
string | Repo path and SCM node id (may be null) |
pr_number |
number | null | PR / MR number |
commit_sha |
string | null | Reviewed commit |
bugs_found |
number | Findings count |
cost_cents |
number | null | Billed cost in cents when separately billed |
dry_run |
boolean | Whether the review was dry-run |
publication_status |
string | e.g. posted or dry_run |
bugs[] |
array | Per-finding rows |
bugs[].comment_id |
string | null | Posted comment id |
bugs[].resolution_status |
string | null | e.g. resolved / unresolved |
bugs[].severity |
string | null | Finding severity |
bugs[].title / description / locations |
mixed | Present on dry-run findings |
pagination.* |
object | Page metadata |
params.metric |
string | Echoes bugbot-reviews |
Caching
Store the response ETag and send it back as If-None-Match on the next poll. Unchanged data returns 304 Not Modified with no body; 304s do not count against the rate limit. Analytics endpoints use Cache-Control: public, max-age=900 (15 minutes). See API Overview → Caching.
Pitfalls
- Calling with an
admin:*key only — docs requireread:*for this route. - Treating
cost_cents: nullas zero spend — null means the review was not billed separately. - Expecting dry-run rows to carry
comment_id/resolution_status— those stay null; usetitle/description/locations. - Requesting more than 30 days — the Analytics date range caps at 30 days.
- Polling without
If-None-Match— burns the 100/min team budget on identical payloads.
Sibling how-tos in this batch: Get the team leaderboard, Get Bugbot PR analytics, Get by-user metrics.