Velocity • Durability

5. Tenants

Creating, listing, and configuring the tenants that partition a realm, including each tenant’s StorageSet quota allocations.

Endpoint Summary

Path Summary Method
/api/v1/tenants List tenants GET
/api/v1/tenants Create tenant POST
/api/v1/tenants/archived List archived tenants GET
/api/v1/tenants/roles List roles available on the current tenant GET
/api/v1/tenants/{tenant_id} Get tenant info GET
/api/v1/tenants/{tenant_id} Update tenant PATCH
/api/v1/tenants/{tenant_id} Delete tenant DELETE
/api/v1/tenants/{tenant_id}/storagesets List tenant storageset quota allocations GET
/api/v1/tenants/{tenant_id}/storagesets/{storageset_id} Get tenant storageset GET
/api/v1/tenants/{tenant_id}/storagesets/{storageset_id} Assign or resize tenant storageset PUT
/api/v1/tenants/{tenant_id}/storagesets/{storageset_id} Unassign tenant storageset DELETE

GET /api/v1/tenants

List tenants

Returns a list of all tenants, each carrying the network status the realm manager reports for it. Any platform role that grants tenants:list may call it.

Authentication: required (PasswordLogin or BearerJWT).

Responses

Status Description Schema
200 Successful response containing the list of tenants ListTenantResponse
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
500 Internal server error. -

Response Body (200, ListTenantResponse)

Field Type Required Default Example Description
tenants array of TenantSummarySchema object no n/a Array of tenant summary objects. Empty array if no tenants found
total integer yes n/a 0, 5, 50 Total count of tenants in this response.

Example

{
   "tenants" : [
      {
         "created_at" : "2026-03-02T12:00:00Z",
         "description" : "FinTech tenant",
         "id" : "e97b94d6-9cc1-4325-a267-1064ae538ccd",
         "name" : "fintech",
         "status" : "active",
         "updated_at" : "2026-03-02T12:00:00Z"
      }
   ],
   "total" : 1
}

POST /api/v1/tenants

Create tenant

Creates a new tenant with the specified configuration and returns its ID. Platform Admin only.

Authentication: required (PasswordLogin or BearerJWT).

Request Body (application/json, required)

Schema: TenantCreateRequest

Request payload for creating a tenant.

Field Type Required Default Example Description
auth_settings LocalAuthSettings object or PamAuthSettings object yes n/a {"auth_mode":"local"}, {"auth_mode":"pam","service":"login"} Tenant authentication settings. Discriminated on auth_mode.
description string, nullable no null FinTech department tenant, Engineering team workspace Tenant description.
display_name string yes n/a FinTech, Engineering, Data Science Human-readable tenant name. Must be 1-255 printable characters.
email string yes n/a admin@fintech.example.com, ops@vdura.example.com Tenant contact email address.
name string yes n/a fintech, eng, datasci Tenant name, used for volume mounting and as the prefix of a tenant-qualified username. Must be 3-10 alphanumeric characters and unique within the system. Stored in lower case. platform is reserved. Immutable after creation.

Responses

Status Description Schema
201 Tenant created successfully TenantCreateResponse
400 Bad request. Invalid parameters or validation error. -
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
409 Conflict. This realm serves its clients over InfiniBand, which cannot carry the VLAN or VXLAN encapsulation multi-tenancy needs, so no tenant can be created on it. -
422 Validation error. Returned for invalid request body. -
500 Internal server error. -
503 Service unavailable. A backend dependency the request needs is unreachable. The request was well formed and changed nothing, so the same call is worth retrying once the dependency is back; which one failed is recorded server-side, not in the response. -

Response Body (201, TenantCreateResponse)

Field Type Required Default Example Description
id string (uuid) yes n/a e97b94d6-9cc1-4325-a267-1064ae538ccd Unique tenant identifier (UUID) assigned by the system

Example

{
   "id" : "e97b94d6-9cc1-4325-a267-1064ae538ccd"
}

GET /api/v1/tenants/archived

List archived tenants

Returns the deleted tenants kept in the platform archive, newest deletion first. Platform Admin only. An archived tenant exists in neither the storage fabric nor the configuration store: the entry is all that is left of it, and it is never removed. Its display name and contact email have no other surviving copy.

Authentication: required (PasswordLogin or BearerJWT).

Responses

Status Description Schema
200 Successful response containing the deleted tenants held in the platform archive. ListArchivedTenantResponse
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
500 Internal server error. -

Response Body (200, ListArchivedTenantResponse)

Field Type Required Default Example Description
tenants array of ArchivedTenantSchema object no n/a Array of archived tenants, newest deletion first. Empty array if none were ever deleted.
total integer yes n/a 0, 5, 50 Total count of archived tenants in this response.

Example

