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:
ownerormember - 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:
| Data | Source |
|---|---|
| Subscription | session.subscription / getSubscription() |
| Balance | getBalance() |
| Transactions | getTransactions() |
| Billing portal | openBillingPortal() |
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.