跳到主要内容

Automate tenant management

You can manage Logto Cloud tenants programmatically, including creating tenants and continuing configuration without switching to Console.

This is useful when you need to provision tenants from your own onboarding flow, internal platform, AI agent, or integration automation.

The automation flow is:

  1. Use a Logto Cloud Personal Access Token (PAT) to call the Logto Cloud API.
  2. Create a tenant with POST /api/tenants.
  3. Read the default Machine-to-machine (M2M) application credentials from the creation response.
  4. Use the default M2M application to get a Management API access token for the new tenant.
  5. Call the new tenant's Management API to continue provisioning applications, users, roles, resources, organizations, and other settings.

Before you start

Prepare the following values:

VariableDescription
CLOUD_API_ENDPOINTThe Logto Cloud API endpoint. For Logto Cloud, use https://cloud.logto.io.
LOGTO_CLOUD_PATA PAT for your Logto Cloud account.
TENANT_NAMEThe display name of the tenant to create.
TENANT_TAGThe tenant type. Use development or production.
REGION_NAMEThe region identifier for the tenant.

Set them as environment variables:

export CLOUD_API_ENDPOINT="https://cloud.logto.io"
export LOGTO_CLOUD_PAT="<logto-cloud-pat>"
export TENANT_NAME="My automated tenant"
export TENANT_TAG="development"
export REGION_NAME="<region-name>"

Get available regions

Before creating a tenant, fetch the regions available to your Logto Cloud account:

curl "$CLOUD_API_ENDPOINT/api/me/regions" \
-H "Authorization: Bearer $LOGTO_CLOUD_PAT"

The response contains the available regions. Use the name value as REGION_NAME when creating the tenant.

Example response:

{
"regions": [
{
"name": "EU",
"displayName": "Europe"
},
{
"name": "US",
"displayName": "United States"
}
]
}

Create a tenant

Call POST /api/tenants with the Logto Cloud PAT:

curl "$CLOUD_API_ENDPOINT/api/tenants" \
-X POST \
-H "Authorization: Bearer $LOGTO_CLOUD_PAT" \
-H "Content-Type: application/json" \
-d '{
"name": "'"$TENANT_NAME"'",
"tag": "'"$TENANT_TAG"'",
"regionName": "'"$REGION_NAME"'"
}'

The response includes the created tenant and a default M2M application. The M2M application is created in the new tenant and has access to the tenant's Management API.

Example response:

{
"id": "new-tenant-id",
"name": "My automated tenant",
"tag": "development",
"indicator": "https://new-tenant-id.logto.app",
"regionName": "EU",
"defaultApplication": {
"id": "default-m2m-app-id",
"secret": "default-m2m-app-secret"
}
}

Save the values you need for the next step:

export TENANT_ID="<response.id>"
export TENANT_ENDPOINT="<response.indicator>"
export DEFAULT_M2M_APP_ID="<response.defaultApplication.id>"
export DEFAULT_M2M_APP_SECRET="<response.defaultApplication.secret>"

Get a Management API access token for the new tenant

Use the default M2M application credentials to request an access token from the new tenant:

curl "$TENANT_ENDPOINT/oidc/token" \
-X POST \
-u "$DEFAULT_M2M_APP_ID:$DEFAULT_M2M_APP_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "resource=$TENANT_ENDPOINT/api" \
-d "scope=all"

Example response:

{
"access_token": "eyJ...",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "all"
}

Save the access token:

export MANAGEMENT_API_ACCESS_TOKEN="<response.access_token>"

Continue provisioning the new tenant

Use the Management API access token to call the new tenant's Management API.

For example, list applications:

curl "$TENANT_ENDPOINT/api/applications" \
-H "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN"

Or create an application:

curl "$TENANT_ENDPOINT/api/applications" \
-X POST \
-H "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My web app",
"type": "SPA",
"oidcClientMetadata": {
"redirectUris": ["https://example.com/callback"],
"postLogoutRedirectUris": ["https://example.com"]
}
}'

At this point, your automation can continue with any Management API operation, such as creating users, applications, API resources, roles, organizations, connectors, or sign-in experience settings.

Full automation example

The following Node.js example creates a tenant, exchanges the returned default M2M credentials for a Management API access token, and lists applications in the new tenant:

const cloudApiEndpoint = 'https://cloud.logto.io';
const logtoCloudPat = process.env.LOGTO_CLOUD_PAT;

const createTenantResponse = await fetch(`${cloudApiEndpoint}/api/tenants`, {
method: 'POST',
headers: {
authorization: `Bearer ${logtoCloudPat}`,
'content-type': 'application/json',
},
body: JSON.stringify({
name: 'My automated tenant',
tag: 'development',
regionName: 'EU',
}),
});

if (!createTenantResponse.ok) {
throw new Error(`Failed to create tenant: ${await createTenantResponse.text()}`);
}

const tenant = await createTenantResponse.json();
const tenantEndpoint = tenant.indicator;
const { id: appId, secret: appSecret } = tenant.defaultApplication;

const tokenResponse = await fetch(`${tenantEndpoint}/oidc/token`, {
method: 'POST',
headers: {
authorization: `Basic ${Buffer.from(`${appId}:${appSecret}`).toString('base64')}`,
'content-type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
resource: `${tenantEndpoint}/api`,
scope: 'all',
}),
});

if (!tokenResponse.ok) {
throw new Error(`Failed to get Management API token: ${await tokenResponse.text()}`);
}

const { access_token: managementApiAccessToken } = await tokenResponse.json();

const applicationsResponse = await fetch(`${tenantEndpoint}/api/applications`, {
headers: {
authorization: `Bearer ${managementApiAccessToken}`,
},
});

if (!applicationsResponse.ok) {
throw new Error(`Failed to list applications: ${await applicationsResponse.text()}`);
}

const applications = await applicationsResponse.json();

console.log({ tenantId: tenant.id, applications });