HyperSaaS
BackendWorkspaces & Teams

Overview

Multi-tenancy with workspaces, teams, and role-based access.

HyperSaaS uses workspace-based multi-tenancy. Every resource (chats, documents, knowledge bases) belongs to a workspace. Users access workspaces through memberships.

Core Models

Workspace

class Workspace(BaseModel):
    id = models.UUIDField(primary_key=True)
    name = models.CharField(max_length=200, default="Default Workspace")
    slug = models.SlugField(max_length=255, unique=True)  # Auto-generated
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    members = models.ManyToManyField(User, through="WorkspaceMembership")
    status = models.CharField(choices=[ACTIVE, ARCHIVED])
    subscription = models.ForeignKey(Subscription, null=True, blank=True)

A workspace's plan comes from its subscription while that grants access, and is Free otherwise. Credit, documents and storage are counted per workspace.

WorkspaceMembership

class WorkspaceMembership(BaseModel):
    workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    role = models.CharField(choices=ROLE_CHOICES, default="member")
    # unique_together = ("workspace", "user")

Team

Teams are sub-groups within a workspace for fine-grained access control:

class Team(BaseModel):
    workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    slug = models.SlugField(max_length=150)
    owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
    members = models.ManyToManyField(User, through="TeamMembership")

Folder

Folders organize resources within a workspace:

class Folder(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
    name = models.CharField(max_length=255)
    type = models.CharField(max_length=50, null=True)  # 'chat', 'file', 'prompt', 'agent'

Roles

RoleCapabilities
OwnerEverything an admin can do, plus delete the workspace and transfer ownership
adminInvite and remove people, change roles, manage teams, change settings, archive the workspace, buy a plan
memberUse chats and documents; manage what they created

The owner is a field on the workspace, not a role: the owner also has an admin membership. See Permissions for the full table.

Joining and Leaving

  • People join only by accepting an invitation. There's no endpoint that adds someone directly. See Invitations.
  • Members can leave (POST /api/workspaces/{id}/leave/). The owner can't, until they transfer ownership.
  • Removing someone, or their leaving, also removes their team memberships in that workspace, clears them as owner of its teams, and deletes pending invitations to them.
  • Transferring ownership (POST /api/workspaces/{id}/transfer-ownership/) makes another member the owner. Both stay on as admins. A subscription stays with whoever pays for it.
  • Deleting a workspace is refused while it has an active subscription, or if it's the owner's only workspace.

Data Isolation

Every workspace-scoped API endpoint:

  1. Extracts workspace_pk from the URL
  2. Verifies the user is a member of that workspace
  3. Filters all queries to that workspace
# Example: Chat sessions are always scoped to a workspace
GET /api/workspaces/{workspace_id}/chats/

On this page