Tenant Deletion
Permanently delete a tenant and all related data. This operation requires triple verification for safety.
IMPORTANT: All endpoints on this page require a Global API Key. This is a dangerous operation that cannot be undone.
Delete Tenant
DELETE /api/tenant
Permanently deletes a tenant and all related data. Requires triple verification for safety.
WARNING
This operation is IRREVERSIBLE. All tenant data will be permanently deleted including:
- All projects and their datasets
- All investigations, notebooks, and dashboards
- Blob storage container and files
- Database records and settings
- User assignments to the tenant (users themselves are not deleted)
Always export important data before deleting a tenant.
Request Body
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation"
}
Triple Verification
All three identifiers must match exactly for the deletion to proceed:
| Field | Type | Required | Description |
|---|---|---|---|
tenantId |
GUID | Yes | Tenant ID to delete |
name |
string | Yes | Tenant name (must match exactly) |
displayName |
string | Yes | Display name (must match exactly) |
This triple verification prevents accidental deletions by requiring you to know and confirm all three identifiers.
Response (200 OK)
{
"message": "Tenant 'Acme Corporation' deleted successfully",
"tenantName": "acme-corp",
"tenantDisplayName": "Acme Corporation",
"storageContainerDeleted": true
}
Response Fields
| Field | Type | Description |
|---|---|---|
message |
string | Success confirmation message |
tenantName |
string | The deleted tenant's system name |
tenantDisplayName |
string | The deleted tenant's display name |
storageContainerDeleted |
boolean | Whether the blob storage was deleted |
Error Responses
Not Found (404)
{
"error": "Tenant not found with ID '12345678-1234-1234-1234-123456789012'"
}
Verification Failed (400)
When the tenant name doesn't match:
{
"error": "Tenant name 'wrong-name' does not match the tenant with ID '12345678-1234-1234-1234-123456789012'. Expected 'acme-corp'.",
"hint": "All three identifiers (ID, name, display name) must match exactly for safety"
}
When the display name doesn't match:
{
"error": "Display name 'Wrong Name' does not match the tenant with ID '12345678-1234-1234-1234-123456789012'. Expected 'Acme Corporation'.",
"hint": "All three identifiers (ID, name, display name) must match exactly for safety"
}
Unauthorized (401)
{
"error": "This endpoint requires a Global API key.",
"hint": "Global API keys can be created at /admin/global-api-keys"
}
Implementation Examples
cURL
# Delete tenant (requires triple verification)
curl -X DELETE "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",
"name": "test-tenant",
"displayName": "Test Tenant"
}'
Python
import requests
BASE_URL = 'https://your-mindzie-instance.com'
class TenantDeleter:
def __init__(self, global_api_key):
"""Initialize with a GLOBAL API key (not tenant-specific)."""
self.headers = {
'Authorization': f'Bearer {global_api_key}',
'Content-Type': 'application/json'
}
def get_tenant(self, tenant_id):
"""Get tenant details for verification."""
url = f'{BASE_URL}/api/tenant/{tenant_id}'
response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json()
def delete_tenant(self, tenant_id, name, display_name, confirm=False):
"""
Delete a tenant with triple verification.
Args:
tenant_id: The tenant GUID
name: The tenant system name (must match exactly)
display_name: The tenant display name (must match exactly)
confirm: Set to True to actually perform deletion
"""
if not confirm:
# Verification mode - check that values match
tenant = self.get_tenant(tenant_id)
errors = []
if tenant['name'] != name:
errors.append(f"Name mismatch: expected '{tenant['name']}', got '{name}'")
if tenant['displayName'] != display_name:
errors.append(f"Display name mismatch: expected '{tenant['displayName']}', got '{display_name}'")
if errors:
raise ValueError("Verification failed:\n" + "\n".join(errors))
print(f"Verification passed for tenant '{display_name}' ({name})")
print(f" - ID: {tenant_id}")
print(f" - Users: {tenant.get('userCount', 'N/A')}")
print(f" - Cases: {tenant.get('caseCount', 'N/A')}")
print("\nCall with confirm=True to proceed with deletion.")
return None
# Perform the deletion
url = f'{BASE_URL}/api/tenant'
payload = {
'tenantId': tenant_id,
'name': name,
'displayName': display_name
}
response = requests.delete(url, json=payload, headers=self.headers)
if response.ok:
return response.json()
elif response.status_code == 404:
raise Exception(f'Tenant not found: {tenant_id}')
elif response.status_code == 400:
error = response.json()
raise Exception(f"Verification failed: {error.get('error', 'Unknown error')}")
else:
raise Exception(f'Failed to delete tenant: {response.text}')
# Usage - Safe deletion workflow
deleter = TenantDeleter('your-global-api-key')
tenant_id = '12345678-1234-1234-1234-123456789012'
tenant_name = 'test-tenant'
display_name = 'Test Tenant'
# Step 1: Verify (no deletion occurs)
try:
deleter.delete_tenant(tenant_id, tenant_name, display_name, confirm=False)
except ValueError as e:
print(f"Verification failed: {e}")
exit(1)
# Step 2: Confirm deletion (uncomment when ready)
# result = deleter.delete_tenant(tenant_id, tenant_name, display_name, confirm=True)
# print(f"Deleted: {result['message']}")
JavaScript
const BASE_URL = 'https://your-mindzie-instance.com';
class TenantDeleter {
constructor(globalApiKey) {
this.headers = {
'Authorization': `Bearer ${globalApiKey}`,
'Content-Type': 'application/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 to get tenant: ${response.status}`);
return await response.json();
}
async deleteTenant(tenantId, name, displayName, confirm = false) {
if (!confirm) {
// Verification mode
const tenant = await this.getTenant(tenantId);
const errors = [];
if (tenant.name !== name) {
errors.push(`Name mismatch: expected '${tenant.name}', got '${name}'`);
}
if (tenant.displayName !== displayName) {
errors.push(`Display name mismatch: expected '${tenant.displayName}', got '${displayName}'`);
}
if (errors.length > 0) {
throw new Error('Verification failed:\n' + errors.join('\n'));
}
console.log(`Verification passed for tenant '${displayName}' (${name})`);
console.log(` - ID: ${tenantId}`);
console.log(` - Users: ${tenant.userCount || 'N/A'}`);
console.log('\nCall with confirm=true to proceed with deletion.');
return null;
}
// Perform the deletion
const url = `${BASE_URL}/api/tenant`;
const response = await fetch(url, {
method: 'DELETE',
headers: this.headers,
body: JSON.stringify({ tenantId, name, displayName })
});
if (response.ok) {
return await response.json();
}
const error = await response.json();
throw new Error(error.error || `Delete failed: ${response.status}`);
}
}
// Usage - Safe deletion workflow
const deleter = new TenantDeleter('your-global-api-key');
const tenantId = '12345678-1234-1234-1234-123456789012';
const tenantName = 'test-tenant';
const displayName = 'Test Tenant';
// Step 1: Verify (no deletion occurs)
try {
await deleter.deleteTenant(tenantId, tenantName, displayName, false);
} catch (e) {
console.error(`Verification failed: ${e.message}`);
process.exit(1);
}
// Step 2: Confirm deletion (uncomment when ready)
// const result = await deleter.deleteTenant(tenantId, tenantName, displayName, true);
// console.log(`Deleted: ${result.message}`);
Safety Best Practices
Before Deletion
- Export All Data: Use the Project API to export all projects as .mpz files
- Verify Users: Check which users are assigned and notify them
- Document: Record what is being deleted and why for audit purposes
- Double-Check: Verify the tenant ID, name, and display name are correct
During Deletion
- Use the Verification Pattern: Call the delete endpoint in verify-only mode first
- Check Response: Verify the response shows the correct tenant information
- Confirm Deliberately: Only pass
confirm=Trueafter manual verification
After Deletion
- Verify Deletion: Confirm the tenant no longer appears in the tenant list
- Check Users: Verify affected users can no longer access the deleted tenant
- Update Documentation: Record the deletion in your system documentation
Alternative: Disable Instead of Delete
Consider disabling a tenant instead of deleting it to preserve data while preventing access:
# Disable tenant (preserves data)
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",
"isDisabled": true
}'
Disabled tenants:
- Users cannot log in to the tenant
- All data is preserved
- Can be re-enabled later by setting
isDisabled: false - Appear in the tenant list with
isDisabled: true
This is often a safer choice than permanent deletion.