Teams Management Guide

Overview

Teams simplify permission management at scale by enabling bulk role assignment to groups of members. Instead of assigning permissions individually, you can create a team, assign custom roles to it, and add members to grant them all the team’s permissions at once. Members can belong to multiple teams and have personal roles simultaneously—their effective permissions are the union of all personal and team roles.

What is a Team?

A team is a logical grouping of organization members that:
  • Has a name and optional description — Identifies the team’s purpose
  • Contains multiple members — Members are added/removed dynamically
  • Has assigned roles — All members inherit these roles’ permissions
  • Is scoped to an organization — Teams exist within a single org
Example:
Team: Engineering
├── Members: Alice, Bob, Carol
├── Roles: Senior Engineer, Code Reviewer
└── Effective Permissions: code:review, code:merge, code:read

Permission Union Model

Each member’s effective permissions are the union of:
  1. Personal Roles — Custom roles assigned directly to the member
  2. Team Roles — Roles assigned to any team the member belongs to
  3. Built-in Role — owner/admin (if applicable)
Example:
Member: Alice
├── Personal Roles: [Content Editor]
│   └── Permissions: [content:read, content:write]
├── Team Memberships:
│   ├── Marketing Team (roles: [Content Approver])
│   │   └── Permissions: [content:approve]
│   └── Product Team (roles: [Product Owner])
│       └── Permissions: [product:read, product:plan]
└── Effective Permissions: 
    [content:read, content:write, content:approve, product:read, product:plan]
When Alice’s permissions are checked, the system:
  1. Queries her personal roles (Content Editor)
  2. Queries all teams she belongs to (Marketing, Product)
  3. Queries all roles assigned to those teams
  4. Merges permissions into a union
  5. Caches the result for 5 minutes

API Overview

Team CRUD Operations

EndpointMethodPurpose
/organizations/:orgId/teamsPOSTCreate a new team
/organizations/:orgId/teamsGETList all teams
/organizations/:orgId/teams/:teamIdGETGet team details (includes members)
/organizations/:orgId/teams/:teamIdPATCHUpdate team name/description
/organizations/:orgId/teams/:teamIdDELETEDelete team

Team Role Management

EndpointMethodPurpose
/organizations/:orgId/teams/:teamId/rolesPOSTAssign role to team
/organizations/:orgId/teams/:teamId/roles/:roleIdDELETERemove role from team

Team Member Management

EndpointMethodPurpose
/organizations/:orgId/teams/:teamId/membersPOSTAdd member to team
/organizations/:orgId/teams/:teamId/members/:memberIdDELETERemove member from team

Typical Team Workflow

Step 1: Create Team

curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering",
    "description": "Backend and frontend engineers"
  }'
Response:
{
  "id": "team_eng123",
  "orgId": "org_xyz",
  "name": "Engineering",
  "description": "Backend and frontend engineers",
  "createdAt": "2026-04-25T10:00:00Z"
}

Step 2: Assign Custom Roles to Team

Get available custom roles first (if needed), then assign to the team:
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/roles" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"roleId": "role_senior_eng"}'
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/roles" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"roleId": "role_code_reviewer"}'

Step 3: Add Members to Team

Add existing organization members to the team. They immediately gain all team roles’ permissions:
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/members" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"memberId": "member_alice"}'
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/members" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"memberId": "member_bob"}'

Step 4: Verify Team Details

Retrieve the team to see all members and roles:
curl "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123" \
  -H "Authorization: Bearer <token>"
Response:
{
  "id": "team_eng123",
  "orgId": "org_xyz",
  "name": "Engineering",
  "description": "Backend and frontend engineers",
  "roles": [
    {
      "id": "role_senior_eng",
      "name": "Senior Engineer",
      "permissions": ["code:review", "code:merge", "code:read"]
    },
    {
      "id": "role_code_reviewer",
      "name": "Code Reviewer",
      "permissions": ["code:review", "code:read"]
    }
  ],
  "members": [
    {
      "id": "member_alice",
      "userId": "user_alice",
      "email": "alice@example.com",
      "joinedAt": "2026-04-25T10:15:00Z"
    },
    {
      "id": "member_bob",
      "userId": "user_bob",
      "email": "bob@example.com",
      "joinedAt": "2026-04-25T10:20:00Z"
    }
  ],
  "createdAt": "2026-04-25T10:00:00Z",
  "updatedAt": "2026-04-25T10:00:00Z"
}

Common Patterns

Bulk Permission Grant

Grant multiple permissions to many people at once by assigning roles to a team: Before (manual):
# Assign role to each person individually (N requests)
POST /members/member_1 { roleId: role_xyz }
POST /members/member_2 { roleId: role_xyz }
POST /members/member_3 { roleId: role_xyz }
... repeat 100 times
After (with teams):
# Create team and assign role once (1 request)
POST /teams { name: "Team A" }
POST /teams/team_123/roles { roleId: role_xyz }

# Add members (N requests, but clear intent)
POST /teams/team_123/members { memberId: member_1 }
POST /teams/team_123/members { memberId: member_2 }
... repeat 100 times

Multi-Team Membership

Members can belong to multiple teams and accumulate permissions from all of them:
Marketing Member: carol@example.com
├── Team: Marketing (roles: [Content Writer, Social Manager])
├── Team: Compliance (roles: [Reviewer])
└── Effective permissions: content:write, social:post, content:review

