Organizations Guide — B2B Multi-Tenant Setup
Tenxyte supports hierarchical organizations with org-scoped RBAC, member management, and invitations.
Opt-in feature — disabled by default for backward compatibility.
Table of Contents
- Enable Organizations
- Configuration
- Concepts
- Organization
- OrganizationRole
- OrganizationMembership
- API Usage
- Create an Organization
- Create a Sub-Organization
- List My Organizations
- Get Organization Details
- Get Organization Tree
- Update an Organization
- Delete an Organization
- Member Management
- List Members
- Add a Member
- Update a Member's Role
- Remove a Member
- Invite a Member by Email
- Organization Roles
- Role Inheritance
- Python API
- Org-Scoped RBAC in Views
- Data Model
- Settings Reference
Enable Organizations
To enable the organizations feature, update your settings.py:
# settings.py
TENXYTE_ORGANIZATIONS_ENABLED = True
# Add the middleware to attach organization context to requests
MIDDLEWARE += [
'tenxyte.middleware.OrganizationContextMiddleware',
]
Then run migrations to prepare the database:
Configuration
TENXYTE_ORGANIZATIONS_ENABLED = True
TENXYTE_ORG_ROLE_INHERITANCE = True # Roles propagate down the hierarchy
TENXYTE_ORG_MAX_DEPTH = 5 # Max hierarchy depth
TENXYTE_ORG_MAX_MEMBERS = 0 # 0 = unlimited
Concepts
Organization
A named entity that groups users. Organizations can be nested (parent → children).
OrganizationRole
A role scoped to an organization (e.g. admin, member, viewer). Different from global RBAC roles.
OrganizationMembership
Links a user to an organization with a specific role.
API Usage
Create an Organization
POST /api/v1/auth/organizations/
Authorization: Bearer <token>
{
"name": "Acme Corp",
"slug": "acme-corp",
"description": "Our main organization"
}
Response 201:
{
"id": 1,
"name": "Acme Corp",
"slug": "acme-corp",
"parent": null,
"created_at": "2026-01-01T00:00:00Z"
}
Create a Sub-Organization
POST /api/v1/auth/organizations/
{
"name": "Engineering",
"slug": "acme-engineering",
"parent_id": 1
}
List My Organizations
Get Organization Details
Get Organization Tree
Response:
{
"id": 1,
"name": "Acme Corp",
"children": [
{
"id": 2,
"name": "Engineering",
"children": [
{ "id": 3, "name": "Backend Team", "children": [] },
{ "id": 4, "name": "Frontend Team", "children": [] }
]
}
]
}
Update an Organization
PATCH /api/v1/auth/organizations/update/
X-Org-Slug: acme-corp
{
"name": "Acme Corporation",
"description": "Updated description"
}
Delete an Organization
Member Management
List Members
Response:
[
{
"user_id": 42,
"email": "alice@acme.com",
"role": "admin",
"joined_at": "2026-01-01T00:00:00Z"
}
]
Add a Member
POST /api/v1/auth/organizations/members/add/
X-Org-Slug: acme-corp
{
"user_id": 42,
"role_code": "member"
}
Update a Member's Role
Remove a Member
Invite a Member by Email
POST /api/v1/auth/organizations/invitations/
X-Org-Slug: acme-corp
{
"email": "newmember@example.com",
"role_code": "member",
"expires_in_days": 7
}
An invitation email is sent. The user can accept by registering or logging in.
Organization Roles
List available org-scoped roles:
Create org roles programmatically:
from tenxyte.models import OrganizationRole
role = OrganizationRole.objects.create(
code="admin",
name="Admin",
description="Administrator with management permissions",
permissions=["org.members.invite", "org.members.manage"]
)
Role Inheritance
When TENXYTE_ORG_ROLE_INHERITANCE = True, roles assigned at a parent organization propagate to all child organizations.
Example:
- Alice is admin in Acme Corp
- She automatically has admin rights in Engineering, Backend Team, etc.
To check effective permissions in a specific org:
membership = OrganizationMembership.objects.get(user=alice, organization=backend_team)
# membership.role may be inherited from parent
Python API
from tenxyte.services import OrganizationService
service = OrganizationService()
# Create
success, org, error = service.create_organization(
name="Acme Corp",
slug="acme-corp",
created_by=user
)
# Add member
success, membership, error = service.add_member(
organization=org,
user_to_add=new_user,
role_code="member",
added_by=admin_user
)
# Get tree
tree = service.get_organization_tree(org)
# Check membership
is_member = service.is_member(user, org)
Org-Scoped RBAC in Views
Use @require_org_permission to protect views with org-scoped permissions:
from tenxyte.decorators import require_jwt, require_org_context, require_org_permission
class OrgSettingsView(APIView):
@require_jwt
@require_org_context
@require_org_permission('org.manage')
def post(self, request):
# request.organization is set by middleware
org = request.organization
...
The middleware resolves the organization from the X-Org-Slug request header.
Data Model
Organization
├── id
├── name
├── slug (unique)
├── description
├── parent (FK → self, nullable)
├── metadata (JSON)
├── is_active
├── max_members
├── created_at
├── updated_at
└── created_by (FK → User, nullable)
OrganizationRole
├── id
├── code (unique)
├── name
├── description
├── is_system
├── is_default
├── permissions (JSON list)
├── created_at
└── updated_at
OrganizationMembership
├── id
├── user (FK → User)
├── organization (FK → Organization)
├── role (FK → OrganizationRole)
├── status
├── invited_by (FK → User, nullable)
├── invited_at (nullable)
├── created_at
└── updated_at
OrganizationInvitation
├── id
├── organization (FK → Organization)
├── email
├── role (FK → OrganizationRole)
├── token (unique)
├── invited_by (FK → User, nullable)
├── status
├── created_at
├── expires_at
└── accepted_at (nullable)
Settings Reference
| Setting | Default | Description |
|---|---|---|
TENXYTE_ORGANIZATIONS_ENABLED |
False |
Enable the feature |
TENXYTE_ORG_ROLE_INHERITANCE |
True |
Propagate roles down hierarchy |
TENXYTE_ORG_MAX_DEPTH |
5 |
Max nesting depth |
TENXYTE_ORG_MAX_MEMBERS |
0 |
Max members per org (0 = unlimited) |
TENXYTE_CREATE_DEFAULT_ORGANIZATION |
True |
Create a default organization for new users |
TENXYTE_ORGANIZATION_MODEL |
'tenxyte.Organization' |
Swappable model |
TENXYTE_ORGANIZATION_ROLE_MODEL |
'tenxyte.OrganizationRole' |
Swappable model |
TENXYTE_ORGANIZATION_MEMBERSHIP_MODEL |
'tenxyte.OrganizationMembership' |
Swappable model |