Skip to main content
View as Markdown

Invitations

POST /api/auth/admin/create-user makes an admin choose the new user's password and sends them nothing — workable for a script, unusable for onboarding a customer. The invitation flow closes that gap: the admin supplies { email, name, role } with no password, Sovrium emails a single-use link, and the invitee sets their own password and lands in an authenticated session.

auth:
  strategies:
    - type: emailAndPassword
  invitationTokenExpiry: '72h' # default; accepts '30s' / '15m' / '72h' / '7d' / ms
  emailTemplates:
    invitation:
      subject: 'You are invited to join, $name'
      text: |
        Hi $name,
        $inviterName invited you to join.
        Set your password: $url
        This invitation expires in 72 hours.

The Two Endpoints

Endpoint Behavior
POST /api/auth/admin/invite-user Accepts { email, name, role } (no password). Returns 200 with { user, invitationSent: true }. 401/403 for unauth / non-admin; 400 for invalid input; 422 when the email already maps to a fully-onboarded user.
POST /api/auth/admin/accept-invitation Backs the public /accept-invitation?token=... page. The invitee sets a password and lands authenticated. 400 for an invalid token, 410 for an expired one.

Tokens reuse the auth.verification table (the same shape Better Auth uses for password reset), expire after invitationTokenExpiry72h by default — and are single-use, consumed on the first successful accept. A replay is rejected rather than silently re-onboarding.

The email body is rendered from the invitation template and substitutes $name, $url, $email and $inviterName.

Role Assignment

Sovrium ships three default roles — admin, member, viewer — with hierarchy levels 80, 40 and 10, and accepts custom roles declared in the auth block.

An invitation carries a role explicitly. When one is not supplied at creation, a new user receives auth.defaultRole, which itself falls back to member:

auth:
  strategies:
    - type: emailAndPassword
  defaultRole: viewer
  roles:
    - name: editor
      description: Can edit content
      level: 30

defaultRole is validated against the built-in roles plus your declared roles[], so a typo fails sovrium validate rather than quietly assigning nothing. The first bootstrap admin is always created with the admin role and a verified email, regardless of defaultRole.

Roles drive every authorization decision in the platform: table permissions, per-field access, page access, and the admin API itself. A role can be changed after the fact with POST /api/auth/admin/set-role.

Invitation vs. Create-User

You want Use
A customer to choose their own password invite-user — they receive a link and never see an admin-set secret.
A service or seed account, no mailbox involved create-user — you set the password, nothing is sent.
To onboard when SMTP is not configured create-user — an invitation email would never be delivered.

Last updated July 27, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta — contributions and corrections are welcome.

Built with Sovrium