Febasidocs
Guides

Tenant onboarding

Provision a new tenant end-to-end — from POST /tenants to the first authenticated admin user.

Onboarding a new tenant takes two distinct calls plus one role assignment. POST /tenants creates the organization record; POST /register creates the first user inside it; POST /roles/assign gives that user the super_admin role.

The whole flow is performed by a platform-level Client Key with tenants:create and users:create scopes.

The chicken-and-egg

A freshly created tenant has no users. To call POST /register inside that tenant you need an authenticated principal whose tenant context matches. There are two ways to do this:

  • Use a platform-level Client Key. A Client Key with tenantAccessLevel: global (and the right scopes) can call /register against any tenant by setting the X-Tenant-Code header.
  • Use the seed script (src/db/seed.ts) in development. It creates a default super-admin (admin@febasi.com.br / admin123) inside the bootstrap tenant. Useful for local work, never for production tenants.

Production onboarding should always go through the platform-key path.

Step 1 — Create the tenant

POST /api/v1/tenants
X-API-Key: ck_platform_********
X-Tenant-Code: febasi
Content-Type: application/json
{
  "code": "acme",
  "name": "ACME Corp",
  "authConfig": {
    "passwordPolicy": {
      "minLength": 12,
      "requireUppercase": true,
      "requireNumbers": true,
      "requireSpecialChars": true
    },
    "sessionLimits": {
      "maxConcurrentSessions": 3,
      "enforceLogout": true
    }
  }
}
FieldRules
code2–50 chars; lowercase, alphanumeric, -, _; must start with a letter. Becomes the tenant's tenantCode for login.
name2–255 chars. Human-readable.
authConfigOptional. Inherits service defaults for anything you omit.

Response is the new tenant record (id, code, name, status: ACTIVE, authConfig, timestamps).

Step 2 — Register the first admin

The new tenant has no users. Use the same platform Client Key with the X-Tenant-Code header pointing at the new tenant:

POST /api/v1/register
X-API-Key: ck_platform_********
X-Tenant-Code: acme
Content-Type: application/json
{
  "email": "admin@acme.com",
  "password": "First-Strong-Pass-12!"
}

The user is created inside the ACME tenant. Capture the returned id.

See Registering users for the full body shape, password policy, and error envelopes.

Step 3 — Grant super_admin

Every tenant ships with a super_admin role pre-seeded at the highest hierarchy level. Look it up by listing roles inside the tenant:

GET /api/v1/roles?name=super_admin
X-API-Key: ck_platform_********
X-Tenant-Code: acme

Then assign it:

POST /api/v1/roles/assign
X-API-Key: ck_platform_********
X-Tenant-Code: acme
{
  "userId": "<id-from-step-2>",
  "roleId": "<super_admin-id>"
}

The user can now log in via POST /login with tenantCode: "acme" and the password set in step 2.

Optional — Give the tenant its own JWT secret

By default the new tenant signs its tokens with the service-wide JWT_SECRET. To isolate the tenant's signing material, generate a dedicated secret:

POST /api/v1/tenants/me/jwt-secret/generate
Authorization: Bearer <super_admin-jwt>

See JWT secrets per tenant for the full rotation model.

End-to-end script

Create the tenant

POST /tenants with code and name. Capture the returned code (should match what you sent).

Register the first user

POST /register with X-Tenant-Code: <code-from-step-1> and a strong password. Capture the returned id.

Find super_admin

GET /roles?name=super_admin against the new tenant. Capture the role id.

Assign super_admin

POST /roles/assign with the user id and the role id. The actor (your platform key) must have hierarchy authority — platform keys with admin:* always do.

Hand off

Send the tenant code and the first admin's credentials to the customer or the application's owner. From this point on, that admin can register additional users, create roles, rotate JWT secrets, and manage the tenant without further platform involvement.

Roadmap

A single-call bootstrap (POST /tenants/bootstrap) that combines all three steps is on the roadmap. Until it ships, the three-call flow above is the recommended path.

On this page