Skip to Content
We are live but in Staging 🎉
API ReferenceUsers & Tenants

Users & tenants

Base: https://api.dodil.io/v1/appid/pools/{pool} · platform bearer · see conventions.

Users

Method + pathBody / paramsNotes
GET /usersemailFilter?, limit? (≤500), cursor?, includeDeleted?Email prefix filter; keyset pagination via nextCursor
GET /users/{userId}
POST /users{ "email", "password?", "emailVerified?", "appRoles?" }No password = invite — the user gets an email link to set one
PATCH /users/{userId}{ "email?", "emailVerified?" }
DELETE /users/{userId}{ "hard?" }Soft by default (hidden, recoverable)
POST /users/{userId}/password{ "password", "keepSessions?" }Revokes sessions unless kept
POST /users/{userId}/sessions/revokeSign out everywhere
POST /users/{userId}/roles{ "roles": [] }Replaces the role set
POST /users/{userId}/ban{ "banned": true|false }Blocks sign-in, keeps the record

The AppUser object:

{ "id": "…", "email": "[email protected]", "emailVerified": true, "appRoles": ["admin"], "banned": false, "createdAt": "…" }

Roles resolve into token permissions[] through the pool’s role catalog.

Tenants

Sub-organizations inside the pool. Slugs: 1–63 chars [a-z0-9-], immutable.

Method + pathBody / params
POST /tenants{ "slug", "displayName?", "metadataJson?" }
GET /tenants
PATCH /tenants/{tenant}{ "displayName?", "metadataJson?" }
DELETE /tenants/{tenant}

Membership

Method + pathBody / paramsNotes
POST /tenants/{tenant}/members{ "userId", "roles": [] }Replaces that user’s roles in the tenant
DELETE /tenants/{tenant}/members/{userId}
GET /tenants/{tenant}/memberslimit?, cursor?Rows: userId, email, roles[], createdAt
GET /users/{userId}/tenantsThe user’s tenants with their roles

Membership flows into tokens automatically (the tenants claim, and pinned-tenant sign-in) — see Concepts → App tenants.