Graceful Migration from Personal Roles

Start with personal role assignment, then gradually migrate to teams:
  1. Phase 1: Keep existing personal role assignments
  2. Phase 2: Create teams and assign roles
  3. Phase 3: Move members from personal roles to teams
  4. Phase 4: Remove personal roles once everyone is on teams
Both systems work together—there’s no migration debt.

Member Management

List All Teams

Get a paginated list of teams in the organization:
curl "https://api.example.com/api/v1/organizations/org_xyz/teams?page=1&pageSize=20" \
  -H "Authorization: Bearer <token>"
Response:
{
  "teams": [
    {
      "id": "team_eng123",
      "name": "Engineering",
      "description": "Backend and frontend engineers",
      "memberCount": 8,
      "createdAt": "2026-04-25T10:00:00Z"
    },
    {
      "id": "team_mkt456",
      "name": "Marketing",
      "description": "Marketing and communications",
      "memberCount": 5,
      "createdAt": "2026-04-25T11:00:00Z"
    }
  ],
  "total": 2,
  "page": 1,
  "pageSize": 20
}

Add Member to Multiple Teams

A member can be in multiple teams. Their permissions are the union of all team roles plus any personal roles:
# Add alice to Engineering team
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/members" \
  -H "Authorization: Bearer <token>" \
  -d '{"memberId": "member_alice"}'

# Add alice to Compliance team
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_cmp789/members" \
  -H "Authorization: Bearer <token>" \
  -d '{"memberId": "member_alice"}'

# alice now has: Engineering roles ∪ Compliance roles ∪ (any personal roles)

Remove Member from Team

curl -X DELETE "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/members/member_alice" \
  -H "Authorization: Bearer <token>"
Member is removed from the team but remains in the organization. Their permissions are updated to exclude this team’s roles.

Update Team Metadata

Change team name or description:
curl -X PATCH "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Engineering (Backend + Frontend)",
    "description": "All engineering disciplines"
  }'

Role Management for Teams

Assign Multiple Roles to a Team

Teams can have multiple roles. Members inherit all roles’ permissions:
# Assign role 1
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/roles" \
  -d '{"roleId": "role_senior_engineer"}'

# Assign role 2
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/roles" \
  -d '{"roleId": "role_code_reviewer"}'

# Assign role 3
curl -X POST "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/roles" \
  -d '{"roleId": "role_architecture_owner"}'

# Members in team_eng123 now have: senior_engineer ∪ code_reviewer ∪ architecture_owner permissions

Remove Role from Team

curl -X DELETE "https://api.example.com/api/v1/organizations/org_xyz/teams/team_eng123/roles/role_code_reviewer" \
  -H "Authorization: Bearer <token>"
All members lose this role’s permissions (unless they have it through another team or personal assignment).

Debugging

View Member’s Effective Permissions

To debug why a member has (or doesn’t have) certain permissions:
curl "https://api.example.com/api/v1/organizations/org_xyz/members/member_alice/permissions" \
  -H "Authorization: Bearer <token>"
Response shows:
{
  "personalRoles": ["role_editor"],
  "personalPermissions": ["content:read", "content:write"],
  "teamMemberships": [
    {
      "teamId": "team_eng123",
      "teamName": "Engineering",
      "roles": ["role_reviewer"],
      "permissions": ["code:review"]
    },
    {
      "teamId": "team_mkt456",
      "teamName": "Marketing",
      "roles": ["role_approver"],
      "permissions": ["content:approve"]
    }
  ],
  "effectivePermissions": ["content:read", "content:write", "code:review", "content:approve"],
  "updatedAt": "2026-04-25T15:30:00Z"
}

Best Practices

1. Organize Teams by Function

Create teams around organizational functions or teams:
  • Engineering — All engineers
  • Marketing — Marketing and content
  • Sales — Sales team
  • Finance — Finance and accounting

2. Use Descriptive Names

Make team purposes clear:
  • ✅ “Engineering (Backend)” — Clear and specific
  • ✅ “Content Approvers” — Descriptive of function
  • ❌ “Team A” — Vague
  • ❌ “Users” — Too generic

3. Assign Roles to Teams, Not Individual Members

For consistency and maintainability:
  • ✅ Add member to team that already has roles assigned
  • ❌ Assign 10 different roles to individual members

4. Document Team Purposes

Use the description field to explain why the team exists:
{
  "name": "Content Approvers",
  "description": "Team members who can approve content for publication. Includes editors, managers, and leads."
}

5. Periodically Audit Team Membership

Teams can accumulate stale members. Regularly review:
  • Who’s still in the team?
  • Are those still the right people?
  • Should any roles be added/removed?

6. Use Audit Logs for Troubleshooting

When permissions change unexpectedly, check audit logs:
curl "https://api.example.com/api/v1/organizations/org_xyz/audit?resource_type=team&resource_id=team_eng123" \
  -H "Authorization: Bearer <token>"
See what roles were added/removed and when.

Access Control

Only organization owners and admins can:
  • Create/update/delete teams
  • Assign/remove roles from teams
  • Add/remove members from teams
Regular members can:
  • View team membership (their own teams)
  • View team details (public metadata)