
Plans
Sync organization team memberships with the Organization API
Set which linked teams one or more users belong to with POST https://api.cursor.com/organizations/team-memberships/sync. You send a batch of users; each row returns its own success or error. Official reference: Organization API → Sync Organization Team Memberships.
Authenticate with an Organization API key (Basic auth, key as username, empty password). This write route needs members:* (or admin:*). Enterprise only. Resolve numeric userId values and linked teamIds first with List organization members.
Request body
| Field | Rules |
|---|---|
organizationId |
Required. Public org id (for example org_abc123). Must match the key’s organization |
users |
Required. Non-empty array, at most 500 entries per request |
Each entry needs a userId plus exactly one of:
| Field | Behavior |
|---|---|
teamIds |
Complete set of linked team ids the user should belong to after the call. Adds missing teams and removes any linked team not listed. At most 100 teams per entry |
destinationTeamId |
Places the user on a single team and removes every other linked team. Same effect as teamIds: [NNN] |
userId accepts an integer (12345) or a string id ("user_abc123").
Move to one team
curl -X POST https://api.cursor.com/organizations/team-memberships/sync \
-u YOUR_ORGANIZATION_API_KEY: \
-H "Content-Type: application/json" \
-d '{
"organizationId": "org_abc123",
"users": [
{ "userId": 12345, "destinationTeamId": 8 }
]
}'
Keep current teams while adding another
List every team that should remain, including the current ones:
curl -X POST https://api.cursor.com/organizations/team-memberships/sync \
-u YOUR_ORGANIZATION_API_KEY: \
-H "Content-Type: application/json" \
-d '{
"organizationId": "org_abc123",
"users": [
{ "userId": 12345, "teamIds": [7, 8] },
{ "userId": "user_abc123", "destinationTeamId": 8 }
]
}'
Success response (HTTP 200)
{
"results": [
{
"userId": 12345,
"teamIds": [7, 8],
"status": "success"
},
{
"userId": "user_abc123",
"teamIds": [8],
"destinationTeamId": 8,
"status": "success"
}
],
"successCount": 2,
"errorCount": 0
}
One failed row does not roll back the others. Read every results[].status and errorMessage. Split work above 500 users into separate requests.
Common errors
| Status / shape | When |
|---|---|
401 Invalid Organization API Key |
Wrong or missing key |
401 missing members:* |
Key valid but lacks members write (or admin:*) |
403 Not authorized |
Body organizationId does not match the key’s organization |
| 404 | Organization not found ({"error":"Organization not found"}) |
| 400 | Missing body, empty users, more than 500 entries, or other invalid body |
Per-row status: "error" (still HTTP 200) |
Invalid ids, user not in the org, team not linked, or user not found |
Per-row examples include Invalid userId, Invalid destinationTeamId, Team is not linked to this organization, User is not a member of this organization, and User not found.
Pitfalls
teamIdsis a full replace. Omitting a current team removes the user from it.- Every team in the entry must already be linked to the organization.
- The target user must already be an organization member before sync succeeds.
- Team Admin CSV-style moves and this endpoint share the same bulk idea; keep using the Organization key and
/organizations/…path here.