Tenants

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