If you wish to learn more about Tenants in general, visit our section on Tenant Management.
The Descope service supports multi-tenancy architecture natively. Each project can have multiple tenants, and the end-users can be assigned to either the project or can belong to one or many tenants.
The most common use case of tenants is when you are building a B2B application, and each of your customers can have multiple users. You must manage these users and their roles at a tenant level.
Descope admins can create and update tenants either manually in the Descope console or using the tenant management API and sdk from within their application as show below.
import DescopeClient from '@descope/node-sdk';const managementKey = "xxxx"try{ // baseUrl="<URL>" // When initializing the Descope clientyou can also configure the baseUrl ex: https://auth.company.com - this is useful when you utilize CNAME within your Descope project. const descopeClient = DescopeClient({ projectId: '__ProjectID__', managementKey: managementKey });} catch (error) { // handle the error console.log("failed to initialize: " + error)}// Note that you can handle async operation failures and capture specific errors to customize errors.// An example can be found here: https://github.com/descope/node-sdk?tab=readme-ov-file#error-handling
This function allows for you to search Descope tenants by ID, name, self service provisioning domain,
and custom attributes.
// Args:// ids (String[]): Array of tenant IDs to search for.const ids = ["TestTenant"]// names (String[]): Array of tenant names to search for.const names = ["TestTenant"]// selfProvisioningDomains (String[]): Array of self service provisioning domains to search for.const selfProvisioningDomains = ["example.com", "company.com"]// customAttributes (String[]): Array of self service provisioning domains to search for.const customAttributes = {"mycustomattribute": "Test"}// When searching based on one of these items or a few of these items, leave the applicable items you are not searching for to null.let resp = await descopeClient.management.tenant.searchAll(ids, names, selfProvisioningDomains, customAttributes);if (!resp.ok) { console.log("Failed to search tenants.") console.log("Status Code: " + resp.code) console.log("Error Code: " + resp.error.errorCode) console.log("Error Description: " + resp.error.errorDescription) console.log("Error Message: " + resp.error.errorMessage)}else { console.log("Successfully searched tenants.") resp.data.forEach((tenant) => { console.log(tenant) });}
At the time of creation, the tenant must be given a name and a tenant-id. If you don't provide a tenant-id, a tenant-id is automatically generated. The tenant-id is used for sign-up/sign-in and other management
operations later. In addition, you can also set domains for the tenant. The domain is used to automatically assign the end-user to a tenant at the time of sign-up and sign-in. The tenant name must be unique per
project. The tenant ID is generated automatically for the tenant when not provided.
// There are two ways to create a tenant via SDK. createWithId (which will assign the given id) and create (which will automatically generate the id). Examples below:// createWithId: Create a new tenant with a given name and tenant id.// ==================================================================// Args:// name (str): The tenant's namevar name = "TestTenantCreateWithId"// id (str): The tenant's id.var id = "TestConfiguredId"// selfProvisioningDomains (List[str]): An optional list of domains that are associated with this tenant. Users authenticating from these domains will be associated with this tenant.var selfProvisioningDomains = ["TestDomain1.com", "TestDomain2.com"]// customAttributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console appconst customAttributes = {"attribute1": "Value 1", "attribute2": "Value 2"}let resp = await descopeClient.management.tenant.createWithId(id, name, selfProvisioningDomains, customAttributes)if (!resp.ok) { console.log(resp) console.log("Unable to create tenant.") console.log("Status Code: " + resp.code) console.log("Error Code: " + resp.error.errorCode) console.log("Error Description: " + resp.error.errorDescription) console.log("Error Message: " + resp.error.errorMessage)}else { console.log("Successfully created tenant.") console.log(resp.data)}// Create: Create a new tenant with the given name. The id will be automatically generated and returned.// ==================================================================// Args:// name (str): The tenant's namename = "TestTenantCreateGeneratedId"// selfProvisioningDomains (List[str]): An optional list of domains that are associated with this tenant. Users authenticating from these domains will be associated with this tenant.selfProvisioningDomains = ["TestDomain3.com", "TestDomain4.com"]// customAttributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console appconst customAttributes = {"attribute1": "Value 1", "attribute2": "Value 2"}resp = await descopeClient.management.tenant.create(name, selfProvisioningDomains, customAttributes)if (!resp.ok) { console.log("Unable to create tenant.") console.log("Status Code: " + resp.code) console.log("Error Code: " + resp.error.errorCode) console.log("Error Description: " + resp.error.errorDescription) console.log("Error Message: " + resp.error.errorMessage)}else { console.log("Successfully created tenant.") console.log(resp.data)}
Use the code below to update an existing tenant with the given name and domains. All parameters are used as overrides to the existing tenant. Empty fields will override populated fields.
// Args:// id (str): The tenant's id.var id = "xxxxxx"// name (str): The tenant's namevar name = "Test Updated Name"// selfProvisioningDomains (List[str]): An optional list of domains that are associated with this tenant. Users authenticating from these domains will be associated with this tenant. If changed, it will be the new list of self provisioned domains.var selfProvisioningDomains = ["TestUpdatedDomain1.com", "TestUpdatedDomain2.com"]// customAttributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console appconst customAttributes = {"attribute1": "Value 1", "attribute2": "Value 2"}const resp = await descopeClient.management.tenant.update(id, name, selfProvisioningDomains, customAttributes);if (!resp.ok) { console.log(resp) console.log("Failed to update tenant.") console.log("Status Code: " + resp.code) console.log("Error Code: " + resp.error.errorCode) console.log("Error Description: " + resp.error.errorDescription) console.log("Error Message: " + resp.error.errorMessage)}else { console.log("Successfully update tenant.") console.log(resp.data)}