List Tenants
List all tenants in the system.
Authentication
Requires TENANT_MANAGEMENT.can_view permission.
Query parameters
Number of records to skip.
Max records to return (1-100).
Include soft-deleted tenants.
Example request
curl "https://mind-be.staging.miva.university/v1/console/tenants?limit=10" \
-H "Authorization: Bearer <access_token>"
Response
{
"success": true,
"data": [
{
"id": "6650a1b2c3d4e5f6a7b8c9d0",
"name": "Demo University",
"slug": "demo-university",
"domain": "demo.miva.university",
"lms_type": "canvas",
"is_active": true,
"created_at": "2025-01-01T00:00:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 10,
"total_pages": 1,
"message": null
}
Create Tenant
Create a new tenant. Branding, SSO, and AI config are configured separately after creation.
Authentication
Requires TENANT_MANAGEMENT.can_create permission.
Request body
Tenant display name. Max 255 characters.
URL-safe identifier. Lowercase alphanumeric and hyphens only (^[a-z0-9-]+$). Max 100 characters.
Custom domain for the tenant. Max 255 characters.
LMS integration type (e.g. canvas, blackboard, moodle). Max 50 characters.
Example request
curl -X POST https://mind-be.staging.miva.university/v1/console/tenants \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "State University",
"slug": "state-university",
"domain": "state.miva.university",
"lms_type": "canvas"
}'
Response
{
"success": true,
"data": {
"id": "6650c3d4e5f6a7b8c9d0e1f2",
"name": "State University",
"slug": "state-university",
"domain": "state.miva.university",
"lms_type": "canvas",
"is_active": true,
"created_at": "2025-06-01T14:00:00Z",
"updated_at": null,
"branding": null,
"sso_config": null,
"ai_config": null,
"allowed_origins": []
},
"message": "Tenant created successfully"
}
Error responses
| Status | Code | Condition |
|---|
409 | CONFLICT | Slug already taken |
422 | VALIDATION_ERROR | Invalid slug format |
Get Tenant
GET /v1/console/tenants/{tenant_id}
Get a tenant’s full configuration including branding, SSO, and AI settings.
Authentication
Requires TENANT_MANAGEMENT.can_view permission.
Path parameters
Example request
curl https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2 \
-H "Authorization: Bearer <access_token>"
Response
{
"success": true,
"data": {
"id": "6650c3d4e5f6a7b8c9d0e1f2",
"name": "State University",
"slug": "state-university",
"domain": "state.miva.university",
"lms_type": "canvas",
"is_active": true,
"created_at": "2025-06-01T14:00:00Z",
"updated_at": null,
"branding": {
"logo_url": "https://cdn.example.com/logo.png",
"primary_color": "#1E3A5F",
"secondary_color": "#F5A623",
"widget_position": "bottom-right"
},
"sso_config": {
"provider": "cas",
"server_url": "https://cas.state.edu",
"callback_url": "https://app.state.edu/cas/callback",
"is_enabled": true
},
"ai_config": {
"default_llm_model": "gpt-4o",
"default_tts_voice": "alloy",
"default_stt_language": "en",
"max_sessions_per_student": 5,
"default_language": "en",
"admin_email": "admin@state.edu",
"support_email": "support@state.edu"
},
"allowed_origins": ["https://app.state.edu"]
},
"message": null
}
Update Tenant
PATCH /v1/console/tenants/{tenant_id}
Update a tenant’s core fields. For branding, SSO, and AI config, use their dedicated endpoints.
Authentication
Requires TENANT_MANAGEMENT.can_edit permission.
Path parameters
Request body
Example request
curl -X PATCH https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2 \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"lms_type": "blackboard"
}'
Response
Returns the full updated tenant object (same shape as Get Tenant).
Delete Tenant
DELETE /v1/console/tenants/{tenant_id}
Soft-delete a tenant. All users under the tenant will lose access.
Authentication
Requires TENANT_MANAGEMENT.can_delete permission.
Path parameters
Example request
curl -X DELETE https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2 \
-H "Authorization: Bearer <access_token>"
Response
Returns the soft-deleted tenant object with is_active: false.
Update Branding
PATCH /v1/console/tenants/{tenant_id}/branding
Update the tenant’s branding configuration.
Authentication
Requires TENANT_MANAGEMENT.can_edit permission.
Path parameters
Request body
URL to the tenant’s logo. Max 500 characters.
Hex color code, e.g. #1E3A5F.
One of: bottom-right, bottom-left, top-right, top-left.
Example request
curl -X PATCH https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2/branding \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"primary_color": "#1E3A5F",
"secondary_color": "#F5A623"
}'
Response
{
"success": true,
"data": {
"logo_url": null,
"primary_color": "#1E3A5F",
"secondary_color": "#F5A623",
"widget_position": "bottom-right"
},
"message": "Branding updated successfully"
}
Update SSO Config
PATCH /v1/console/tenants/{tenant_id}/sso
Configure CAS SSO settings for the tenant.
Authentication
Requires TENANT_MANAGEMENT.can_edit permission.
Path parameters
Request body
Callback URL after CAS authentication.
Example request
curl -X PATCH https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2/sso \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"provider": "cas",
"server_url": "https://cas.state.edu",
"callback_url": "https://app.state.edu/cas/callback",
"is_enabled": true
}'
Response
{
"success": true,
"data": {
"provider": "cas",
"server_url": "https://cas.state.edu",
"callback_url": "https://app.state.edu/cas/callback",
"is_enabled": true
},
"message": "SSO config updated successfully"
}
Update AI Config
PATCH /v1/console/tenants/{tenant_id}/ai-config
Configure default AI settings for the tenant.
Authentication
Requires TENANT_MANAGEMENT.can_edit permission.
Path parameters
Request body
Default text-to-speech voice.
Default speech-to-text language code.
Max session attempts per student per case study.
Default UI language code.
Admin notification email.
Example request
curl -X PATCH https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2/ai-config \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"default_llm_model": "gpt-4o",
"max_sessions_per_student": 5
}'
Response
{
"success": true,
"data": {
"default_llm_model": "gpt-4o",
"default_tts_voice": null,
"default_stt_language": null,
"max_sessions_per_student": 5,
"default_language": null,
"admin_email": null,
"support_email": null
},
"message": "AI config updated successfully"
}
Get Allowed Origins
GET /v1/console/tenants/{tenant_id}/allowed-origins
Get the CORS allowed origins list for a tenant.
Authentication
Requires TENANT_MANAGEMENT.can_view permission.
Path parameters
Example request
curl https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2/allowed-origins \
-H "Authorization: Bearer <access_token>"
Response
{
"success": true,
"data": ["https://app.state.edu", "https://staging.state.edu"],
"message": null
}
Add Allowed Origin
POST /v1/console/tenants/{tenant_id}/allowed-origins
Add a CORS origin to the tenant’s allowed list.
Authentication
Requires TENANT_MANAGEMENT.can_edit permission.
Path parameters
Request body
The origin URL to allow (e.g. https://app.state.edu).
Example request
curl -X POST https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2/allowed-origins \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{ "origin": "https://newapp.state.edu" }'
Response
Returns the full updated list of allowed origins.
Remove Allowed Origin
DELETE /v1/console/tenants/{tenant_id}/allowed-origins/{origin}
Remove a CORS origin. The origin path parameter must be URL-encoded.
Authentication
Requires TENANT_MANAGEMENT.can_edit permission.
Path parameters
The origin URL to remove (URL-encoded).
Example request
curl -X DELETE "https://mind-be.staging.miva.university/v1/console/tenants/6650c3d4e5f6a7b8c9d0e1f2/allowed-origins/https%3A%2F%2Fnewapp.state.edu" \
-H "Authorization: Bearer <access_token>"
Response
{
"success": true,
"data": null,
"message": "Origin removed successfully"
}