Stack Auth provides built-in multi-tenancy through Teams, allowing users to be members of multiple organizations with different roles and permissions in each. This guide explains the team system and how to use it.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/stack-auth/stack-auth/llms.txt
Use this file to discover all available pages before exploring further.
Team Concepts
What is a Team?
A Team represents a group of users working together within your application. Teams enable:- Multi-tenancy (users belong to multiple organizations)
- Team-specific data isolation
- Role-based access within teams
- Collaborative features
- Each team has a unique ID across the project
- Teams are associated with a specific branch (usually “main”)
- Teams can have custom metadata (client, server, read-only)
- Users can be members of multiple teams simultaneously
Team Membership
TeamMember represents a user’s membership in a specific team:- Links a
ProjectUserto aTeam - Can override user’s display name and profile image for that team
- Stores team-specific permissions
- Tracks whether this team is the user’s selected team
Selected Team
Users can have one selected team at a time:- Used as the default team for operations
- Included in JWT access token (
selected_team_id) - Unique constraint ensures only one selected team per user
- Can be updated via API
/apps/backend/prisma/schema.prisma:143.
Team Operations
Creating a Team
Create a new team with the current user as the creator:Team creation
A
Team record is created with:- Unique team ID
- Display name
- Profile image (uploaded to S3 if base64)
- Metadata fields
- Mirrored project/branch IDs for uniqueness constraints
Creator added as member
If
creator_user_id is provided, a TeamMember record is created linking the user to the team with type: 'creator'.Default permissions granted
Team creator receives default permissions from config:Typically includes:
$update_team$delete_team$invite_members$remove_members$manage_api_keys
/apps/backend/src/app/api/latest/teams/crud.tsx:38.
With client authentication, users can only create teams if
allowClientTeamCreation is enabled in the project configuration. With server/admin authentication, teams can always be created.Reading a Team
Fetch team details by ID:- Client auth: User must be a member of the team
- Server/admin auth: Any team can be accessed
/apps/backend/src/app/api/latest/teams/crud.tsx:110.
Updating a Team
Modify team information:- Client auth: User must have
$update_teampermission (recursively checked) - Server/admin auth: No permission check required
/apps/backend/src/app/api/latest/teams/crud.tsx:136.
Deleting a Team
Remove a team and all associated data:- Client auth: User must have
$delete_teampermission - Server/admin auth: No permission check required
- All
TeamMemberrecords are deleted - All
TeamMemberDirectPermissionrecords are deleted - All
ProjectApiKeyrecords for the team are deleted - Team-specific data is removed
/apps/backend/src/app/api/latest/teams/crud.tsx:182.
Listing Teams
Retrieve teams (optionally filtered by user membership):- Client auth: Must filter by current user (
user_id=me) - Server/admin auth: Can list all teams or filter by any user
/apps/backend/src/app/api/latest/teams/crud.tsx:214.
Team Memberships
Adding Users to Teams
Add a user to a team (invitation flow):TeamMember record and grants default member permissions.
Implementation:
type parameter determines which default permissions are granted:
"creator"- Gets team creator permissions"member"- Gets team member permissions
/apps/backend/src/app/api/latest/teams/crud.tsx:90.
Team Member Profiles
Each team membership can have customized profile information:displayName- Overrides user’s global display name within this teamprofileImageUrl- Overrides user’s global profile image within this team
/apps/backend/prisma/schema.prisma:143.
Selected Team
Users can mark one team as their “selected” team:- Sets
isSelected = TRUEon the specifiedTeamMember - Unsets
isSelectedon all other memberships for this user - Updates the user’s access token to include
selected_team_id
BooleanTrue enum (only values: TRUE) ensures only one selected team per user.
See model at /apps/backend/prisma/schema.prisma:157.
Team Permissions
System Team Permissions
Stack Auth includes built-in team permissions:- Cannot be modified or deleted
- Are available in all projects
- Are granted via default permission configuration
/apps/backend/src/lib/permissions.tsx:13.
Custom Team Permissions
Define custom team-scoped permissions in your project config:- Must have
scope: "team" - Can contain other team permissions
- Are granted per team membership
- Cannot contain project-scoped permissions
Granting Team Permissions
Grant a permission to a user within a specific team:TeamMemberDirectPermission record.
Requirements:
- User must be a member of the team
- Permission must exist and have
scope: "team" - System permissions (prefixed with
$) are always available
Checking Team Permissions
Verify a user has a specific team permission:recursive: true, the check includes:
- Direct permission grants
- Permissions contained by granted permissions
- Full permission hierarchy
/apps/backend/src/app/api/latest/teams/crud.tsx:144.
Team Invitations
Invite users to join teams via email:Creating an Invitation
- Creates a
VerificationCodewith typeTEAM_INVITATION - Sends an email with the invitation code
- Returns the code (for testing) or just success
- Client auth: User must have
$invite_memberspermission - Server/admin auth: No permission check
Accepting an Invitation
- Validates the verification code
- Creates user account if needed
- Adds user to the team as a member
- Grants default team member permissions
- Marks the code as used
Team API Keys
Teams can have their own API keys for programmatic access:Creating Team API Keys
ProjectApiKey record associated with the team.
Authorization:
- Client auth: User must have
$manage_api_keyspermission - Server/admin auth: No permission check
Using Team API Keys
Team API keys authenticate requests on behalf of the team:- Access to team resources
- Team-scoped operations
- No individual user context
Data Model
Team Table
TeamMember Table
TeamMemberDirectPermission Table
/apps/backend/prisma/schema.prisma:111.
Multi-Tenancy Patterns
Team Isolation
Data can be isolated per team using tenancy patterns:Selected Team Context
Use the selected team from the access token:Cross-Team Operations
When users need to access multiple teams:Best Practices
Team Creation
- Always add the creator as the first team member
- Grant appropriate creator permissions
- Consider team limits per user/project
- Validate team names for uniqueness if needed
Permission Management
- Use system permissions (
$) for common operations - Create custom permissions for domain-specific actions
- Leverage permission hierarchies for role-like behavior
- Document permission requirements in API documentation
Team Switching
- Update selected team when user explicitly switches
- Include selected team in access token for easy access
- Invalidate cached data when switching teams
- Consider using team-scoped URL patterns (e.g.,
/teams/{teamId}/...)
Invitation Flows
- Send verification codes via email
- Include team information in invitation emails
- Handle expired invitation codes gracefully
- Allow re-sending invitations
- Track invitation status and history
Data Isolation
- Always filter by
teamIdfor team-scoped data - Verify team membership before data access
- Use database indexes on
teamIdcolumns - Consider row-level security in database
- Test cross-team access carefully