PLANS / manage-billing-groups-via-admin-api

Plans

Manage billing groups with the Admin API

Enterprise admins can create billing groups, move members between them, and pull group spend for chargebacks with the /teams/groups routes. Official reference: Admin API → Billing Groups. Members can sit in only one billing group at a time; everyone else lands in the reserved Unassigned group.

Authenticate with a team Admin API key (Basic auth, key as username, empty password). Mutating group routes are rate limited to 20 requests per minute per team.

List groups and cycle spend

curl -X GET "https://api.cursor.com/teams/groups?billingCycle=2025-01-15" \
  -u YOUR_API_KEY:

billingCycle is an optional ISO date (defaults to the current cycle). The response includes groups, a reserved unassignedGroup, and the cycle window. Each group carries spendCents, currentMembers, formerMembers, and dailySpend.

Create a group

curl -X POST https://api.cursor.com/teams/groups \
  -u YOUR_API_KEY: \
  -H "Content-Type: application/json" \
  -d '{ "name": "Engineering" }'

type defaults to BILLING (currently the only supported type).

Rename or attach directory sync

Only one field may change per request. To rename and re-attach directory sync, send two PATCHes.

curl -X PATCH https://api.cursor.com/teams/groups/group_PDSPmvukpYgZEDXsoNirw3CFhy \
  -u YOUR_API_KEY: \
  -H "Content-Type: application/json" \
  -d '{ "name": "Platform Engineering" }'

Detach directory sync with "directoryGroupId": null.

Add and remove members

Users must already be team members and must not already belong to another group. SCIM-synced groups cannot be edited here — change membership through SCIM.

curl -X POST https://api.cursor.com/teams/groups/group_PDSPmvukpYgZEDXsoNirw3CFhy/members \
  -u YOUR_API_KEY: \
  -H "Content-Type: application/json" \
  -d '{ "userIds": ["user_abc123", "user_def456"] }'
curl -X DELETE https://api.cursor.com/teams/groups/group_PDSPmvukpYgZEDXsoNirw3CFhy/members \
  -u YOUR_API_KEY: \
  -H "Content-Type: application/json" \
  -d '{ "userIds": ["user_def456"] }'

Removed members move to Unassigned. Encoded user IDs match /teams/members (user_…).

Get one group or delete it

curl -X GET "https://api.cursor.com/teams/groups/group_PDSPmvukpYgZEDXsoNirw3CFhy?billingCycle=2025-01-15" \
  -u YOUR_API_KEY:
curl -X DELETE https://api.cursor.com/teams/groups/group_PDSPmvukpYgZEDXsoNirw3CFhy \
  -u YOUR_API_KEY:

Delete returns 204. It is destructive: historical usage for that group is reassigned retroactively to Unassigned.

Pitfalls

  • Passing display names instead of encoded group_… / user_… IDs.
  • Trying to PATCH name and directoryGroupId in one body — one field per request.
  • Editing members on a SCIM-synced group via the API — membership must go through SCIM.
  • Deleting a group without planning for Unassigned reassignment of historical spend.