Admin - Roles
Manage tenant roles and permissions through the Admin API. Create custom roles with fine-grained permission sets, assign credit limits, compare permissions across roles, and browse the permissions catalog.
List Roles
List all roles visible to the caller. When tenant_id is provided, returns default tenant roles plus custom roles scoped to that tenant. When omitted, returns all custom roles for the caller's MSP.
Endpoint
GET /v1/admin/roles
Query Parameters
tenant_id(optional): Tenant HashID — filter to roles assignable to this tenantlimit(optional): Maximum number of roles to return per source (1-100, default: 10)offset(optional): Number of roles to skip per source (default: 0)
Example Query
curl 'https://ai.hatz.ai/v1/admin/roles?tenant_id=tenant_abc123&limit=20&offset=0' \
-H 'X-API-Key: $HATZ_API_KEY'
Response
{
"roles": [
{
"id": "role_a3k9x2m8",
"name": "general_user",
"display_name": "General User",
"description": "Standard user access",
"user_credit_limit": null,
"role_source": "default",
"scope": null,
"permissions_count": 12,
"permissions_preview": ["Secure Chat", "App Builder", "Workshop Access"],
"assigned_users_count": 45
},
{
"id": "role_b7j2y5p1",
"name": "engineering-lead",
"display_name": "Engineering Lead",
"description": "Custom role for engineering team leads",
"user_credit_limit": 5000.0,
"role_source": "custom",
"scope": "tenant",
"permissions_count": 18,
"permissions_preview": ["Secure Chat", "App Builder", "Workflow Management"],
"assigned_users_count": 3
}
],
"total_count": 2
}
Get Role Detail
Get full detail for a role (custom or default) including its permissions.
Endpoint
GET /v1/admin/roles/{role_id}
Path Parameters
role_id(required): Role HashID (e.g., "role_a3k9x2m8")
Example Query
curl 'https://ai.hatz.ai/v1/admin/roles/role_a3k9x2m8' \
-H 'X-API-Key: $HATZ_API_KEY'
Response
{
"id": "role_a3k9x2m8",
"name": "general_user",
"display_name": "General User",
"description": "Standard user access",
"user_credit_limit": null,
"role_source": "default",
"scope": null,
"permissions_count": 3,
"permissions_preview": ["Secure Chat", "App Builder", "Workshop Access"],
"assigned_users_count": 45,
"permissions": [
{
"name": "secure_chat",
"printable_name": "Secure Chat",
"description": "Access to the secure AI chat",
"scope": "entity",
"tags": ["chat"],
"user_selectable": true
},
{
"name": "app_builder",
"printable_name": "App Builder",
"description": "Create and manage apps",
"scope": "entity",
"tags": ["apps"],
"user_selectable": true
},
{
"name": "workshop_access",
"printable_name": "Workshop Access",
"description": "View and use existing apps in the workshop",
"scope": "entity",
"tags": ["apps"],
"user_selectable": true
}
]
}
Get Role Permissions
List permissions assigned to a specific role with pagination.
Endpoint
GET /v1/admin/roles/{role_id}/permissions
Path Parameters
role_id(required): Role HashID (e.g., "role_a3k9x2m8")
Query Parameters
limit(optional): Maximum number of permissions to return (1-200, default: 10)offset(optional): Number of permissions to skip (default: 0)
Example Query
curl 'https://ai.hatz.ai/v1/admin/roles/role_a3k9x2m8/permissions?limit=50&offset=0' \
-H 'X-API-Key: $HATZ_API_KEY'
Response
{
"permissions": [
{
"name": "secure_chat",
"printable_name": "Secure Chat",
"description": "Access to the secure AI chat",
"scope": "entity",
"tags": ["chat"],
"user_selectable": true
}
],
"total_count": 12
}
Compare Role Permissions
Compare permissions across multiple roles side-by-side. Useful for auditing differences between roles.
Endpoint
POST /v1/admin/roles/compare-permissions
Request Body
role_ids(required): List of role HashIDs to compare (max 10)
{
"role_ids": ["role_a3k9x2m8", "role_b7j2y5p1"]
}
Example Request
curl -X POST 'https://ai.hatz.ai/v1/admin/roles/compare-permissions' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"role_ids": ["role_a3k9x2m8", "role_b7j2y5p1"]
}'
Response
{
"permissions": [
{
"permission_name": "secure_chat",
"printable_name": "Secure Chat",
"role_a3k9x2m8": true,
"role_b7j2y5p1": true
},
{
"permission_name": "workflow_management",
"printable_name": "Workflow Management",
"role_a3k9x2m8": false,
"role_b7j2y5p1": true
}
],
"role_summaries": [
{
"id": "role_a3k9x2m8",
"name": "general_user",
"display_name": "General User",
"permissions_count": 12
},
{
"id": "role_b7j2y5p1",
"name": "engineering-lead",
"display_name": "Engineering Lead",
"permissions_count": 18
}
]
}
Create Custom Role
Create a new custom role. When tenant_id is provided the role is scoped to that tenant. When omitted the role is MSP-wide.
Endpoint
POST /v1/admin/roles/custom
Request Body
display_name(required): Human-readable name shown in the UIdescription(optional): Role descriptionuser_credit_limit(optional): Per-user credit limittenant_id(optional): Tenant HashID — scopes the role to that tenant; omit for MSP-widepermission_names(optional): List of permission slugs to assign to the new role
{
"display_name": "string",
"description": "string",
"user_credit_limit": 5000.0,
"tenant_id": "string",
"permission_names": ["secure_chat", "app_builder"]
}
Example Request
curl -X POST 'https://ai.hatz.ai/v1/admin/roles/custom' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"display_name": "Engineering Lead",
"description": "Custom role for engineering team leads",
"user_credit_limit": 5000.0,
"tenant_id": "tenant_abc123",
"permission_names": ["secure_chat", "app_builder", "workflow_management"]
}'
Response (201 Created)
{
"id": "role_c4m8n1q6",
"name": "engineering-lead",
"display_name": "Engineering Lead",
"description": "Custom role for engineering team leads",
"user_credit_limit": 5000.0,
"role_source": "custom",
"scope": "tenant",
"permissions_count": 3,
"permissions_preview": ["Secure Chat", "App Builder", "Workflow Management"],
"assigned_users_count": 0,
"permissions": [
{
"name": "secure_chat",
"printable_name": "Secure Chat",
"description": "Access to the secure AI chat",
"scope": "entity",
"tags": ["chat"],
"user_selectable": true
}
]
}
Update Custom Role
Update the display name, description, or credit limit of a custom role.
Endpoint
PATCH /v1/admin/roles/custom/{role_id}
Path Parameters
role_id(required): Role HashID (e.g., "role_c4m8n1q6")
Request Body
All fields are optional — provide only the fields you want to update.
display_name(optional): Human-readable namedescription(optional): Role descriptionuser_credit_limit(optional): Per-user credit limit
{
"display_name": "Senior Engineer",
"user_credit_limit": 10000.0
}
Example Request
curl -X PATCH 'https://ai.hatz.ai/v1/admin/roles/custom/role_c4m8n1q6' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"display_name": "Senior Engineer",
"user_credit_limit": 10000.0
}'
Response
{
"id": "role_c4m8n1q6",
"name": "engineering-lead",
"display_name": "Senior Engineer",
"description": "Custom role for engineering team leads",
"user_credit_limit": 10000.0,
"role_source": "custom",
"scope": "tenant",
"permissions_count": 3,
"permissions_preview": ["Secure Chat", "App Builder", "Workflow Management"],
"assigned_users_count": 0,
"permissions": []
}
Delete Custom Role
Delete a custom role. Returns 409 Conflict if users are currently assigned to the role.
Endpoint
DELETE /v1/admin/roles/custom/{role_id}
Path Parameters
role_id(required): Role HashID (e.g., "role_c4m8n1q6")
Example Request
curl -X DELETE 'https://ai.hatz.ai/v1/admin/roles/custom/role_c4m8n1q6' \
-H 'X-API-Key: $HATZ_API_KEY'
Response (204 No Content)
No response body.
Error Responses
409— Role has users assigned and cannot be deleted
Set Custom Role Permissions
Replace the full set of permissions for a custom role. This is a full replacement — any permissions not included in the request will be removed.
Endpoint
PUT /v1/admin/roles/custom/{role_id}/permissions
Path Parameters
role_id(required): Role HashID (e.g., "role_c4m8n1q6")
Query Parameters
limit(optional): Maximum number of permissions to return (1-200, default: 10)offset(optional): Number of permissions to skip (default: 0)
Request Body
permission_names(required): List of permission slugs to assign
{
"permission_names": ["secure_chat", "app_builder", "workflow_management", "usage_analytics"]
}
Example Request
curl -X PUT 'https://ai.hatz.ai/v1/admin/roles/custom/role_c4m8n1q6/permissions' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"permission_names": ["secure_chat", "app_builder", "workflow_management"]
}'
Response
{
"permissions": [
{
"name": "secure_chat",
"printable_name": "Secure Chat",
"description": "Access to the secure AI chat",
"scope": "entity",
"tags": ["chat"],
"user_selectable": true
},
{
"name": "app_builder",
"printable_name": "App Builder",
"description": "Create and manage apps",
"scope": "entity",
"tags": ["apps"],
"user_selectable": true
}
],
"total_count": 3
}
Duplicate Custom Role
Duplicate a custom role, copying all of its permissions to the new role.
Endpoint
POST /v1/admin/roles/custom/{role_id}/duplicate
Path Parameters
role_id(required): Role HashID of the role to duplicate (e.g., "role_c4m8n1q6")
Request Body
All fields are optional.
name(optional): Slug for the new role; defaults to the original name with "-copy" appendedtenant_id(optional): Tenant HashID to scope the duplicate; omit for MSP-wide
{
"name": "engineering-lead-v2",
"tenant_id": "tenant_abc123"
}
Example Request
curl -X POST 'https://ai.hatz.ai/v1/admin/roles/custom/role_c4m8n1q6/duplicate' \
-H 'X-API-Key: $HATZ_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"name": "engineering-lead-v2"
}'
Response (201 Created)
{
"id": "role_d9k3w7t2",
"name": "engineering-lead-v2",
"display_name": "Senior Engineer (Copy)",
"description": "Custom role for engineering team leads",
"user_credit_limit": 10000.0,
"role_source": "custom",
"scope": "tenant",
"permissions_count": 3,
"permissions_preview": ["Secure Chat", "App Builder", "Workflow Management"],
"assigned_users_count": 0,
"permissions": []
}
List Permissions
List the available user-selectable permissions. When tenant_id is provided, the scope may widen for internal MSP tenants.
Endpoint
GET /v1/admin/permissions
Query Parameters
tenant_id(optional): Tenant HashID — widens scope for internal MSP tenantlimit(optional): Maximum number of permissions to return (1-200, default: 10)offset(optional): Number of permissions to skip (default: 0)
Example Query
curl 'https://ai.hatz.ai/v1/admin/permissions?limit=50&offset=0' \
-H 'X-API-Key: $HATZ_API_KEY'
Response
{
"permissions": [
{
"name": "secure_chat",
"printable_name": "Secure Chat",
"description": "Access to the secure AI chat",
"scope": "entity",
"tags": ["chat"],
"user_selectable": true
},
{
"name": "app_builder",
"printable_name": "App Builder",
"description": "Create and manage apps",
"scope": "entity",
"tags": ["apps"],
"user_selectable": true
}
],
"total_count": 24
}
List Tenant Assignable Roles
List all roles assignable within a specific tenant context. Returns default roles plus MSP-wide and tenant-scoped custom roles.
Endpoint
GET /v1/admin/tenants/{tenant_id}/roles
Path Parameters
tenant_id(required): Tenant HashID (e.g., "tenant_abc123")
Query Parameters
limit(optional): Maximum number of roles to return (1-500, default: 100)offset(optional): Number of roles to skip (default: 0)
Example Query
curl 'https://ai.hatz.ai/v1/admin/tenants/tenant_abc123/roles?limit=50&offset=0' \
-H 'X-API-Key: $HATZ_API_KEY'
Response
{
"roles": [
{
"id": "role_a3k9x2m8",
"name": "general_user",
"display_name": "General User",
"description": "Standard user access",
"user_credit_limit": null,
"role_source": "default",
"scope": null,
"permissions_count": 12,
"permissions_preview": [],
"assigned_users_count": null
},
{
"id": "role_b7j2y5p1",
"name": "msp-power-user",
"display_name": "MSP Power User",
"description": "MSP-wide custom role",
"user_credit_limit": 8000.0,
"role_source": "custom",
"scope": "msp",
"permissions_count": 15,
"permissions_preview": [],
"assigned_users_count": null
},
{
"id": "role_c4m8n1q6",
"name": "engineering-lead",
"display_name": "Engineering Lead",
"description": "Tenant-scoped custom role",
"user_credit_limit": 5000.0,
"role_source": "custom",
"scope": "tenant",
"permissions_count": 18,
"permissions_preview": [],
"assigned_users_count": null
}
],
"total_count": 3
}