Organizations

Organizations let your users form teams. Subscriptions, balance, and billing are all scoped to the active organization.

Concepts

Personal Organization

Every user gets a personal org on signup:

  • Created automatically, cannot be deleted
  • User is always the owner
  • Name matches the user's email
  • Used as the default context

Team Organizations

Users can create team orgs to collaborate:

  • Creator becomes the owner
  • Members can be invited via email or shareable links
  • Each member has a role: owner or member
  • Multiple owners are allowed

Active Organization

The JWT always includes an active_org_id. All org-scoped operations (subscriptions, balance, billing) use the active org. Switching orgs re-issues the JWT with the new context.

Creating Organizations

const reauth = createReauthClient({ domain: 'yourdomain.com' });

const org = await reauth.createOrg('Acme Corp');
// { id: "uuid", name: "Acme Corp", isPersonal: false, createdAt: "..." }

Listing Organizations

const orgs = await reauth.listOrgs();
// Returns all orgs the user belongs to (personal + team orgs)

Switching Organizations

When the user switches orgs, the JWT is re-issued with the new active_org_id, org_role, and subscription data for that org:

const result = await reauth.switchOrg('org-uuid');
// {
//   activeOrgId: "org-uuid",
//   orgRole: "owner",
//   subscription: {
//     status: "active",
//     planCode: "pro",
//     planName: "Pro Plan",
//     ...
//   },
// }

After switching, getSession() reflects the new org context:

const session = await reauth.getSession();
session.active_org_id; // "org-uuid"
session.org_role;       // "owner"
session.subscription;   // Subscription for this org

Member Management

Listing Members

const members = await reauth.listOrgMembers('org-uuid');
// [{ id, orgId, endUserId, role: "owner" | "member", joinedAt }]

Updating Roles

Owners can change member roles:

await reauth.updateMemberRole('org-uuid', 'user-uuid', 'owner');

Removing Members

Owners can remove members:

await reauth.removeOrgMember('org-uuid', 'user-uuid');

Invitations

Email Invitations

// Send invite (owner only)
const invite = await reauth.inviteToOrg('org-uuid', 'user@example.com', 'member');
// { id, orgId, email, token, role, status: "pending", expiresAt, createdAt }

// List pending invites
const pending = await reauth.listPendingInvites('org-uuid');

// Revoke an invite
await reauth.revokeInvite('org-uuid', 'invite-uuid');

// Accept an invite (invitee)
const { orgId, role } = await reauth.acceptInvite('invite-token');

Shareable Invite Links

// Create a link (owner only)
const link = await reauth.createInviteLink('org-uuid', 'member');
// { id, orgId, token, role, isActive, expiresAt, createdAt }

// List links
const links = await reauth.listInviteLinks('org-uuid');

// Revoke a link
await reauth.revokeInviteLink('org-uuid', 'link-uuid');

// Join via link (anyone with the token)
await reauth.joinViaLink('link-token');

Org-Scoped Data

When a user switches orgs, these change to reflect the active org:

DataSource
Subscriptionsession.subscription / getSubscription()
BalancegetBalance()
TransactionsgetTransactions()
Billing portalopenBillingPortal()

This means each org can have its own subscription plan and credit balance.

Deletion Guards

  • A user who is the sole owner of an org with other members cannot delete their account or leave the org
  • Transfer ownership first, or remove all other members
  • Personal orgs cannot be deleted

Managing Organizations

// Update org name (owner only)
await reauth.updateOrg('org-uuid', 'New Name');

// Delete org (owner only, no other members)
await reauth.deleteOrg('org-uuid');

Server-Side: Reading Org Context

The server SDK's authenticate() returns org context from the JWT:

const result = await reauth.authenticate(request);
if (result.valid && result.user) {
  result.user.activeOrgId; // Current org
  result.user.orgRole;     // "owner" | "member"
}

No network call needed — org context is embedded in the JWT.