Endpoints
All endpoints are mounted under your Better Auth base path (e.g. /api/auth).
Tenant management
Requires management authorization unless noted. See Tenant management for membership roles vs global admin rules.
POST /tenant/create
Create a new tenant. The authenticated platform user’s id is stored as ownerId and an owner tenantMember row is created when a session is present.
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Display name |
slug | string | yes | Unique URL-friendly id |
metadata | object | no | Arbitrary JSON metadata |
Response: Tenant object
GET /tenant/get
Get a tenant by id or slug. This endpoint is public, but the response depends on the caller:
- Unauthorized callers (and unrelated platform users) receive only the public fields:
id,name,slug,createdAt. - Tenant members and global admins (
canManageTenants) receive the full record, includingownerIdandmetadata. - Set
exposeTenantDetailsPublicly: trueto always return the full record (not recommended ifmetadataholds private data).
Query
| Field | Type | Required | Description |
|---|---|---|---|
id | string | one of | Tenant id |
slug | string | one of | Tenant slug |
Response: Tenant object (public subset for unauthorized callers)
GET /tenant/list
List tenants the caller can access (all for global admin; memberships for platform users).
Query
| Field | Type | Required | Description |
|---|---|---|---|
limit | number | no | Max items to return (1–100) |
offset | number | no | Number of items to skip (default 0) |
Response: Array of tenant objects when limit and offset are omitted. When either is provided, returns { data, total, nextOffset? }.
POST /tenant/update
Update a tenant. Requires admin role or higher (or global admin).
Body
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Tenant to update |
data | object | yes | Fields to update |
data may include name, slug, and metadata. Pass metadata: null to clear metadata; omit the field to leave it unchanged.
Response: Updated tenant object
POST /tenant/delete
Delete a tenant and cascade related records. Requires owner role (or global admin).
Body
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Tenant to delete |
Response: { success: true }
Membership
POST /tenant/member/add
Add a platform user as a member. Requires admin or higher. Admins may only assign role member.
Body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | yes | Tenant |
userId | string | one of | Platform user id |
email | string | one of | Platform user email |
role | string | no | owner | admin | member |
Response: TenantMember object
GET /tenant/member/list
List members. Requires member role or higher.
Query
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | yes | Tenant |
limit | number | no | Max items to return (1–100) |
offset | number | no | Number of items to skip (default 0) |
Response: Array of TenantMember objects when limit and offset are omitted. When either is provided, returns { data, total, nextOffset? }.
POST /tenant/member/update
Change a member’s role. Requires owner (or global admin). Cannot demote the last owner.
Body: tenantId, userId, role
Response: TenantMember object
POST /tenant/member/remove
Remove a member. Requires admin or higher. Admins cannot remove owners/admins. Cannot remove the last owner.
Body: tenantId, userId
Response: { success: true }
Invites
Manage invites for tenant end-user email and first-time OAuth registration. Requires admin role or higher (or global admin). When requireInviteForTenantSignUp is enabled, registration must include a matching inviteToken.
POST /tenant/invite/create
Create an invite for a tenant end-user.
Body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | yes | Tenant |
email | string | yes | Email address to invite |
expiresIn | number | no | Lifetime in seconds (default 7 days) |
Response: TenantInvite object (includes token for the sign-up link)
GET /tenant/invite/list
List invites for a tenant. By default returns only pending (unconsumed, unrevoked, unexpired) invites.
Query
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | yes | Tenant |
includeConsumed | boolean | no | Include consumed and revoked invites |
Response: Array of TenantInvite objects
POST /tenant/invite/revoke
Revoke a pending invite.
Body: tenantId, inviteId
Response: TenantInvite object
Email auth
POST /tenant/sign-up/email
Sign up a user under a tenant.
Body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | no* | Tenant id |
name | string | yes | User display name |
email | string | yes | Email address |
password | string | yes | Password |
image | string | no | Profile image URL |
callbackURL | string | no | Email verification callback |
rememberMe | boolean | no | Remember session (default true) |
inviteToken | string | no* | Invite token from an admin |
*Required when requireInviteForTenantSignUp is enabled.
*Required unless resolved via header or resolveTenantId.
Response: User and session (when verification not required)
POST /tenant/sign-in/email
Sign in a user under a tenant.
Body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | no* | Tenant id |
email | string | yes | Email address |
password | string | yes | Password |
callbackURL | string | no | Redirect after sign-in |
rememberMe | boolean | no | Remember session (default true) |
Response: User and session
GET /tenant/verify-email
Verify a tenant-scoped user's email from the link sent by signUpEmailTenant / signInEmailTenant. Not interchangeable with core's GET /verify-email — see Email auth.
Query
| Field | Type | Required | Description |
|---|---|---|---|
token | string | yes | Tenant-scoped verification token |
callbackURL | string | no | Redirect target after (or on failure) |
Response: { status: true, user: null }, or a redirect to callbackURL (with ?error=<code> on failure) when provided
OAuth configuration
Requires management authorization.
POST /tenant/oauth-config/register
Create or update a per-tenant OAuth provider config.
Body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | no* | Tenant id |
providerId | string | yes | e.g. google, github |
clientId | string | yes | OAuth client id |
clientSecret | string | yes | OAuth client secret |
scopes | string[] | no | Requested scopes |
redirectURI | string | no | Override redirect URI |
enabled | boolean | no | Default true |
Response: Config object (no client secret)
GET /tenant/oauth-config/list
List OAuth configs for a tenant.
Query
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | no* | Tenant id |
Response: Array of config objects (secrets omitted)
POST /tenant/oauth-config/delete
Delete a tenant OAuth config.
Body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | no* | Tenant id |
providerId | string | yes | Provider to remove |
Response: { success: true }
OAuth sign-in
POST /tenant/sign-in/social
Start OAuth sign-in for a tenant.
Body
| Field | Type | Required | Description |
|---|---|---|---|
tenantId | string | no* | Tenant id |
provider | string | yes | Provider id |
callbackURL | string | no | Success redirect |
newUserCallbackURL | string | no | Redirect for newly registered users |
errorCallbackURL | string | no | Error redirect |
inviteToken | string | no* | Required for first-time registration when invite-only sign-up is enabled |
requestSignUp | boolean | no | Explicitly request sign-up |
disableRedirect | boolean | no | Return the URL instead of redirecting |
Response: Redirect to OAuth provider (or { url, redirect } when disableRedirect is true)
First-time social registration honors requireInviteForTenantSignUp / allowedEmailDomains the same way as email sign-up. Existing OAuth users can sign in without an invite.
GET /tenant/callback/{providerId}
OAuth callback handler. Creates a session with tenantId and redirects to callbackURL.
Tenant id resolution
For endpoints marked with *, tenantId can be omitted when resolved via:
resolveTenantIdoption- Request body
tenantId - Query
tenantId - Header (default
x-tenant-id)
See Configuration.