Example Docs

Organizations

The organizations plugin adds multi-tenant support to your app. Users can create organizations, invite members, assign roles, and manage teams.

Setup

import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";

export const auth = betterAuth({
  plugins: [
    organization({
      allowUserToCreateOrganization: true,
      maximumOrganizations: 5, // Per user
      roles: {
        owner: {
          permissions: ["*"], // All permissions
        },
        admin: {
          permissions: ["member:read", "member:invite", "member:remove", "organization:update"],
        },
        member: {
          permissions: ["member:read"],
        },
      },
    }),
  ],
});

Client Setup

import { createAuthClient } from "better-auth/react";
import { organizationClient } from "better-auth/client/plugins";

export const authClient = createAuthClient({
  plugins: [organizationClient()],
});

Creating an Organization

const { data: org, error } = await authClient.organization.create({
  name: "Acme Inc",
  slug: "acme",
  metadata: {
    plan: "pro",
    industry: "saas",
  },
});

console.log("Created:", org.name); // "Acme Inc"

Inviting Members

// Invite by email
const { data: invitation } = await authClient.organization.inviteMember({
  organizationId: org.id,
  email: "colleague@example.com",
  role: "member",
});

// The invited user receives an email with an accept link

Accept an Invitation

const { data } = await authClient.organization.acceptInvitation({
  invitationId: "invitation-id",
});

Managing Members

List Members

const { data: members } = await authClient.organization.listMembers({
  organizationId: org.id,
});

members.forEach((member) => {
  console.log(`${member.user.name} — ${member.role}`);
});

Update Member Role

await authClient.organization.updateMemberRole({
  organizationId: org.id,
  memberId: "member-id",
  role: "admin",
});

Remove a Member

await authClient.organization.removeMember({
  organizationId: org.id,
  memberId: "member-id",
});

Active Organization

Users can be part of multiple organizations. Set the active one:

// Set active organization
await authClient.organization.setActive({
  organizationId: org.id,
});

// Get active organization
const { data: activeOrg } = await authClient.useActiveOrganization();

Server-Side Usage

Check Organization Membership

const session = await auth.api.getSession({ headers });
const membership = await auth.api.getOrganizationMember({
  organizationId: "org-id",
  userId: session.user.id,
});

if (!membership) {
  throw new Error("Access denied");
}

if (membership.role !== "admin" && membership.role !== "owner") {
  throw new Error("Insufficient permissions");
}

Database Schema

The plugin adds these tables:

TableDescription
organizationOrganization details (name, slug, metadata)
memberUser-organization relationship with roles
invitationPending invitations

Permissions

Define custom permissions per role:

organization({
  roles: {
    owner: { permissions: ["*"] },
    admin: {
      permissions: [
        "member:read",
        "member:invite",
        "member:remove",
        "project:create",
        "project:read",
        "project:update",
        "project:delete",
        "billing:read",
        "billing:update",
      ],
    },
    viewer: {
      permissions: ["member:read", "project:read"],
    },
  },
});

Check permissions:

const hasPermission = await auth.api.hasPermission({
  organizationId: "org-id",
  userId: session.user.id,
  permission: "project:delete",
});