{
   "tenants" : [
      {
         "created_at" : "2026-01-10T08:00:00Z",
         "deleted_at" : "2026-04-02T11:20:00Z",
         "description" : "Decommissioned engineering tenant",
         "display_name" : "Engineering (retired)",
         "email" : "eng-owner@vdura.example.com",
         "id" : "3f2b1c0d-5e4a-4b8c-9d7e-6a5b4c3d2e1f",
         "name" : "oldeng",
         "status" : "archived",
         "updated_at" : "2026-04-02T11:15:00Z"
      }
   ],
   "total" : 1
}

GET /api/v1/tenants/roles

List roles available on the current tenant

Returns the roles available on the caller’s current tenant - resolved from the auth context, with no tenant_id path parameter. The response is a roles array with a total; each entry carries the role id and the permissions map of resource to the actions that role may perform on it. Roles are read from the current tenant’s RBAC policy, so Platform and Tenant contexts each return the role set defined and enforced on their own tenant.

Authentication: required (PasswordLogin or BearerJWT).

Responses

Status Description Schema
200 Roles available on the current tenant retrieved successfully. TenantRolesResponse
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant RBAC policy roles not found. -
500 Internal server error. -

Response Body (200, TenantRolesResponse)

Field Type Required Default Example Description
roles array of TenantRole object no n/a Array of roles the tenant policy defines. Empty array if the policy defines none.
total integer yes n/a 2, 5 Total count of roles in this response.

Example

{
   "roles" : [
      {
         "id" : "admin",
         "permissions" : {
            "roles" : [
               "view",
               "update"
            ],
            "tenants" : [
               "view"
            ],
            "users" : [
               "list",
               "view",
               "create",
               "update",
               "delete"
            ],
            "volumes" : [
               "list",
               "view",
               "create",
               "update",
               "delete",
               "action"
            ]
         },
         "reserved" : false
      },
      {
         "id" : "s3-gateway",
         "permissions" : {
            "fs-users" : [
               "read-s3-secret",
               "list"
            ]
         },
         "reserved" : true
      }
   ],
   "total" : 2
}

GET /api/v1/tenants/{tenant_id}

Get tenant info

Returns details for a specific tenant by its ID, including the network status the realm manager reports for it. The platform tenant may view any tenant, and a Tenant Admin may view only their own tenant.

Authentication: required (PasswordLogin or BearerJWT).

Parameters

Name In Type Required Description
tenant_id path string (uuid) yes Tenant identifier (UUID)

Responses

Status Description Schema
200 Successfully retrieved detailed information about the tenant. GetTenantResponse
400 Bad request. Invalid tenant_id parameter. -
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant not found. -
422 Validation Error HTTPValidationError
500 Internal server error. -

Response Body (200, GetTenantResponse)

Field Type Required Default Example Description
tenant Tenant object yes n/a Tenant entity with all available details.

PATCH /api/v1/tenants/{tenant_id}

Update tenant

Updates a tenant using PATCH semantics. Only the fields provided in the request are modified. Platform Admin only.

Authentication: required (PasswordLogin or BearerJWT).

Parameters

Name In Type Required Description
tenant_id path string (uuid) yes Tenant identifier (UUID)

Request Body (application/json, required)

Schema: TenantPatchRequest

Request payload for updating a tenant via PATCH.

Allows partial updates. At least one field must be provided. Patchable fields: display_name, email, description, auth_settings. Tenant Admin can update display_name, email, description and auth_settings. name is the immutable handle and is not patchable.

Field Type Required Default Example Description
auth_settings LocalAuthSettings object or PamAuthSettings object, nullable no null {"auth_mode":"local"}, {"auth_mode":"pam","service":"login"} Updated tenant authentication settings.
description string, nullable no null Updated tenant description, New department focus Updated tenant description.
display_name string, nullable no null FinTech Renamed, Engineering 2.0 Updated human-readable tenant name. Must be 1-255 printable characters.
email string, nullable no null admin@fintech.example.com Updated tenant contact email address.

Responses

Status Description Schema
204 Tenant updated successfully. -
400 Bad request. Invalid tenant_id or custom validation error. -
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant not found. -
422 Validation error. Returned for invalid request body (all fields are optional). -
500 Internal server error. -

DELETE /api/v1/tenants/{tenant_id}

Delete tenant

Deletes the specified tenant by its ID, removing its records from both the storage fabric and the configuration store and leaving an entry in the platform archive. Platform Admin only. Safe to repeat: a delete interrupted part-way is resumed by sending it again.

Authentication: required (PasswordLogin or BearerJWT).

Parameters

Name In Type Required Description
tenant_id path string (uuid) yes Tenant identifier (UUID)

Responses

