Skip to content

Guides

Multi-tenant

How Inspow isolates data per organization (tenant).

Inspow is multi-tenant: each Organization (in the code, tenant) operates in isolation. Its data (Users, Beneficiaries, Subscriptions, Plans, Invoices, Attendance Records, Meal Menus) belongs to a single organization and is never mixed with another’s.

The organization is not taken from a client header, but from a verified credential. The middleware accepts two forms in Authorization:

  • JWT (Bearer <token>): the tenant_id is read from the token.
  • API Key (token with the ak_ prefix): the key is validated and its organization is resolved.

The subdomain can provide a hint of the slug, but on its own it gives no access: without a valid credential there is no tenant_id.

Access depends on the organization’s status (status):

StatusValueAPI access
TrialtrialAllowed while the period hasn’t expired; expired → HTTP 402 (SAAS_ACCOUNT_LOCKED)
ActiveactiveAllowed
SuspendedsuspendedBlocked: HTTP 402 (SAAS_ACCOUNT_LOCKED) if the pause is due to the account’s payment; HTTP 503 in other cases
ClosedclosedPermanently blocked (HTTP 403)

A new organization starts in trial with a 14-day trial; when it expires, the API responds 402 until the account settles its Plan.

The organization type is defined by the vertical field. In the API, the people served are always beneficiaries (beneficiaries); what changes is how the app calls them:

  • Gym (gym): Members
  • School (school): Beneficiaries
  • Academy (academy): Students
  • Club (club): Club members
  • Coworking (coworking): Coworkers
  • Clinic (clinic): Patients

Operations on /tenants require admin:tenants (super-admin), except reading your own tenant:

MethodPathPermission
POST/tenantsadmin:tenants
GET/tenantsadmin:tenants
GET/tenants/:idread:tenant-info (own tenant only)
PATCH/tenants/:idadmin:tenants
POST/tenants/:id/suspendadmin:tenants
POST/tenants/:id/activateadmin:tenants
DELETE/tenants/:idadmin:tenants (logical closure)
GET/tenants/:id/preferencesread:tenant-preferences
PATCH/tenants/:id/preferencesupdate:tenant-preferences
GET/tenants/:id/feature-flagsread:tenant-features
PATCH/tenants/:id/feature-flagsadmin:tenants

Deletion is a logical closure: it moves the organization to closed, it doesn’t delete the data.