テナント管理
mindzieStudioプラットフォームでテナントの作成、一覧取得、取得、および更新を行います。
重要: このページのすべてのエンドポイントにはグローバルAPIキーが必要です。テナント固有のAPIキーを使用すると、401 Unauthorizedエラーが返されます。
すべてのテナントを一覧表示
GET /api/tenant
システム内のすべてのテナントのページネーションされたリストと概要統計を取得します。
クエリパラメータ
| パラメータ | タイプ | デフォルト | 説明 |
|---|---|---|---|
page |
integer | 1 | ページネーションのページ番号 |
pageSize |
integer | 50 | 1ページあたりのアイテム数(最大100) |
レスポンス (200 OK)
{
"tenants": [
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation",
"description": "Main tenant for Acme Corporation",
"caseCount": 50000,
"maxUserCount": 100,
"maxAnalystCount": 20,
"analystCount": 12,
"userCount": 45,
"preRelease": false,
"isAcademic": false,
"autoload": true,
"dateCreated": "2024-01-15T10:30:00Z",
"isDisabled": false
}
],
"totalCount": 5,
"page": 1,
"pageSize": 50
}
テナントオブジェクトのフィールド
| フィールド | タイプ | 説明 |
|---|---|---|
tenantId |
GUID | テナントの一意な識別子 |
name |
string | 一意のシステム名(URLで使用される) |
displayName |
string | 人間が読みやすい表示名 |
description |
string | テナントの説明 |
caseCount |
integer | すべてのデータセットにわたるケースの総数 |
maxUserCount |
integer | 最大許可ユーザー数 |
maxAnalystCount |
integer | 最大許可アナリスト数 |
analystCount |
integer | 現在のアナリスト数 |
userCount |
integer | 現在のユーザー数 |
preRelease |
boolean | テナントがプリリリース機能を持つかどうか |
isAcademic |
boolean | 学術用テナントかどうか |
autoload |
boolean | プロジェクトの自動読み込み設定 |
dateCreated |
datetime | テナントの作成日時 |
isDisabled |
boolean | テナントが無効化されているかどうか |
エラー応答
Unauthorized (401):
{
"error": "This endpoint requires a Global API key. Tenant-specific API keys cannot list all tenants.",
"hint": "Global API keys can be created at /admin/global-api-keys"
}
テナントをIDで取得
GET /api/tenant/{tenantId}
指定したIDのテナントの詳細情報を取得します。
パスパラメータ
| パラメータ | タイプ | 必須 | 説明 |
|---|---|---|---|
tenantId |
GUID | はい | テナントの一意な識別子 |
レスポンス (200 OK)
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation",
"description": "Main tenant for Acme Corporation",
"isAcademic": false,
"preRelease": false,
"maxUserCount": 100,
"maxAnalystCount": 20,
"maxCases": 100000,
"dateCreated": "2024-01-15T10:30:00Z",
"isDisabled": false
}
エラー応答
Not Found (404):
{
"error": "Tenant with ID '12345678-1234-1234-1234-123456789012' not found"
}
テナントを作成
POST /api/tenant
必要なインフラストラクチャすべてを含む、新しいテナントをシステムに作成します。
リクエストボディ
{
"name": "new-tenant",
"displayName": "New Tenant Corp",
"description": "Description of the new tenant",
"maxUsers": 50,
"maxAnalyst": 10,
"maxCases": 100000,
"timeZone": "America/New_York"
}
リクエストフィールド
| フィールド | タイプ | 必須 | 説明 |
|---|---|---|---|
name |
string | はい | 一意のシステム名(3~63文字、小文字の英数字とハイフンのみ) |
displayName |
string | はい | 人間が読みやすい表示名 |
description |
string | いいえ | テナントの説明 |
maxUsers |
integer | はい | 最大ユーザー数 |
maxAnalyst |
integer | はい | 最大アナリスト数 |
maxCases |
integer | はい | 最大ケース数 |
timeZone |
string | いいえ | テナントのタイムゾーン |
テナント名の要件
- 3~63文字
- 小文字の英数字およびハイフンのみ
- スペースや特殊文字は不可
- 全テナントで一意であること
レスポンス (201 Created)
{
"tenantId": "aabbccdd-1234-1234-1234-123456789012",
"name": "new-tenant",
"displayName": "New Tenant Corp",
"message": "Tenant 'New Tenant Corp' created successfully",
"storageContainerCreated": true
}
エラー応答
Conflict (409):
{
"error": "A tenant with name 'new-tenant' already exists"
}
License Limit (429):
{
"error": "Maximum number of tenants reached. Your license allows 10 tenants.",
"hint": "Upgrade your license to create more tenants"
}
Validation Error (400):
{
"error": "Validation failed",
"validationErrors": [
"Name must be between 3 and 63 characters",
"Name can only contain lowercase letters, numbers, and hyphens"
]
}
テナントを更新
PUT /api/tenant
既存のテナントのプロパティを更新します。指定されたフィールドのみが更新され、null値は無視されます。
リクエストボディ
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"displayName": "Acme Corporation Updated",
"description": "Updated description",
"maxUsers": 100,
"maxAnalyst": 25,
"maxCases": 200000,
"timeZone": "America/New_York",
"isAcademic": false,
"preRelease": true,
"isDisabled": false
}
リクエストフィールド
| フィールド | タイプ | 必須 | 説明 |
|---|---|---|---|
tenantId |
GUID | はい | 更新対象のテナント |
displayName |
string | いいえ | 新しい表示名(nullなら変更なし) |
description |
string | いいえ | 新しい説明(null=変更なし、""=クリア) |
maxUsers |
integer | いいえ | 最大ユーザー数(nullなら変更なし) |
maxAnalyst |
integer | いいえ | 最大アナリスト数(nullなら変更なし) |
maxCases |
integer | いいえ | 最大ケース数(null=変更なし、-1=無制限) |
timeZone |
string | いいえ | タイムゾーンID(nullなら変更なし) |
isAcademic |
boolean | いいえ | 学術用フラグ(nullなら変更なし) |
preRelease |
boolean | いいえ | プリリリース機能(nullなら変更なし) |
isDisabled |
boolean | いいえ | テナント無効化(nullなら変更なし) |
注意: 作成後はテナントの name を変更できません。
レスポンス (200 OK)
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation Updated",
"message": "Tenant 'acme-corp' updated successfully",
"isDisabled": false
}
エラー応答
Not Found (404):
{
"error": "Tenant with ID '12345678-1234-1234-1234-123456789012' not found"
}
Validation Error (400):
{
"error": "Validation failed",
"validationErrors": ["Display name cannot exceed 255 characters"]
}
実装例
cURL
# すべてのテナント一覧取得
curl -X GET "https://your-mindzie-instance.com/api/tenant?page=1&pageSize=50" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY"
# 特定のテナントをIDで取得
curl -X GET "https://your-mindzie-instance.com/api/tenant/12345678-1234-1234-1234-123456789012" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY"
# テナント作成
curl -X POST "https://your-mindzie-instance.com/api/tenant" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "new-tenant",
"displayName": "New Tenant Corp",
"description": "Test tenant",
"maxUsers": 50,
"maxAnalyst": 10,
"maxCases": 100000
}'
# テナント更新
curl -X PUT "https://your-mindzie-instance.com/api/tenant" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenantId": "12345678-1234-1234-1234-123456789012",
"displayName": "New Tenant Corp Updated",
"maxUsers": 100,
"isDisabled": false
}'
Python
import requests
BASE_URL = 'https://your-mindzie-instance.com'
class TenantManager:
def __init__(self, global_api_key):
"""グローバルAPIキー(テナント固有ではない)で初期化します。"""
self.headers = {
'Authorization': f'Bearer {global_api_key}',
'Content-Type': 'application/json'
}
def list_tenants(self, page=1, page_size=50):
"""システム内のすべてのテナントを一覧表示します。"""
url = f'{BASE_URL}/api/tenant'
params = {'page': page, 'pageSize': page_size}
response = requests.get(url, headers=self.headers, params=params)
response.raise_for_status()
return response.json()
def get_tenant(self, tenant_id):
"""指定したIDのテナントを取得します。"""
url = f'{BASE_URL}/api/tenant/{tenant_id}'
response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json()
def create_tenant(self, name, display_name, description='', max_users=50,
max_analyst=10, max_cases=100000, timezone=None):
"""新しいテナントを作成します。"""
url = f'{BASE_URL}/api/tenant'
payload = {
'name': name,
'displayName': display_name,
'description': description,
'maxUsers': max_users,
'maxAnalyst': max_analyst,
'maxCases': max_cases
}
if timezone:
payload['timeZone'] = timezone
response = requests.post(url, json=payload, headers=self.headers)
response.raise_for_status()
return response.json()
def update_tenant(self, tenant_id, display_name=None, description=None,
max_users=None, max_analyst=None, is_disabled=None):
"""既存のテナントを更新します。"""
url = f'{BASE_URL}/api/tenant'
payload = {'tenantId': tenant_id}
if display_name is not None:
payload['displayName'] = display_name
if description is not None:
payload['description'] = description
if max_users is not None:
payload['maxUsers'] = max_users
if max_analyst is not None:
payload['maxAnalyst'] = max_analyst
if is_disabled is not None:
payload['isDisabled'] = is_disabled
response = requests.put(url, json=payload, headers=self.headers)
response.raise_for_status()
return response.json()
# 使用例
manager = TenantManager('your-global-api-key')
# すべてのテナント一覧取得
result = manager.list_tenants()
print(f"テナント総数: {result['totalCount']}")
for tenant in result['tenants']:
print(f"- {tenant['displayName']} ({tenant['name']})")
print(f" ユーザー数: {tenant['userCount']}/{tenant['maxUserCount']}")
# 新しいテナント作成
new_tenant = manager.create_tenant(
name='test-tenant',
display_name='Test Tenant',
description='Created via API',
max_users=25,
max_analyst=5,
max_cases=50000
)
print(f"作成したテナントID: {new_tenant['tenantId']}")
# テナントの制限を更新
manager.update_tenant(
tenant_id=new_tenant['tenantId'],
max_users=50,
max_analyst=10
)
print("テナントの制限を更新しました")
JavaScript
const BASE_URL = 'https://your-mindzie-instance.com';
class TenantManager {
constructor(globalApiKey) {
this.headers = {
'Authorization': `Bearer ${globalApiKey}`,
'Content-Type': 'application/json'
};
}
async listTenants(page = 1, pageSize = 50) {
const url = `${BASE_URL}/api/tenant?page=${page}&pageSize=${pageSize}`;
const response = await fetch(url, { headers: this.headers });
if (!response.ok) throw new Error(`Failed: ${response.status}`);
return await response.json();
}
async getTenant(tenantId) {
const url = `${BASE_URL}/api/tenant/${tenantId}`;
const response = await fetch(url, { headers: this.headers });
if (!response.ok) throw new Error(`Failed: ${response.status}`);
return await response.json();
}
async createTenant(config) {
const url = `${BASE_URL}/api/tenant`;
const response = await fetch(url, {
method: 'POST',
headers: this.headers,
body: JSON.stringify(config)
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || `Failed: ${response.status}`);
}
return await response.json();
}
async updateTenant(tenantId, updates) {
const url = `${BASE_URL}/api/tenant`;
const response = await fetch(url, {
method: 'PUT',
headers: this.headers,
body: JSON.stringify({ tenantId, ...updates })
});
if (!response.ok) throw new Error(`Failed: ${response.status}`);
return await response.json();
}
}
// 使用例
const manager = new TenantManager('your-global-api-key');
// テナント一覧取得
const tenants = await manager.listTenants();
console.log(`見つかったテナント数: ${tenants.totalCount}`);
// テナント作成
const newTenant = await manager.createTenant({
name: 'new-tenant',
displayName: 'New Tenant',
maxUsers: 50,
maxAnalyst: 10,
maxCases: 100000
});
console.log(`作成されたテナントID: ${newTenant.tenantId}`);
// テナント更新
await manager.updateTenant(newTenant.tenantId, {
displayName: 'Updated Tenant Name',
maxUsers: 100
});
ベストプラクティス
- グローバルAPIキー:テナント管理にはグローバルAPIキーのみ使用してください。システム全体に対する権限があるためです。
- ライセンスの把握:新しいテナントを作成する前に、ライセンス制限に対してテナント数を監視してください。
- キャパシティプランニング:予想される利用に基づいて適切なユーザー数およびアナリスト数の制限を設定してください。
- 命名規則:テナント名には一貫した小文字のハイフン区切り命名規則を使用してください。