Status Description Schema
204 Tenant deleted successfully. -
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant not found. -
409 Conflict. The tenant cannot be deleted as it currently stands: it still owns volumes or subnets, a delete of it is already running, or it is the immutable PanAPI Platform Tenant. The detail says which; the example shows the shape, not the alternatives. -
422 Validation Error HTTPValidationError
500 Internal server error. -

GET /api/v1/tenants/{tenant_id}/storagesets

List tenant storageset quota allocations

Lists the storageset quota allocations assigned to a tenant. Callers may only list their own tenant.

Authentication: required (PasswordLogin or BearerJWT).

Parameters

Name In Type Required Description
tenant_id path string (uuid) yes Tenant identifier (UUID)

Responses

Status Description Schema
200 Successful response containing the tenant’s storageset quota allocations. ListTenantStorageSetResponse
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant not found. -
422 Validation Error HTTPValidationError
500 Internal server error. -

Response Body (200, ListTenantStorageSetResponse)

Field Type Required Default Example Description
storagesets array of StorageSetAssignment object no n/a Array of storageset assignments (id + quota + name). Empty array if none are assigned.
total integer yes n/a 0, 2, 5 Total count of storageset assignments in this response.

Example

{
   "storagesets" : [
      {
         "quota_bytes" : 2199023255552,
         "storageset_id" : 1,
         "storageset_name" : "Set 1"
      },
      {
         "quota_bytes" : 5497558138880,
         "storageset_id" : 3,
         "storageset_name" : "Set 3"
      }
   ],
   "total" : 2
}

GET /api/v1/tenants/{tenant_id}/storagesets/{storageset_id}

Get tenant storageset

Returns a single storageset quota allocation for a tenant. Callers may only access their own tenant.

Authentication: required (PasswordLogin or BearerJWT).

Parameters

Name In Type Required Description
tenant_id path string (uuid) yes Tenant identifier (UUID)
storageset_id path integer yes StorageSet identifier

Responses

Status Description Schema
200 Successfully retrieved the tenant storageset quota allocation. GetTenantStorageSetResponse
400 Bad request. Invalid tenant_id parameter. -
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant or storageset not found. -
422 Validation error. -
500 Internal server error. -

Response Body (200, GetTenantStorageSetResponse)

Field Type Required Default Example Description
storageset StorageSetAssignment object yes n/a Storageset assignment (id + quota + name).

Example

{
   "storageset" : {
      "quota_bytes" : 2199023255552,
      "storageset_id" : 1,
      "storageset_name" : "Set 1"
   }
}

PUT /api/v1/tenants/{tenant_id}/storagesets/{storageset_id}

Assign or resize tenant storageset

Upserts a storageset quota allocation for a tenant: assigns the storageset with the given quota if it is not yet assigned, or replaces the quota if it already is. The combined cross-tenant quota must fit within the storageset capacity. Only platform-admin and storage-admin may change tenant storageset quotas, for any tenant; a Tenant Admin gets 403.

Authentication: required (PasswordLogin or BearerJWT).

Parameters

Name In Type Required Description
tenant_id path string (uuid) yes Tenant identifier (UUID)
storageset_id path integer yes StorageSet identifier

Request Body (application/json, required)

Schema: TenantStorageSetQuotaRequest

Request body for assigning or resizing a tenant storageset quota.

Field Type Required Default Example Description
quota_bytes integer yes n/a 2199023255552, 5497558138880 Maximum storage quota in bytes that the tenant can consume within this storageset.

Example

{
   "quota_bytes" : 2199023255552
}

Responses

Status Description Schema
200 Storageset assigned to the tenant, or its quota updated. Returns the resulting allocation. GetTenantStorageSetResponse
400 Bad request. The requested quota exceeds the storageset capacity. -
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant or storageset not found. -
422 Validation error. Returned for an invalid request body or path parameter. -
500 Internal server error. -

Response Body (200, GetTenantStorageSetResponse)

Field Type Required Default Example Description
storageset StorageSetAssignment object yes n/a Storageset assignment (id + quota + name).

Example

{
   "storageset" : {
      "quota_bytes" : 2199023255552,
      "storageset_id" : 1,
      "storageset_name" : "Set 1"
   }
}

DELETE /api/v1/tenants/{tenant_id}/storagesets/{storageset_id}

Unassign tenant storageset

Unassigns a storageset from a tenant. Callers may only modify their own tenant.

Authentication: required (PasswordLogin or BearerJWT).

Parameters

Name In Type Required Description
tenant_id path string (uuid) yes Tenant identifier (UUID)
storageset_id path integer yes StorageSet identifier

Responses

Status Description Schema
204 Storageset unassigned from the tenant successfully. No content is returned. -
401 Unauthorized. Authentication required. -
403 Forbidden. Insufficient permissions. -
404 Tenant or storageset not found. -
422 Validation Error HTTPValidationError
500 Internal server error. -