Organizations
An organization groups users under shared ownership, gives them roles, and - the part that surprises people - becomes a tenant of its own. Creating one registers a second tenancy alongside your personal one, and switching into it changes which data your requests can see at all.
Creating an organization requires a verified email on the account
record. A locally minted token will not do; the check reads the stored
user, so an unverified account gets 403 email_not_verified no matter what
the token claims.
Create
snug auth org check-slug --slug my-org
snug auth org create --name "My Org" --slug my-org
snug auth org list
snug auth org get --id <org_id>
snug auth org update --id <org_id> --name "New Name"Mind the flag names: get, update, and delete take --id, while
invite, members, update-role, remove-member, invitations, and
set-active take --org-id.
{
"org_id": "dqxPXsVANGJNbqchQTgS",
"name": "Docs4 Auth Org",
"slug": "docs4-auth-org",
"created_by": "xhMLHYzgKQPSnTSsfcmz",
"member_count": 1,
"sso_enforced": false,
"created_at": "2026-08-28T22:55:46.249410Z",
"updated_at": "2026-08-28T22:55:46.249410Z"
}Slugs are globally unique. check-slug answers {"available": true|false},
and racing past it lands on 409 org_slug_taken. The creator becomes
owner and counts as the first member.
Roles
Three roles, strictly ordered: owner, admin, member. Anything that
changes the organization needs at least admin, and a member attempting
it gets a precise refusal:
{
"status": 403,
"msg": "insufficient organization role: required admin, actual member",
"error": "insufficient_org_role"
}The role lives in the org_role claim of a token issued for that
organization, and it is unrelated to platform_role. An organization owner
has no admin powers outside their own organization.
Members and invitations
snug auth org invite --org-id <org_id> --email dev@example.com --role member
snug auth org invitations --org-id <org_id> # sent by this org
snug auth org invitations # addressed to you
snug auth org accept-invite --invitation-id <id>
snug auth org decline-invite --invitation-id <id>
snug auth org members --org-id <org_id>
snug auth org update-role --org-id <org_id> --member-id <member_id> --role admin
snug auth org remove-member --org-id <org_id> --member-id <member_id>An invitation is addressed to an email and expires in 48 hours:
{
"invitation_id": "BQdLExeBEERfZNAKxBVy",
"org_id": "dqxPXsVANGJNbqchQTgS",
"email": "dev@example.com",
"role": "member",
"status": "pending",
"expires_at": "2026-08-30T22:56:03.739383Z"
}The invited user does not need the emailed link. Once they have an account
with that address, snug auth org invitations lists the invitation for them
by email match, which is the practical path on any deployment where mail is
not actually being delivered.
Two rules are enforced on redemption. Only the addressed account may accept,
so a different signed-in user gets
403 invitation_email_mismatch. And an invitation is spent once answered:
declining returns 204, after which accepting the same invitation is a
409 (the message reads "already been accepted" even for a declined one,
while the organization's own invitation list correctly shows
"status": "declined"). Send a fresh invitation rather than trying to
revive a spent one.
member_id is not a user ID. It is the composite
{org_id}:{user_id} returned by members and by accept-invite:
{
"member_id": "dqxPXsVANGJNbqchQTgS:ELjVQhdfXmswqAFSGCBR",
"user_id": "ELjVQhdfXmswqAFSGCBR",
"role": "member",
"created_at": "2026-08-28T22:56:21.448381Z"
}Role changes and removals both take that composite. remove-member answers
204 with no body, after which the member is gone from members.
Switching context, and what it costs
snug auth org set-active --org-id <org_id>
snug auth org clear-activeset-active re-issues your access token. The new one carries
azp set to the organization ID and picks up an org_role claim:
Subject (sub): xhMLHYzgKQPSnTSsfcmz
Tenant ID (azp): dqxPXsVANGJNbqchQTgS
Platform role: user
Org role: ownerBecause azp is the tenant boundary, this is not a cosmetic switch. Data
you wrote in your personal context is simply not there in the organization
context, and the other way around. Reproduced end to end:
snug auth org clear-active
snug kv set docs/probe '"personal"' # written under the personal tenant
snug auth org set-active --org-id <org_id>
snug kv get docs/probe{ "status": 404, "msg": "Key not found: docs/probe", "error": "key_not_found" }Nothing was deleted; the key belongs to a tenant you are no longer acting
as. clear-active returns you to the personal context and the key is
readable again. Treat an organization as a separate workspace, and decide
deliberately which context a piece of data belongs to before writing it.
Two practical consequences:
- A worker that should operate on organization data needs a token minted for the organization tenant, not a personal token with an organization membership.
- Anything that re-issues a token from scratch, such as signing in again,
drops you back to the personal context until you
set-activeonce more.
Deleting an organization
snug auth org delete --id <org_id>Deletion removes the organization and its memberships. It does not delete the member accounts themselves.
Limits
A user may create 10 organizations and an organization may hold 100 members
by default (AUTH_SERVICE_MAX_ORGS_PER_USER,
AUTH_SERVICE_MAX_MEMBERS_PER_ORG), and invitations expire after 48 hours
(AUTH_SERVICE_INVITATION_TTL_SECONDS). All three are in the
auth CONFIG reference.
Reference
- Auth API - every organization endpoint
- Enterprise SSO - giving an organization its own identity provider
- Authentication - how
azpdrives tenancy platform-wide