Skip to content
POST /tenant/bulk

Request Body

environment_idstring · uuid

Environment to create the tenants in. Required for session auth; ignored for API tokens. Applied to every row in the batch — the endpoint does not let you mix environments in one request.

Example: 8a2b104d-74a6-47f2-b93e-c6b611e82391
tenantsobject[]

The list of tenants to create. Max 1000 per request — split larger inputs client-side.

idstring

URL-path-safe tenant id. Must match ^[A-Za-z0-9._:@+-]{1,255}$.

Example: acme-corp
metadataRecord<string, any>

Free-form JSON object.

Example: {"tier":"gold"}
namestring

Display name. Defaults to id when omitted.

Example: Acme Corp

Response Body

createdobject[]

The tenants that were successfully inserted.

created_atstring · date-time

The date and time when the tenant was created.

Example: 2026-07-02T09:14:03.117Z
environment_idstring · uuid

The environment this tenant belongs to.

Example: 8a2b104d-74a6-47f2-b93e-c6b611e82391
idstring

The tenant identifier — caller-chosen, URL-path-safe, and immutable once created. Composite primary key with environment_id, so the same value can exist independently in development, staging, and production. Must match ^[A-Za-z0-9._:@+-]{1,255}$.

Example: acme-corp
metadataRecord<string, any>

Free-form JSON object stored verbatim. Truto does not interpret this field — use it for tier, region, billing plan, or any other customer attribute your app cares about.

Example: {"tier":"gold","region":"wnam"}
namestring

Display name shown in the dashboard. Defaults to the tenant id on create if not supplied; can be edited later via PATCH /tenant/{id}.

Example: Acme Corp
updated_atstring · date-time

The date and time when the tenant was last updated.

Example: 2026-07-02T09:14:03.117Z
skippedobject[]

Rows that were not inserted because a tenant with the same (id, environment_id) already existed. The endpoint uses INSERT ... ON CONFLICT DO NOTHING, so re-running the same bulk request is safe and idempotent.

idstring

The tenant id that was skipped.

Example: acme-corp
reasonstring

Why the row was skipped.

Example: already_exists
Possible values:
already_exists
curl -X POST 'https://api.truto.one/tenant/bulk' \
  -H 'Authorization: Bearer <your_api_token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "tenants": [],
  "environment_id": "8a2b104d-74a6-47f2-b93e-c6b611e82391"
}'
const body = {
  "tenants": [],
  "environment_id": "8a2b104d-74a6-47f2-b93e-c6b611e82391"
};

const response = await fetch('https://api.truto.one/tenant/bulk', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer <your_api_token>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(body),
});

const data = await response.json();
console.log(data);
import requests

url = "https://api.truto.one/tenant/bulk"
headers = {
    "Authorization": "Bearer <your_api_token>",
    "Content-Type": "application/json",
}
params = {
}
payload = {
    "tenants": [],
    "environment_id": "8a2b104d-74a6-47f2-b93e-c6b611e82391"
}

response = requests.post(url, headers=headers, params=params, json=payload)
print(response.json())