Gestión de Inquilinos
Cree, liste, recupere y actualice inquilinos en la plataforma mindzieStudio.
IMPORTANTE: Todos los endpoints en esta página requieren una Clave API Global. Las claves API específicas de inquilinos recibirán un error 401 No autorizado.
Listar Todos los Inquilinos
GET /api/tenant
Recupera una lista paginada de todos los inquilinos en el sistema con estadísticas resumidas.
Parámetros de Consulta
| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
page |
entero | 1 | Número de página para paginación |
pageSize |
entero | 50 | Número de elementos por página (máx.: 100) |
Respuesta (200 OK)
{
"tenants": [
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation",
"description": "Inquilino principal para 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
}
Campos del Objeto Inquilino
| Campo | Tipo | Descripción |
|---|---|---|
tenantId |
GUID | Identificador único para el inquilino |
name |
string | Nombre único en el sistema (usado en URLs) |
displayName |
string | Nombre para mostrar legible por humanos |
description |
string | Descripción del inquilino |
caseCount |
entero | Número total de casos en todos los conjuntos de datos |
maxUserCount |
entero | Número máximo permitido de usuarios |
maxAnalystCount |
entero | Número máximo permitido de analistas |
analystCount |
entero | Número actual de analistas |
userCount |
entero | Número actual de usuarios |
preRelease |
booleano | Si el inquilino tiene características previas al lanzamiento |
isAcademic |
booleano | Si este es un inquilino académico |
autoload |
booleano | Si se cargan proyectos automáticamente |
dateCreated |
datetime | Fecha de creación del inquilino |
isDisabled |
booleano | Si el inquilino está deshabilitado |
Respuestas de Error
No autorizado (401):
{
"error": "Este endpoint requiere una clave API Global. Las claves API específicas de inquilinos no pueden listar todos los inquilinos.",
"hint": "Las claves API Globales pueden crearse en /admin/global-api-keys"
}
Obtener Inquilino por ID
GET /api/tenant/{tenantId}
Recupera información detallada para un inquilino específico por su ID.
Parámetros de Ruta
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
tenantId |
GUID | Sí | Identificador único del inquilino |
Respuesta (200 OK)
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation",
"description": "Inquilino principal para Acme Corporation",
"isAcademic": false,
"preRelease": false,
"maxUserCount": 100,
"maxAnalystCount": 20,
"maxCases": 100000,
"dateCreated": "2024-01-15T10:30:00Z",
"isDisabled": false
}
Respuestas de Error
No encontrado (404):
{
"error": "Inquilino con ID '12345678-1234-1234-1234-123456789012' no encontrado"
}
Crear Inquilino
POST /api/tenant
Crea un nuevo inquilino en el sistema con toda la infraestructura necesaria.
Cuerpo de la Solicitud
{
"name": "new-tenant",
"displayName": "New Tenant Corp",
"description": "Descripción del nuevo inquilino",
"maxUsers": 50,
"maxAnalyst": 10,
"maxCases": 100000,
"timeZone": "America/New_York"
}
Campos de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name |
string | Sí | Nombre único en el sistema (3-63 caracteres, alfanumérico en minúsculas con guiones) |
displayName |
string | Sí | Nombre para mostrar legible por humanos |
description |
string | No | Descripción del inquilino |
maxUsers |
entero | Sí | Número máximo de usuarios |
maxAnalyst |
entero | Sí | Número máximo de analistas |
maxCases |
entero | Sí | Número máximo de casos |
timeZone |
string | No | Zona horaria para el inquilino |
Requisitos para el Nombre del Inquilino
- 3-63 caracteres
- Alfanumérico en minúsculas con guiones solamente
- Sin espacios ni caracteres especiales
- Debe ser único entre todos los inquilinos
Respuesta (201 Creado)
{
"tenantId": "aabbccdd-1234-1234-1234-123456789012",
"name": "new-tenant",
"displayName": "New Tenant Corp",
"message": "Inquilino 'New Tenant Corp' creado con éxito",
"storageContainerCreated": true
}
Respuestas de Error
Conflicto (409):
{
"error": "Ya existe un inquilino con el nombre 'new-tenant'"
}
Límite de Licencia (429):
{
"error": "Se alcanzó el número máximo de inquilinos. Su licencia permite 10 inquilinos.",
"hint": "Actualice su licencia para crear más inquilinos"
}
Error de Validación (400):
{
"error": "Validación fallida",
"validationErrors": [
"El nombre debe tener entre 3 y 63 caracteres",
"El nombre solo puede contener letras minúsculas, números y guiones"
]
}
Actualizar Inquilino
PUT /api/tenant
Actualiza las propiedades de un inquilino existente. Solo los campos proporcionados serán actualizados; los valores nulos son ignorados.
Cuerpo de la Solicitud
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"displayName": "Acme Corporation Actualizado",
"description": "Descripción actualizada",
"maxUsers": 100,
"maxAnalyst": 25,
"maxCases": 200000,
"timeZone": "America/New_York",
"isAcademic": false,
"preRelease": true,
"isDisabled": false
}
Campos de la Solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tenantId |
GUID | Sí | Inquilino a actualizar |
displayName |
string | No | Nuevo nombre para mostrar (null = sin cambios) |
description |
string | No | Nueva descripción (null = sin cambios, "" = borrar) |
maxUsers |
entero | No | Máximo de usuarios (null = sin cambios) |
maxAnalyst |
entero | No | Máximo de analistas (null = sin cambios) |
maxCases |
entero | No | Máximo de casos (null = sin cambios, -1 = ilimitado) |
timeZone |
string | No | ID de zona horaria (null = sin cambios) |
isAcademic |
booleano | No | Indicador académico (null = sin cambios) |
preRelease |
booleano | No | Características previas al lanzamiento (null = sin cambios) |
isDisabled |
booleano | No | Deshabilitar inquilino (null = sin cambios) |
Nota: El name del inquilino no puede cambiarse después de la creación.
Respuesta (200 OK)
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation Actualizado",
"message": "Inquilino 'acme-corp' actualizado con éxito",
"isDisabled": false
}
Respuestas de Error
No encontrado (404):
{
"error": "Inquilino con ID '12345678-1234-1234-1234-123456789012' no encontrado"
}
Error de Validación (400):
{
"error": "Validación fallida",
"validationErrors": ["El nombre para mostrar no puede exceder los 255 caracteres"]
}
Ejemplos de Implementación
cURL
# Listar todos los inquilinos
curl -X GET "https://your-mindzie-instance.com/api/tenant?page=1&pageSize=50" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY"
# Obtener inquilino específico por ID
curl -X GET "https://your-mindzie-instance.com/api/tenant/12345678-1234-1234-1234-123456789012" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY"
# Crear inquilino
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
}'
# Actualizar inquilino
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):
"""Inicializa con una clave API GLOBAL (no específica de inquilino)."""
self.headers = {
'Authorization': f'Bearer {global_api_key}',
'Content-Type': 'application/json'
}
def list_tenants(self, page=1, page_size=50):
"""Lista todos los inquilinos en el sistema."""
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):
"""Obtiene un inquilino específico por 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):
"""Crea un nuevo inquilino."""
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):
"""Actualiza un inquilino existente."""
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()
# Uso
manager = TenantManager('your-global-api-key')
# Listar todos los inquilinos
result = manager.list_tenants()
print(f"Total de inquilinos: {result['totalCount']}")
for tenant in result['tenants']:
print(f"- {tenant['displayName']} ({tenant['name']})")
print(f" Usuarios: {tenant['userCount']}/{tenant['maxUserCount']}")
# Crear un nuevo inquilino
new_tenant = manager.create_tenant(
name='test-tenant',
display_name='Test Tenant',
description='Creado vía API',
max_users=25,
max_analyst=5,
max_cases=50000
)
print(f"Inquilino creado: {new_tenant['tenantId']}")
# Actualizar límites del inquilino
manager.update_tenant(
tenant_id=new_tenant['tenantId'],
max_users=50,
max_analyst=10
)
print("Límites del inquilino actualizados")
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(`Falló: ${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(`Falló: ${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 || `Falló: ${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(`Falló: ${response.status}`);
return await response.json();
}
}
// Uso
const manager = new TenantManager('your-global-api-key');
// Listar inquilinos
const tenants = await manager.listTenants();
console.log(`Encontrados ${tenants.totalCount} inquilinos`);
// Crear inquilino
const newTenant = await manager.createTenant({
name: 'new-tenant',
displayName: 'Nuevo Inquilino',
maxUsers: 50,
maxAnalyst: 10,
maxCases: 100000
});
console.log(`Creado: ${newTenant.tenantId}`);
// Actualizar inquilino
await manager.updateTenant(newTenant.tenantId, {
displayName: 'Nombre de Inquilino Actualizado',
maxUsers: 100
});
Mejores Prácticas
- Claves API Globales: Use solo claves API globales para la gestión de inquilinos, ya que tienen privilegios significativos a nivel de sistema
- Conciencia de Licencias: Controle la cantidad de inquilinos frente a los límites de licencia antes de crear nuevos inquilinos
- Planificación de Capacidad: Establezca límites adecuados de usuarios y analistas según el uso esperado
- Convenciones de Nombres: Use nombres consistentes, en minúsculas y con guiones para los nombres de inquilinos