Tenants And Organizations

Use these routes with a PLATFORM_ADMIN token.

Tenant Lifecycle

ActionRoute
List tenantsGET /admin/api/v1/tenants
Create tenantPOST /admin/api/v1/tenants
Read tenantGET /admin/api/v1/tenants/{tenant_id}
Update tenantPATCH /admin/api/v1/tenants/{tenant_id}
Delete tenantDELETE /admin/api/v1/tenants/{tenant_id}

Create tenants with a stable slug, display name, optional instance_fingerprint, and optional branding.

  {
  "name": "Example Tenant",
  "slug": "example-tenant",
  "instance_fingerprint": "sha256:example"
}
  

Tenant deletion is a backend soft delete. Treat it as an operationally sensitive action and keep the audit record attached to the change.

Organization Lifecycle

ActionRoute
List organizations in a tenantGET /admin/api/v1/tenants/{tenant_id}/organizations
Create organization in a tenantPOST /admin/api/v1/tenants/{tenant_id}/organizations
Read organizationGET /admin/api/v1/tenants/{tenant_id}/organizations/{organization_id}
Update organizationPATCH /admin/api/v1/tenants/{tenant_id}/organizations/{organization_id}
Delete organizationDELETE /admin/api/v1/tenants/{tenant_id}/organizations/{organization_id}
Canonical create aliasPOST /admin/api/v1/organizations

The canonical create alias accepts tenant_id in the JSON body and is useful for onboarding tools that do not use tenant-scoped URLs.

  {
  "tenant_id": "11111111-1111-4111-8111-111111111111",
  "name": "Example Client",
  "slug": "example-client",
  "commercial_tier": "CLIENT",
  "email_domains": ["example.com"]
}
  

Commercial Tree

The backend stores a variable-depth commercial tree. Use:

FieldPurpose
is_selfMarks the operator organization for the instance.
parent_organization_idLinks a reseller/client to its direct provider.
commercial_tierDescriptive tier such as DISTRIBUTEUR, REVENDEUR, or CLIENT.

The tier is billing metadata. It does not create a new application role.

Organization Provisioning

When the Keycloak Admin provisioner is configured, organization creation calls Keycloak and returns a provisioning status. If Keycloak is unavailable, the backend returns a structured SERVICE_UNAVAILABLE error instead of silently creating a partial identity state.

Operational Checks

After creating an organization:

CheckExpected result
Organization appears in GET /admin/api/v1/tenants/{tenant_id}/organizations.Present, not deleted.
Audit log contains the admin action where applicable.Entry hash populated.
Keycloak organization metadata exists when the provisioner is enabled.External ID stored or provisioner status returned.
Branding and IdP URLs pass the outbound URL policy.No private, localhost, link-local, or credential-bearing URLs unless explicitly allowed.