I’m looking to build an organization-level AI usage dashboard and need data on cost, usage, billing, users, token consumption, and other relevant metrics.
Could someone please advise which API endpoints I should use to retrieve this data? Thank you!
Everything you listed is available through our Admin API and Analytics API (both available on Enterprise). One thing to note first: the API key has to be created by a team admin in the dashboard under API Keys. The key is passed as the Basic auth username with an empty password, for example curl https://api.cursor.com/teams/members -u YOUR_API_KEY:
Cost, billing and tokens (Admin API):
POST /teams/filtered-usage-events: per-request events with user, model, tokenUsage (input, output, cache read/write tokens) and chargedCents. This is the most granular source, and summing chargedCents reconciles with dashboard spend.
POST /teams/spend: per-member spend for the current billing cycle (spendCents, overallSpendCents, spend limits).
POST /teams/daily-usage-data: per-user, per-day activity (requests by mode, lines added/accepted, Tab accepts, most used model). Max 30 days per call.
Users:
GET /teams/members: members, roles and status.
GET /analytics/team/dau: daily active users.
Usage and adoption (Analytics API):
/analytics/team/models, /agent-edits, /tabs, /client-versions, /mcp, /leaderboard, and more, plus per-user versions under /analytics/by-user/....
A few tips for a dashboard:
Usage data is aggregated hourly, so polling once an hour is plenty.
Rate limits are 20 requests/min for most Admin API endpoints (60/min for filtered-usage-events), so page through with pageSize up to 1000 and store the events on your side.
Analytics endpoints support ETags, so cached responses don’t count against the limit.
Each event’s timestamp is when the request started. Events show up as soon as the work is processed (there’s no hourly batch), but a request that starts at 9:58 and runs for 10 minutes is filed under 9:58 and only fills in after 10:00. Its tokens and chargedCents keep growing until the request finishes.
Most requests finish within minutes, so most of an hour’s usage is visible shortly after the hour ends. Long agent runs are the exception and can keep adding to an earlier hour for a while.
So rather than fetching each hour once, I’d re-read a trailing window on every run and replace what you stored for those hours instead of appending:
At 10:15, request startDate = 07:00 and endDate = 10:00 (closed hours only, never the current hour).
Overwrite your stored data for 07:00 to 10:00 with the result.
Run anomaly detection on 9:00 to 10:00, knowing it can still grow slightly. If you want near-final numbers, score 8:00 to 9:00 instead.
For completeness checks: the response doesn’t include a unique event ID today, so replacing whole hours is more reliable than de-duplicating individual events. If a window needs more than one page, split it into smaller windows (for example 15 minutes) so each fits in a single pageSize: 1000 page, and check that the number of rows you got matches totalUsageEventsCount.