Skip to main content

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

FieldTypeDescription
idUUIDProfile identifier
namestringHuman-readable name
slugstringMachine identifier, format ^[a-z][a-z0-9-]*$
descriptionstringDescription of the profile's intent
creditCapPerMonthinteger | nullPer-actor monthly credit ceiling. null = unlimited, 0 = hard stop, positive = capped
allowedModelTiersstring[]Subset of everyday, advanced, strategic
Effective profile resolution

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:

FieldTypeRequiredDescription
namestringYesProfile name
slugstringYesMachine identifier, ^[a-z][a-z0-9-]*$
descriptionstringYesProfile description
creditCapPerMonthinteger | nullNoMonthly credit cap (default null = unlimited)
allowedModelTiersstring[]NoAllowed 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 same slug already exists

GET /api/usage-profiles/{id}

Retrieve a single usage profile.

Authentication: Required (session)

Pre-blocks: permission.tenant.superuser, usageProfile.lookup

Path Parameters:

ParameterTypeDescription
idUUIDProfile 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:

FieldTypeDescription
namestringProfile name
descriptionstringProfile description (must be a real value if included)
creditCapPerMonthinteger | nullMonthly credit cap
allowedModelTiersstring[]Allowed tiers
Slug is immutable

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/agents
  • 409 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:

FieldTypeRequiredDescription
profileIdUUID | nullYesProfile to assign, or null to unassign

Response:

Returns the assigned { profileId, profile }, or { profileId: null, profile: null } when unassigning.

Errors:

  • 404 Not Found — the supplied profileId does not exist