
Get AI commit metrics with the AI Code Tracking API
Retrieve paginated per-commit metrics that attribute lines to TAB, COMPOSER, and non-AI with GET https://api.cursor.com/analytics/ai-code/commits. Official reference: AI Code Tracking API → Get AI Commit Metrics.
Authenticate with a team API key (Basic auth, key as username, empty password — same method as the Admin API). Create keys at cursor.com/dashboard → API Keys with scope admin:*. Availability: Enterprise only (contact sales for access). Status: Alpha — response shapes and fields may change. Rate limit: 20 requests per minute per endpoint. Metrics cover the git repository at the top level of the workspace root; multi-root workspaces are unsupported.
Query parameters
| Parameter | Rules |
|---|---|
startDate |
ISO date, now, or relative days such as 7d (means now − 7 days). Default: now − 7 days |
endDate |
ISO date, now, or relative days such as 0d. Default: now |
page |
1-based page number. Default: 1 |
pageSize |
Results per page. Default: 100, max: 1000 |
user |
Optional single-user filter: email, encoded id (user_…), or numeric id |
Request
curl -X GET "https://api.cursor.com/analytics/ai-code/commits?startDate=7d&endDate=now&page=1&pageSize=100" \
-u YOUR_API_KEY:
Example response:
{
"items": [
{
"commitHash": "a1b2c3d4",
"userId": "user_3k9x8q...",
"userEmail": "developer@company.com",
"repoName": "company/repo",
"branchName": "main",
"isPrimaryBranch": true,
"commitSource": "ide",
"totalLinesAdded": 120,
"totalLinesDeleted": 30,
"tabLinesAdded": 50,
"tabLinesDeleted": 10,
"composerLinesAdded": 40,
"composerLinesDeleted": 5,
"nonAiLinesAdded": 30,
"nonAiLinesDeleted": 15,
"message": "Refactor: extract analytics client",
"commitTs": "2025-07-30T14:12:03.000Z",
"createdAt": "2025-07-30T14:12:30.000Z"
}
],
"totalCount": 42,
"page": 1,
"pageSize": 100
}
Response fields
| Field | Type | Meaning |
|---|---|---|
commitHash |
string | Git commit hash |
userId |
string | Encoded user id (user_…); stable for API use |
userEmail |
string | User email |
repoName |
string | null | Repository name |
branchName |
string | null | Branch name |
isPrimaryBranch |
boolean | null | True when the branch equals the repo default; may be undefined when repo info is unavailable |
commitSource |
"ide" | "cli" | "cloud" |
Where the commit originated |
totalLinesAdded / totalLinesDeleted |
number | Total lines in the commit |
tabLinesAdded / tabLinesDeleted |
number | Lines from accepted TAB (inline) completions |
composerLinesAdded / composerLinesDeleted |
number | Lines from accepted Composer / Agent diffs |
nonAiLinesAdded / nonAiLinesDeleted |
number | null | Derived as max(0, totalLines − AI lines) |
message |
string | null | Commit message |
commitTs |
string | null | Commit timestamp (ISO) |
createdAt |
string | Ingestion timestamp on Cursor servers (ISO) |
Pagination returns items, totalCount, page, and pageSize.
Semantics
- TAB = accepted inline completions; COMPOSER = accepted Agent / Composer diffs. Those counters are separate.
- Prefer CSV for bulk extracts: Download AI commit metrics CSV. For accepted changes independent of commits, see Get AI code change metrics.
- Endpoints support HTTP caching with
ETag/If-None-Match(15-minuteCache-Control);304responses do not count against the rate limit. See API Overview.
Pitfalls
- Calling from a multi-root workspace — metrics only cover the top-level git repo under the workspace root.
- Treating
commitHashas unique forever — amended commits can appear more than once;commitTsstays the same after amend. - Confusing
commitTs(git time) withcreatedAt(ingestion time). - Polling faster than a few minutes — near real-time ingestion, but the rate limit is 20/min per endpoint.
- Expecting GA field stability — Alpha shapes may change.
For blame ranges and conversation metadata on a known hash, see Get AI commit details. Join conversationId values from commit details with Get filtered usage events when you need usage-event cost rows for the same Agent session.