Skip to main content

Teams

A team is a named group of subjects (team_<hex>) that can hold role grants of its own. Instead of assigning builder to forty engineers one by one, you grant it once to the platform team — members inherit the team's roles for as long as they're on the team, and authorization decisions record that the access came via the team.

Teams are account-owned: they live on the account (parent organization) and can be granted roles at account, workspace, or project scope. Team management therefore requires authority on the account — a workspace-only admin cannot create or edit teams.

Manage teams

MethodPathPermissionDescription
POST/v1/organizations/{orgId}/teamsteam.createCreate a team (name, optional slug)
GET/v1/organizations/{orgId}/teamsorganization.member.listList the account's teams
GET/v1/organizations/{orgId}/teams/{teamId}organization.member.listGet one team
PATCH/v1/organizations/{orgId}/teams/{teamId}team.updateRename / re-slug
DELETE/v1/organizations/{orgId}/teams/{teamId}team.deleteDelete the team
curl -X POST https://api.orunbase.com/v1/organizations/ws_a1b2c3d4/teams \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Platform", "slug": "platform"}'
{
"data": {
"team": {
"id": "team_3c2b1a09f8e7d6c5b4a3928170654e3d",
"name": "Platform",
"slug": "platform",
"status": "active",
"createdAt": "2026-07-02T12:00:00.000Z"
}
},
"meta": { "requestId": "req_4c5d6e7f8a9b", "cursor": null }
}
const { team } = await client.teams.createTeam(orgId, { name: "Platform" });
const { teams } = await client.teams.listTeams(orgId);
await client.teams.updateTeam(orgId, team.id, { name: "Platform Eng" });
await client.teams.deleteTeam(orgId, team.id);

Any workspace reference under the account works in the path — teams resolve to the account root.

Manage team membership

MethodPathPermissionDescription
GET/v1/organizations/{orgId}/teams/{teamId}/membersorganization.member.listList team members
POST/v1/organizations/{orgId}/teams/{teamId}/membersteam.member.addAdd a subject (subjectId, optional subjectType, default user)
DELETE/v1/organizations/{orgId}/teams/{teamId}/members/{subjectId}team.member.removeRemove a subject
await client.teams.addTeamMember(orgId, teamId, { subjectId: "usr_7a6b5c4d…" });
const { members } = await client.teams.listTeamMembers(orgId, teamId);
await client.teams.removeTeamMember(orgId, teamId, "usr_7a6b5c4d…");

Service principals can be team members too (subjectType: "service_principal"), so a team grant can cover automation alongside its human owners.

Grant roles to a team

Team role grants are the point of the feature: the team becomes the subject of a role assignment, at any of the three scopes.

MethodPathPermissionDescription
POST/v1/organizations/{orgId}/team-rolesteam.role.grantGrant {teamId, role, scopeKind, scopeRef?}
DELETE/v1/organizations/{orgId}/team-rolesteam.role.grantRevoke the same tuple

scopeKind is account, organization (a workspace), or projectscopeRef names the project when scopeKind is project.

curl -X POST https://api.orunbase.com/v1/organizations/ws_a1b2c3d4/team-roles \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"teamId": "team_3c2b1a09f8e7d6c5b4a3928170654e3d", "role": "builder", "scopeKind": "organization"}'
{
"data": {
"grant": { "teamId": "team_3c2b1a09f8e7d6c5b4a3928170654e3d", "role": "builder", "scopeKind": "organization", "scopeRef": null }
},
"meta": { "requestId": "req_5d6e7f8a9b0c", "cursor": null }
}
await client.teams.grantTeamRole(orgId, { teamId, role: "builder", scopeKind: "organization" });
await client.teams.revokeTeamRole(orgId, { teamId, role: "builder", scopeKind: "organization" });
tip

Manage access at team granularity end to end: onboarding is team member-add, offboarding is team member-remove — no per-workspace role edits. Direct member roles still work and union with team grants; the effective permission set is the union of everything the subject holds.

Provenance: decisions show the team path

Authorization facts assembled for a team member carry their origin, and allowed decisions report it as via{ "kind": "team", "teamId": "team_…" } — alongside direct and account_cascade. The effective-access endpoint renders this per action, so "why does Sam have project.create here?" is answerable without spelunking role tables. Provenance is reporting only; it never changes the decision.

Team lifecycle changes (team.created, team.member.added, team.role grants, …) are recorded in the workspace audit log.

Teams from the CLI

The orun-cloud CLI mirrors the whole surface:

orun-cloud team list
orun-cloud team create "Platform" --slug=platform
orun-cloud team get team_3c2b1a09…
orun-cloud team update team_3c2b1a09… --name="Platform Eng"
orun-cloud team members team_3c2b1a09…
orun-cloud team member-add team_3c2b1a09… usr_7a6b5c4d…
orun-cloud team member-remove team_3c2b1a09… usr_7a6b5c4d…
orun-cloud team grant team_3c2b1a09… --role=builder --scope=organization
orun-cloud team revoke team_3c2b1a09… --role=builder --scope=organization
orun-cloud team access # your own effective access, with via provenance
orun-cloud team delete team_3c2b1a09…

All commands accept --org=ORG_ID to override the active workspace and --output=json for scripting.