Usage Profiles
A usage profile bundles an AI credit budget with a set of allowed model tiers, then is assigned to teams (or agents) to govern what their members can do. See Usage & Credits for how profiles fit into enforcement.
Profile fields
| Field | Type | Description |
|---|---|---|
id | UUID | Profile identifier |
name | string | Human-readable name |
slug | string | Machine identifier, format ^[a-z][a-z0-9-]*$ |
description | string | Description of the profile's intent |
creditCapPerMonth | integer | null | Per-actor monthly credit ceiling. null = unlimited, 0 = hard stop, positive = capped |
allowedModelTiers | string[] | Subset of everyday, advanced, strategic |
A user's effective profile is resolved from their team memberships. When a user belongs to multiple teams with different profiles, the result is merged to the most permissive: the union of allowedModelTiers and the highest creditCapPerMonth (null/unlimited always wins). If no team assignment applies, the tenant's default profile is used.
GET /api/usage-profiles
List all usage profiles for the tenant. System-seeded profiles (Standard, Premium) appear first, followed by tenant-created profiles in creation order.
Authentication: Required (session)
Pre-blocks: permission.tenant.superuser
Response:
{
"_links": { "self": { "href": "/api/usage-profiles" } },
"_embedded": {
"inf:usage-profile": [
{
"id": "11111111-1111-1111-1111-111111111111",
"name": "Standard",
"slug": "standard",
"description": "Everyday models with a monthly credit cap",
"creditCapPerMonth": 5000,
"allowedModelTiers": ["everyday", "advanced"],
"isUnlimited": false,
"createdAt": "2026-05-01T00:00:00Z",
"updatedAt": "2026-05-01T00:00:00Z"
}
]
}
}
POST /api/usage-profiles
Create a new usage profile.
Authentication: Required (session)
Pre-blocks: permission.usage.write
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Profile name |
slug | string | Yes | Machine identifier, ^[a-z][a-z0-9-]*$ |
description | string | Yes | Profile description |
creditCapPerMonth | integer | null | No | Monthly credit cap (default null = unlimited) |
allowedModelTiers | string[] | No | Allowed tiers (default []) |
Example Request:
{
"name": "Analysts",
"slug": "analysts",
"description": "Strategic models, no monthly cap",
"creditCapPerMonth": null,
"allowedModelTiers": ["everyday", "advanced", "strategic"]
}
Response:
Returns the created profile object.
Errors:
409 Conflict— a profile with the sameslugalready exists
GET /api/usage-profiles/{id}
Retrieve a single usage profile.
Authentication: Required (session)
Pre-blocks: permission.tenant.superuser, usageProfile.lookup
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | UUID | Profile ID |
Response:
Returns the profile object with its HAL inf:usage-profile link.
PUT /api/usage-profiles/{id}
Update a usage profile. All fields are optional — only the supplied fields are changed.
Authentication: Required (session)
Pre-blocks: permission.usage.write, usageProfile.lookup
Request Body:
| Field | Type | Description |
|---|---|---|
name | string | Profile name |
description | string | Profile description (must be a real value if included) |
creditCapPerMonth | integer | null | Monthly credit cap |
allowedModelTiers | string[] | Allowed tiers |
slug cannot be changed after creation and is not accepted by this endpoint.
Response:
Returns the updated profile object.
DELETE /api/usage-profiles/{id}
Delete a usage profile.
Authentication: Required (session)
Pre-blocks: permission.usage.write, usageProfile.lookup
Response:
{ "success": true }
Errors:
409 Conflict— the profile is assigned to one or more teams/agents409 Conflict— the profile is the tenant default
GET /api/teams/{id}/ai/profile
Get the usage profile currently assigned to a team.
Authentication: Required (session)
Pre-blocks: team.lookup, permission.billing.manage
Response:
{
"profileId": "11111111-1111-1111-1111-111111111111",
"profile": {
"id": "11111111-1111-1111-1111-111111111111",
"name": "Standard",
"slug": "standard",
"creditCapPerMonth": 5000,
"allowedModelTiers": ["everyday", "advanced"]
}
}
When no profile is assigned, both fields are null:
{ "profileId": null, "profile": null }
PUT /api/teams/{id}/ai/profile
Assign a usage profile to a team, or unassign it.
Authentication: Required (session)
Pre-blocks: team.lookup, permission.billing.manage
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
profileId | UUID | null | Yes | Profile to assign, or null to unassign |
Response:
Returns the assigned { profileId, profile }, or { profileId: null, profile: null } when unassigning.
Errors:
404 Not Found— the suppliedprofileIddoes not exist