Organizations
Organizations provide B2B team structures for end-users with role-based access control.
An Organization represents a team, workspace, or company created by the tenant's end-users. This is a B2B feature — it allows users of your application to group themselves into teams with role-based access control.
Think of it as Slack workspaces, GitHub organizations, or Notion teams.
When to Use Organizations
- B2B SaaS: Your customers are companies, and each company needs their own workspace with team members.
- Role-based access: Different users within a team need different permission levels (admin, member, viewer).
- Team billing: You want to bill per-organization rather than per-user.
If you are building a B2C application (social media, consumer app), you likely do not need organizations at all. They are completely optional.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
id | UUID | Auto-generated | Unique identifier |
tenant_id | UUID | Required | Parent tenant |
name | string (max 255) | Required | Display name (e.g., "Startup Inc") |
slug | string (max 63) | Required | URL-safe identifier, unique per tenant |
logo_url | string? | null | URL to the organization's logo |
settings_json | JSON | {} | Custom settings |
Memberships
A Membership links a user to an organization with a specific role:
| Property | Type | Default | Description |
|---|---|---|---|
organization_id | UUID | Required | The organization |
user_id | UUID | Required | The user |
role | string | "member" | Role: "admin", "member", or custom |
permissions | string[] | [] | Fine-grained permissions (e.g., ["billing:read"]) |
A user can belong to multiple organizations. Each membership has its own role and permissions.
Invitations
Organizations grow through email invitations. An admin sends an invitation with a role assignment. The invitation contains a hashed token with an expiration date.
| Property | Type | Description |
|---|---|---|
email | string | Invited user's email |
role | string | Role assigned upon acceptance (default: "member") |
expires_at | datetime | When the invitation expires |
accepted_at | datetime? | When accepted (null if pending) |
JWT Claims
When a user signs in and belongs to an organization, the JWT access token includes organization claims:
{
"sub": "user_def456",
"tid": "tenant_ghi012",
"org_id": "org_jkl345",
"org_role": "admin"
}Your application can use these claims to enforce organization-level access control without additional API calls.
API Endpoints
| Method | Path | Description |
|---|---|---|
POST | /v1/admin/organizations | Create an organization |
GET | /v1/admin/organizations | List organizations |
GET | /v1/admin/organizations/{org_id} | Get an organization |
PATCH | /v1/admin/organizations/{org_id} | Update name, settings |
DELETE | /v1/admin/organizations/{org_id} | Delete an organization |
GET | /v1/admin/organizations/{org_id}/members | List members |
POST | /v1/admin/organizations/{org_id}/members | Add a member |
PATCH | /v1/admin/organizations/{org_id}/members/{user_id} | Update role |
DELETE | /v1/admin/organizations/{org_id}/members/{user_id} | Remove member |
POST | /v1/admin/organizations/{org_id}/invitations | Send an invitation |
B2B vs B2C Comparison
| B2C App | B2B App | |
|---|---|---|
| Organizations | Not needed | Essential |
| Example | Photo editing app | Project management SaaS |
| User model | Each user is independent | Users belong to teams |
| Access control | Per-user | Per-organization + role |
| Billing | Per-user | Per-organization |
Real-World Example
TaskFlow is a project management SaaS for companies:
- Tenant: "TaskFlow" (plan: pro)
- Project: "TaskFlow App" (production)
End-users create their own organizations:
| Organization | Members | Description |
|---|---|---|
| Startup Inc | Alice (admin), Bob (member) | A small startup team |
| Agency XYZ | Diana (admin), Eve (member) | A design agency |
Alice manages her team from the TaskFlow dashboard — inviting members, assigning roles, and removing people. TaskFlow's backend checks the org_id and org_role JWT claims to determine access.