Cursor APIs Overview
Cursor provides multiple APIs for programmatic access to your team's data, AI-powered coding agents, and analytics.
Available APIs
| API | Description | Availability |
|---|---|---|
| Admin API | Manage team members, settings, usage data, spending, and model access. Build custom dashboards and monitoring tools. | Enterprise teams |
| Analytics API | Comprehensive insights into team's Cursor usage, AI metrics, active users, and model usage. | Enterprise teams |
| AI Code Tracking API | Track AI-generated code contributions at commit and change levels for attribution and analytics. | Enterprise teams |
| Bugbot API | Trigger Bugbot reviews and retrieve per-review analytics. | Enterprise teams |
| Cloud Agents API | Programmatically create and manage AI-powered coding agents for automated workflows and code generation. | Beta (All Plans) |
| Origin API | Work with Origin repositories, commits, checks, pull requests, and app installations. | Alpha |
| TypeScript SDK | Run Cursor agents from TypeScript with one interface for local and cloud runtimes. | All users |
| Python SDK | Run Cursor agents from Python with sync and async clients for local and cloud runtimes. | All users |
| SDK Bridge | Build agent SDKs in other languages on the open bridge protocol and standalone binaries. | All users |
The Cloud Agents API and SDKs run Cursor agent workflows (workspace context, tools, commands, and edits). They are not a standalone model-inference or chat-completions API. Cursor Router selects models for those agent runs when you use Auto / auto-smart; see Router in the TypeScript SDK or Python SDK.
Authentication
All Cursor APIs accept Basic Authentication. The Cloud Agents API additionally accepts Bearer tokens — pick whichever is easier for your HTTP client.
Basic Authentication
Use your API key as the username in basic authentication (leave password empty):
curl https://api.cursor.com/teams/members \ -u YOUR_API_KEY:Or set the Authorization header directly:
Authorization: Basic {base64_encode('YOUR_API_KEY:')}Bearer Authentication (Cloud Agents API)
The Cloud Agents API also accepts Authorization: Bearer <key> headers. Both schemes behave identically — use whichever your HTTP client makes easier:
curl https://api.cursor.com/v1/me \ -H "Authorization: Bearer YOUR_API_KEY"Creating API Keys
Team administrators can create and manage API keys from the API Keys page in the dashboard.
Admin API & AI Code Tracking API
- Navigate to cursor.com/dashboard → API Keys
- Click New API Key
- Give your key a descriptive name (e.g., "Usage Dashboard Integration")
- Copy the generated key immediately. You won't see it again
Key format: crsr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Required scope: admin:*
Analytics API
Generate an API key from Cursor Dashboard → API Keys.
Cloud Agents API
Create a user API key from Cursor Dashboard → API Keys, or use a service account API key from team settings.
API keys are tied to your organization and viewable by all admins. Keys are unaffected by the original creator's account status.
Rate Limits
All APIs implement rate limiting to ensure fair usage and system stability. Rate limits are enforced per team and reset every minute.
Rate Limits by API
| API | Endpoint Type | Rate Limit |
|---|---|---|
| Admin API | Most endpoints | 20 requests/minute |
| Admin API | /teams/filtered-usage-events and /organizations/filtered-usage-events | 60 requests/minute |
| Admin API | /teams/user-spend-limit | 250 requests/minute |
| Analytics API | Most team-level endpoints | 100 requests/minute |
| Analytics API | /analytics/team/conversation-insights | 20 requests/minute |
| Analytics API | By-user endpoints | 50 requests/minute |
| AI Code Tracking API | All endpoints | 20 requests/minute per endpoint |
| Bugbot API | /bugbot/review | 30 requests/minute |
| Bugbot API | /bugbot/review with dryRun: true | 10 requests/minute (in addition to the trigger limit) |
| Cloud Agents API | All endpoints | Standard rate limiting |
Rate Limit Response
When you exceed the rate limit, you'll receive a 429 Too Many Requests response:
{ "error": "Too Many Requests", "message": "Rate limit exceeded. Please try again later."}Caching
Several APIs support HTTP caching with ETags to reduce bandwidth usage and improve performance.
Supported APIs
- Analytics API: All endpoints (both team-level and by-user) support HTTP caching
- AI Code Tracking API: Endpoints support HTTP caching
How Caching Works
- Initial Request: Make a request to any supported endpoint
- Response Includes ETag: The API returns an
ETagheader in the response - Subsequent Requests: Include the
ETagvalue in anIf-None-Matchheader - 304 Not Modified: If data hasn't changed, you'll receive a
304 Not Modifiedresponse with no body
Example
# Initial requestcurl -X GET "https://api.cursor.com/analytics/team/dau" \ -H "Authorization: Bearer YOUR_API_KEY" \ -D headers.txt# Response includes: ETag: "abc123xyz"# Subsequent request with ETagcurl -X GET "https://api.cursor.com/analytics/team/dau" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "If-None-Match: \"abc123xyz\""# Returns 304 Not Modified if data hasn't changedCache Duration
- Cache duration: 15 minutes (
Cache-Control: public, max-age=900) - Responses include an
ETagheader - Include
If-None-Matchheader in subsequent requests to receive304 Not Modifiedwhen data hasn't changed
Benefits
- Reduces bandwidth usage: 304 responses contain no body
- Faster responses: Avoids processing unchanged data
- Rate limit friendly: 304 responses don't count against rate limits
- Better performance: Especially useful for frequently polled endpoints
Best Practices
1. Implement Exponential Backoff
When you receive a 429 response, wait before retrying with increasing delays:
import timeimport requestsdef make_request_with_backoff(url, headers, max_retries=5): for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code == 429: # Exponential backoff: 1s, 2s, 4s, 8s, 16s wait_time = 2 ** attempt print(f"Rate limited. Waiting {wait_time}s before retry...") time.sleep(wait_time) continue return response raise Exception("Max retries exceeded")2. Distribute Requests Over Time
Spread your API calls over time rather than making burst requests:
- Schedule batch jobs to run at different intervals
- Add delays between requests when processing large datasets
- Use queuing systems to smooth out traffic spikes
3. Leverage Caching
For Analytics API and AI Code Tracking API:
These APIs support HTTP caching with ETags. See the Caching section above for details on how to use ETags to reduce bandwidth usage and avoid unnecessary requests.
Key benefits:
- Reduces bandwidth usage
- Faster responses when data hasn't changed
- Doesn't count against rate limits (for 304 responses)
Use date shortcuts (7d, 30d) instead of timestamps for better caching support in Analytics API.
4. Monitor Your Usage
Track your request patterns to stay within limits:
- Log API call timestamps and response codes
- Set up alerts for 429 responses
- Monitor daily/weekly usage trends
- Adjust polling intervals based on actual needs
5. Batch Wisely
For endpoints with pagination:
- Use appropriate page sizes to get more data per request
- For Analytics API by-user endpoints: Use
usersparameter to filter specific users - For large data extractions: Use CSV endpoints when available (they stream data efficiently)
6. Poll at Appropriate Intervals
Don't over-poll endpoints that update infrequently:
- Admin API
/teams/daily-usage-data: Poll at most once per hour (data aggregated hourly) - Admin API
/teams/filtered-usage-events: Poll at most once per hour (data aggregated hourly) - Admin API
/organizations/pooled-usage: Poll at most once per hour (data aggregated hourly) - Admin API
/organizations/filtered-usage-events: Poll at most once per hour (data aggregated hourly) - Analytics API: Use date shortcuts (
7d,30d) for better caching support - AI Code Tracking API: Data is ingested in near real-time but polling every few minutes is sufficient
7. Handle Errors Gracefully
Implement proper error handling for all API calls:
async function fetchAnalytics(endpoint) { try { const response = await fetch(`https://api.cursor.com${endpoint}`, { headers: { 'Authorization': `Basic ${btoa(API_KEY + ':')}` } }); if (response.status === 429) { // Rate limited - implement backoff throw new Error('Rate limit exceeded'); } if (response.status === 401) { // Invalid API key throw new Error('Authentication failed'); } if (response.status === 403) { // Insufficient permissions throw new Error('Enterprise access required'); } if (!response.ok) { throw new Error(`API error: ${response.status}`); } return await response.json(); } catch (error) { console.error('API request failed:', error); throw error; }}Common Error Responses
All APIs use standard HTTP status codes:
400 Bad Request
Request parameters are invalid or missing required fields.
{ "error": "Bad Request", "message": "Some users are not in the team"}401 Unauthorized
Invalid or missing API key.
{ "error": "Unauthorized", "message": "Invalid API key"}403 Forbidden
Valid API key but insufficient permissions (e.g., Enterprise features on non-Enterprise plan).
{ "error": "Forbidden", "message": "Enterprise access required"}404 Not Found
Requested resource doesn't exist.
{ "error": "Not Found", "message": "Resource not found"}429 Too Many Requests
Rate limit exceeded. Implement exponential backoff.
{ "error": "Too Many Requests", "message": "Rate limit exceeded. Please try again later."}500 Internal Server Error
Server-side error. Contact support if persistent.
{ "error": "Internal Server Error", "message": "An unexpected error occurred"}