Comprehensive guide to View's tenant management system, including multi-tenant configuration, virtual deployments, and tenant isolation within the View platform.
Overview
The View Tenant management system provides comprehensive multi-tenant configuration capabilities, allowing you to create and manage separate virtual deployments within the same physical infrastructure. Tenants provide complete data isolation, ensuring that users in one tenant have no access rights to data in another tenant, while sharing the same underlying infrastructure resources.
Key Features
- Multi-Tenant Architecture: Configure separate virtual deployments within the same physical deployment
- Complete Data Isolation: Strict tenant boundaries ensure no cross-tenant data access
- Regional Configuration: Configure tenants for specific geographic regions
- Domain Management: Set up custom S3 and REST API domains for each tenant
- Storage Pool Integration: Associate tenants with default storage pools for data management
- Active/Inactive States: Control tenant availability and access
- Protection Controls: Mark tenants as protected to prevent accidental modification
- Administrative Control: Full administrative access for tenant management
Supported Operations
- Create: Create new tenant configurations with regional and domain settings
- Read: Retrieve individual tenant configurations and metadata
- Enumerate: List all tenants with pagination support
- Update: Modify existing tenant configurations
- Delete: Remove tenant configurations from the system
- Existence Check: Verify tenant presence without retrieving details
API Endpoints
Tenants are managed via the Configuration server API at [http|https]://[hostname]:[port]/v1.0/tenants
Supported HTTP Methods: GET
, HEAD
, PUT
, DELETE
Important: All tenant operations require administrator-level access tokens.
Tenant Object Structure
Tenant objects contain comprehensive configuration for multi-tenant deployments and virtual infrastructure. Here's the complete structure:
{
"GUID": "00000000-0000-0000-0000-000000000000",
"AccountGUID": "00000000-0000-0000-0000-000000000000",
"DefaultPoolGUID": "00000000-0000-0000-0000-000000000000",
"Name": "Default Tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"Active": true,
"IsProtected": true,
"CreatedUtc": "2025-03-23T07:57:38.758241Z"
}
Field Descriptions
- GUID (GUID): Globally unique identifier for the tenant object
- AccountGUID (GUID): Globally unique identifier for the associated account
- DefaultPoolGUID (GUID): Default storage pool's unique identifier for the tenant
- Name (string): Display name for the tenant
- Region (string): S3 region string for geographic configuration
- S3BaseDomain (string): Hostname on which View should listen for S3 requests for this tenant
- RestBaseDomain (string): Hostname on which View should listen for REST storage requests for this tenant
- Active (boolean): Indicates whether the tenant is considered active and able to be used
- IsProtected (boolean): Indicates whether the tenant is protected from modification
- CreatedUtc (datetime): UTC timestamp when the tenant was created
Create Tenant
Creates a new tenant configuration using PUT /v1.0/tenants
. This endpoint allows you to configure a new virtual deployment with regional settings, domain configuration, and storage pool association.
Request Parameters
Required Parameters
- Name (string, Body, Required): Display name for the tenant
- Region (string, Body, Required): S3 region string for geographic configuration
- S3BaseDomain (string, Body, Required): Hostname for S3 requests for this tenant
- RestBaseDomain (string, Body, Required): Hostname for REST storage requests for this tenant
Optional Parameters
- DefaultPoolGUID (GUID, Body, Optional): Default storage pool GUID for the tenant (can be set to null)
Important Notes
- DefaultPoolGUID: Can be set to
null
when creating. It is recommended that after creating a tenant, you create its storage pool, and update the tenant object with the storage pool's GUID - Administrator Access: This operation requires administrator-level authentication tokens
- Domain Configuration: Ensure proper DNS configuration for the specified domains
curl -X PUT http://localhost:8000/v1.0/tenants \
-H "Content-Type: application/json" \
-H "x-token: [accesToken]
-d '
{
"Name": "My tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"DefaultPoolGUID": "df6c9117-a1ea-44ca-bddc-fa7a3d932fe9"
}'
import { ViewConfigurationSdk } from "view-sdk";
const api = new ViewConfigurationSdk(
'http://localhost:8000/', //endpoint
'default', //tenant Id
'default', //access key
);
api.accessToken = "<adminToken>" //This API requires Admin access
const createTenant = async () => {
try {
const createdTenant = await api.Tenant.create(
{
Name: 'My tenant',
Region: 'us-west-1',
S3BaseDomain: 'localhost',
RestBaseDomain: 'localhost',
DefaultPoolGUID: '<pool-guid>',
}
);
console.log(createdTenant, 'Tenant created successfully');
} catch (err) {
console.log('Error creating Tenant:', err);
}
};
createTenant();
import view_sdk
from view_sdk import configuration
from view_sdk.sdk_configuration import Service
sdk = view_sdk.configure(
access_key="default",
base_url="localhost",
tenant_guid="default",
service_ports={Service.DEFAULT: 8000},
)
def createTenant():
tenant = configuration.Tenant.create(
headers={
"x-token": "adminToken" },
AccountGUID="account-guid",
Name="My tenant",
DefaultPoolGUID="pool-guid",
S3BaseDomain="localhost",
RestBaseDomain="localhost",
)
print(tenant)
createTenant()
using View.Sdk;
using View.Sdk.Configuration;
ViewConfigurationSdk sdk = new ViewConfigurationSdk(Guid.Parse("00000000-0000-0000-0000-000000000000"),"default", "http://view.homedns.org:8000/");
TenantMetadata request = new TenantMetadata()
{
AccountGUID = "default",
Name = "My tenant",
DefaultPoolGUID = "default",
S3BaseDomain = "localhost",
RestBaseDomain = "localhost"
};
sdk.XToken = "default"
await sdk.Tenant.Create(request);
Response
Returns the created tenant object with all configuration details:
{
"GUID": "00000000-0000-0000-0000-000000000000",
"AccountGUID": "00000000-0000-0000-0000-000000000000",
"DefaultPoolGUID": "00000000-0000-0000-0000-000000000000",
"Name": "My tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"Active": true,
"IsProtected": false,
"CreatedUtc": "2025-03-23T07:57:38.758241Z"
}
Enumerate Tenants
Retrieves a paginated list of all tenant objects in the system using GET /v2.0/tenants
. This endpoint provides comprehensive enumeration with pagination support for managing multiple tenant configurations.
The enumeration response includes pagination metadata and tenant objects:
Request Parameters
No additional parameters required beyond authentication.
curl --location --head 'http://view.homedns.org:8000/v1.0/tenants/00000000-0000-0000-0000-000000000000' \
--header 'Authorization: ••••••'
import { ViewConfigurationSdk } from "view-sdk";
const api = new ViewConfigurationSdk(
"http://localhost:8000/", //endpoint
"default", //tenant Id
"default", //access key
);
api.accessToken = "<adminToken>" //This API requires Admin access
export const enumerateTenant = async () => {
try {
const tenants = await api.Tenant.enumerate();
console.log(tenants, "Tenants fetched successfully");
} catch (err) {
console.log("Error fetching Tenants:", err);
}
};
enumerateTenant();
import view_sdk
from view_sdk import configuration
from view_sdk.sdk_configuration import Service
sdk = view_sdk.configure(
access_key="default",
base_url="localhost",
tenant_guid="default",
service_ports={Service.DEFAULT: 8000},
)
def enumerateTenants():
tenants = configuration.Tenant.enumerate( headers={"x-token":"<adminToken>"})
print(tenants)
enumerateTenants()
using View.Sdk;
using View.Sdk.Configuration;
ViewConfigurationSdk sdk = new ViewConfigurationSdk(Guid.Parse("00000000-0000-0000-0000-000000000000"),"default", "http://view.homedns.org:8000/");
sdk.XToken = "default"
EnumerationResult<TenantMetadata> response = await sdk.Tenant.Enumerate()
Response
Returns a paginated list of tenant objects:
{
"Success": true,
"Timestamp": {
"Start": "2024-10-21T02:36:37.677751Z",
"TotalMs": 23.58,
"Messages": {}
},
"MaxResults": 10,
"IterationsRequired": 1,
"EndOfResults": true,
"RecordsRemaining": 0,
"Objects": [
{
"GUID": "00000000-0000-0000-0000-000000000000",
"AccountGUID": "00000000-0000-0000-0000-000000000000",
"DefaultPoolGUID": "00000000-0000-0000-0000-000000000000",
"Name": "Default Tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"Active": true,
"IsProtected": true,
"CreatedUtc": "2025-03-23T07:57:38.758241Z"
}
],
"ContinuationToken": null
}
Read Tenant
Retrieves tenant configuration and metadata by GUID using GET /v1.0/tenants/[tenant-guid]
. Returns the complete tenant configuration including all properties and metadata. If the tenant doesn't exist, a 404 error is returned.
Request Parameters
- tenant-guid (string, Path, Required): GUID of the tenant object to retrieve
curl --location 'http://view.homedns.org:8000/v1.0/tenants/00000000-0000-0000-0000-000000000000' \
--header 'Authorization: Bearer ******'
import { ViewConfigurationSdk } from "view-sdk";
const api = new ViewConfigurationSdk(
'http://localhost:8000/', //endpoint
'default', //tenant Id
'default', //access key
);
const retrieveTenantById = async () => {
try {
const tenant = await api.Tenant.read('<tenant-guid>');
console.log(tenant);
} catch (err) {
console.log('err: ', err);
}
};
retrieveTenantById();
import view_sdk
from view_sdk import configuration
from view_sdk.sdk_configuration import Service
sdk = view_sdk.configure(
access_key="default",
base_url="localhost",
tenant_guid="default",
service_ports={Service.DEFAULT: 8000},
)
def readTenant():
tenant = configuration.Tenant.retrieve("tenant-guid",headers={"x-token":"<adminToken>"})
print(tenant)
readTenant()
using View.Sdk;
using View.Sdk.Configuration;
ViewConfigurationSdk sdk = new ViewConfigurationSdk(Guid.Parse("00000000-0000-0000-0000-000000000000"),"default", "http://view.homedns.org:8000/");
sdk.TenantGUID = "default";
TenantMetadata response = await sdk.Tenant.Retrieve();
Console.WriteLine(response);
Response
Returns the complete tenant configuration:
{
"GUID": "default",
"AccountGUID": "00000000-0000-0000-0000-000000000000",
"DefaultPoolGUID": "default",
"Name": "Default Tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"Active": true,
"IsProtected": true,
"CreatedUtc": "2024-07-10T05:09:31.000000Z"
}
Note: the HEAD
method can be used as an alternative to get to simply check the existence of the object. HEAD
requests return either a 200/OK
in the event the object exists, or a 404/Not Found
if not. No response body is returned with a HEAD
request.
Read All Tenants
Retrieves all tenant objects in the system using GET /v1.0/tenants/
. Returns an array of tenant objects with complete configuration details for all tenants in the system.
Request Parameters
No additional parameters required beyond authentication.
curl --location 'http://view.homedns.org:8000/v1.0/tenants/' \
--header 'Authorization: ••••••'
import { ViewConfigurationSdk } from "view-sdk";
const api = new ViewConfigurationSdk(
"http://localhost:8000/", //endpoint
"default", //tenant Id
"default", //access key
);
api.accessToken = "<adminToken>" //This API requires Admin access
const fetchTenant = async () => {
try {
const tenants = await api.Tenant.readAll();
console.log(tenants, "Tenant fetched successfully");
} catch (err) {
console.log("Error fetching Tenant:", err);
}
};
fetchTenant();
import view_sdk
from view_sdk import configuration
from view_sdk.sdk_configuration import Service
sdk = view_sdk.configure(
access_key="default",
base_url="localhost",
tenant_guid="default",
service_ports={Service.DEFAULT: 8000},
)
def readAllTenants():
tenants = configuration.Tenant.retrieve_all(headers={"x-token":"<adminToken>"})
print(tenants)
readAllTenants()
using View.Sdk;
using View.Sdk.Configuration;
ViewConfigurationSdk sdk = new ViewConfigurationSdk(Guid.Parse("00000000-0000-0000-0000-000000000000"),"default", "http://view.homedns.org:8000/");
sdk.XToken = "default"
List<TenantMetadata> response = await sdk.Tenant.RetrieveMany()
Response
Returns an array of all tenant objects:
[
{
"GUID": "00000000-0000-0000-0000-000000000000",
"AccountGUID": "00000000-0000-0000-0000-000000000000",
"DefaultPoolGUID": "00000000-0000-0000-0000-000000000000",
"Name": "Default Tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"Active": true,
"IsProtected": true,
"CreatedUtc": "2025-03-23T07:57:38.758241Z"
},
{
"GUID": "11111111-1111-1111-1111-111111111111",
"AccountGUID": "00000000-0000-0000-0000-000000000000",
"DefaultPoolGUID": "22222222-2222-2222-2222-222222222222",
"Name": "Production Tenant",
"Region": "us-east-1",
"S3BaseDomain": "prod.example.com",
"RestBaseDomain": "api.prod.example.com",
"Active": true,
"IsProtected": false,
"CreatedUtc": "2025-03-24T10:15:30.123456Z"
}
]
Update Tenant
Updates an existing tenant configuration using PUT /v1.0/tenants/[tenant-guid]
. This endpoint allows you to modify tenant parameters while preserving certain immutable fields.
Request Parameters
- tenant-guid (string, Path, Required): GUID of the tenant object to update
Updateable Fields
All configuration parameters can be updated except for:
- GUID: Immutable identifier
- CreatedUtc: Immutable creation timestamp
Important Notes
- Field Preservation: Certain fields cannot be modified and will be preserved across updates
- Complete Object: Provide a fully populated object in the request body
- Validation: All updated parameters will be validated before applying changes
Request body:
curl --location --request PUT 'http://view.homedns.org:8000/v1.0/tenants/00000000-0000-0000-0000-000000000000' \
--header 'content-type: application/json' \
--header 'Authorization: ••••••' \
--data '{
"Name": "Updated Tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"DefaultPoolGUID": "00000000-0000-0000-0000-000000000000"
}'
import { ViewConfigurationSdk } from "view-sdk";
const api = new ViewConfigurationSdk(
'http://localhost:8000/', //endpoint
'default', //tenant Id
'default' //access key
);
api.accessToken = "<adminToken>" //This API requires Admin access
const updateTenant = async () => {
// tenant object to update
try {
const updatedTenant = await api.Tenant.update({
GUID: '<tenant-guid>',
AccountGUID: '<account-guid>',
DefaultPoolGUID: '<pool-guid>',
Name: 'Default Tenant123',
Region: 'us-west-1',
S3BaseDomain: 'localhost',
RestBaseDomain: 'localhost',
Active: true,
IsProtected: true,
CreatedUtc: '2025-06-09T17:59:30.333249Z',
});
console.log(updatedTenant, 'Tenant updated successfully');
} catch (err) {
console.log('Error updating Tenant:', err);
}
};
updateTenant();
import view_sdk
from view_sdk import configuration
from view_sdk.sdk_configuration import Service
sdk = view_sdk.configure(
access_key="default",
base_url="localhost",
tenant_guid="default",
service_ports={Service.DEFAULT: 8000},
)
def updateTenant():
tenant = configuration.Tenant.update("tenant-guid",headers={"x-token":"<adminToken>"},
data={
"AccountGUID": "account-guid",
"DefaultPoolGUID": "poll-guid",
"Name": "My Updated Tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"Active": True,
"IsProtected": False,
"CreatedUtc": "2025-05-05T10:07:59.000503Z"
}
)
print(tenant)
updateTenant()
using View.Sdk;
using View.Sdk.Configuration;
ViewConfigurationSdk sdk = new ViewConfigurationSdk(Guid.Parse("00000000-0000-0000-0000-000000000000"),"default", "http://view.homedns.org:8000/");
TenantMetadata request = new TenantMetadata()
{
GUID = Guid.Parse("<tenant-guid>"),
Name = "My tenant",
DefaultPoolGUID = "default",
S3BaseDomain = "localhost",
RestBaseDomain = "localhost"
};
sdk.XToken = "default"
await sdk.Tenant.Update(request);
Response
Returns the updated tenant object with all configuration details:
{
"GUID": "default",
"AccountGUID": "00000000-0000-0000-0000-000000000000",
"DefaultPoolGUID": "default",
"Name": "My Updated Tenant",
"Region": "us-west-1",
"S3BaseDomain": "localhost",
"RestBaseDomain": "localhost",
"Active": true,
"IsProtected": false,
"CreatedUtc": "2024-07-10T05:09:31.000000Z"
}
Delete Tenant
Deletes a tenant object by GUID using DELETE /v1.0/tenants/[tenant-guid]
. This operation permanently removes the tenant configuration from the system. Use with caution as this action cannot be undone.
Important Note: Deletion of a tenant does not delete subordinate data, as it may be preferred to retain it for later use. If you wish to entirely delete a tenant, delete subordinate data as described by other APIs.
Request Parameters
- tenant-guid (string, Path, Required): GUID of the tenant object to delete
curl --location --request DELETE 'http://view.homedns.org:8000/v1.0/tenants/00000000-0000-0000-0000-000000000000' \--header 'Authorization: ••••••' \--data ''
import { ViewConfigurationSdk } from "view-sdk";
const api = new ViewConfigurationSdk(
"http://localhost:8000/", //endpoint
"default", //tenant Id
"default" //access key
);
api.accessToken = "<adminToken>" //This API requires Admin access
const deleteTenant = async () => {
try {
await api.Tenant.delete("<tenantGUID>");
console.log("Tenant deleted successfully");
} catch (err) {
console.log("Error deleting Tenant:", err);
}
};
import view_sdk
from view_sdk import configuration
from view_sdk.sdk_configuration import Service
sdk = view_sdk.configure(
access_key="default",
base_url="localhost",
tenant_guid="default",
service_ports={Service.DEFAULT: 8000},
)
def deleteTenant():
tenant = configuration.Tenant.delete("tenant-guid",headers={"x-token":"<adminToken>"})
print(tenant)
deleteTenant()
using View.Sdk;
using View.Sdk.Configuration;
ViewConfigurationSdk sdk = new ViewConfigurationSdk(Guid.Parse("00000000-0000-0000-0000-000000000000"),"default", "http://view.homedns.org:8000/");
sdk.XToken = "default"
await sdk.Tenant.Delete(Guid.Parse("tenant-guid"));
Response
Returns 204 No Content on successful deletion. No response body is returned.
Check Tenant Existence
Verifies if a tenant object exists without retrieving its configuration using HEAD /v1.0/tenants/[tenant-guid]
. This is an efficient way to check tenant presence before performing operations.
Request Parameters
- tenant-guid (string, Path, Required): GUID of the tenant object to check
curl --location --head 'http://view.homedns.org:8000/v1.0/tenants/00000000-0000-0000-0000-000000000000' \
--header 'Authorization: ••••••'
import { ViewConfigurationSdk } from "view-sdk";
const api = new ViewConfigurationSdk(
"http://view.homedns.org:8000/", //endpoint
"default", //tenant Id
"default" //access token
);
api.accessToken = "<adminToken>" //This API requires Admin access
export const tenantExists = async () => {
try {
const tenant = await api.Tenant.exists(
"<tenant-guid>"
);
console.log(tenant, "Tenant exists"); //true
} catch (err) {
console.log("Error fetching Tenant:", err);
}
};
tenantExists();
import view_sdk
from view_sdk import configuration
from view_sdk.sdk_configuration import Service
sdk = view_sdk.configure(
access_key="default",
base_url="localhost",
tenant_guid="default",
service_ports={Service.DEFAULT: 8000},
)
def existTenant():
tenant = configuration.Tenant.exists("tenant-guid",headers={"x-token":"<adminToken>"})
print(tenant)
existTenant()
using View.Sdk;
using View.Sdk.Configuration;
ViewConfigurationSdk sdk = new ViewConfigurationSdk(Guid.Parse("00000000-0000-0000-0000-000000000000"),"default", "http://view.homedns.org:8000/");
bool isExists = await sdk.Tenant.Exists(Guid.Parse("tenant-guid"));
Response
- 200 No Content: Tenant exists
- 404 Not Found: Tenant does not exist
- No response body: Only HTTP status code is returned
Note: HEAD requests do not return a response body, only the HTTP status code indicating whether the tenant exists.
Best Practices
When managing tenants in the View platform, consider the following recommendations for optimal multi-tenant configuration:
- Administrator Access: Ensure all tenant operations use administrator-level authentication tokens
- Domain Configuration: Properly configure DNS settings for S3BaseDomain and RestBaseDomain
- Storage Pool Management: Create storage pools before or immediately after tenant creation
- Regional Planning: Configure appropriate regions for geographic distribution and compliance
- Data Isolation: Leverage tenant isolation for secure multi-tenant deployments
Next Steps
After successfully managing tenants, you can:
- Multi-Tenant Applications: Implement applications that leverage tenant isolation for secure data separation
- Regional Deployment: Configure tenants across different geographic regions for global distribution
- Storage Management: Create and manage storage pools for tenant-specific data storage
- User Management: Implement user authentication and authorization within tenant boundaries
- Integration: Integrate tenant management with other View platform services and APIs