Organizations
Organizations let your end-users create and manage multi-tenant workspaces inside your product. Each organization has members with roles, and roles carry permissions you define.
How it works
An organization is a group of end-users that share access to resources in your application. AuthGate manages the full lifecycle — creation, membership, invitations, and permission checks — so you don't have to build multi-tenancy infrastructure from scratch.
- Every organization has a unique ID and an optional slug (human-readable URL segment)
- Members belong to an organization through a membership record that links a user, an organization, and a role
- Roles carry permissions defined as
resource:actionstrings (e.g.documents:write) - Invitations are time-limited (7 days) and accepted via a one-time token
See Roles & Permissions for how to define roles and permission strings, and Organizations SDK for the full SDK reference.
Creating organizations
Organizations are created by end-users through your application. Call the proxy API or use the AuthGateClient from @auth-gate/core.
Via the proxy API
Create organization
curl -X POST https://your-authgate-instance.com/api/proxy/orgs \
-H "Authorization: Bearer <user_jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corp",
"slug": "acme-corp"
}'
Response
{
"org": {
"id": "org_abc123",
"name": "Acme Corp",
"slug": "acme-corp",
"created_at": "2025-01-15T10:00:00Z"
}
}
The user who creates the organization is automatically added as a member with the default admin role.
Via the SDK
src/app/api/orgs/route.ts
import { createAuthGate } from "@auth-gate/nextjs";
const { client } = createAuthGate({
apiKey: process.env.AUTHGATE_API_KEY!,
baseUrl: process.env.AUTHGATE_URL!,
appUrl: process.env.NEXT_PUBLIC_APP_URL!,
});
export async function POST(request: Request) {
const { name, slug } = await request.json();
const org = await client.createOrg({ name, slug });
return Response.json({ org });
}
Listing organizations
List orgs for the current user
import { AuthGateClient } from "@auth-gate/core";
const client = new AuthGateClient({
baseUrl: process.env.AUTHGATE_URL!,
userToken: userJwt,
});
const { organizations } = await client.listOrgs();
Each entry in organizations is an OrgWithMembership — it includes the org details and the calling user's membership record (role and permissions).
Managing members
Adding a member
Add a user directly to an organization via the admin API. This is useful for programmatic onboarding flows where you don't need the invitation email flow.
Add member (admin API)
import { AuthGateClient } from "@auth-gate/core";
const adminClient = new AuthGateClient({
baseUrl: process.env.AUTHGATE_URL!,
apiKey: process.env.AUTHGATE_API_KEY!,
});
await adminClient.addOrgMember("org_abc123", {
userId: "user_xyz",
roleKey: "member",
});
Changing a member's role
Update member role
await client.updateOrgMember("org_abc123", "user_xyz", {
roleKey: "admin",
});
Removing a member
Remove member
await client.removeOrgMember("org_abc123", "user_xyz");
Leaving an organization
Members can leave an organization themselves:
Leave org
await client.leaveOrg("org_abc123");
The last admin of an organization cannot leave or be removed. Transfer the admin role to another member first, or delete the organization.
Invitations
Invite users to an organization by email. AuthGate sends the invitation email and manages the token lifecycle.
Sending an invitation
Invite by email
const { invitation } = await client.inviteToOrg("acme-corp", {
email: "alice@example.com",
roleKey: "member",
});
Invitation object
{
"id": "inv_abc123",
"email": "alice@example.com",
"role": { "key": "member", "name": "Member" },
"expires_at": "2025-01-22T10:00:00Z",
"created_at": "2025-01-15T10:00:00Z"
}
Invitations expire after 7 days. The invited user receives an email with a link containing a one-time accept token.
Accepting an invitation
When the user clicks the invitation link, exchange the token for membership:
Accept invitation
const { membership } = await client.acceptOrgInvitation({
token: "inv_token_from_url",
});
The user must be authenticated before accepting. If they don't have an account, prompt them to sign up first.
Managing pending invitations
List and revoke invitations
// List pending invitations for an org
const { invitations } = await client.listOrgInvitations("acme-corp");
// Revoke a specific invitation
await client.revokeOrgInvitation("acme-corp", "inv_abc123");
Only members with the org:manage permission (or a wildcard role) can send, list, and revoke invitations.
Permissions
Check whether the current user has a specific permission before performing sensitive actions.
Using SDK utilities
Check permissions server-side
import { hasPermission, hasRole, hasAnyPermission } from "@auth-gate/core";
import { createOrgHelpers } from "@auth-gate/nextjs";
const { getOrgMembership } = createOrgHelpers({
baseUrl: process.env.AUTHGATE_URL!,
apiKey: process.env.AUTHGATE_API_KEY!,
});
export async function deleteDocument(orgId: string, userId: string) {
const membership = await getOrgMembership(orgId, userId);
if (!hasPermission(membership, "documents:delete")) {
throw new Error("Insufficient permissions");
}
// proceed with deletion
}
Using React hooks and components
Gate UI by permission
import { OrgGuard } from "@auth-gate/react";
function ManageTeamButton({ orgId }: { orgId: string }) {
return (
<OrgGuard orgId={orgId} permission="org:manage" fallback={null}>
<button>Manage Team</button>
</OrgGuard>
);
}
See Roles & Permissions for the full permission string format and Organizations SDK for the complete SDK reference.