Admin - Usage Limits

Usage limits cap how many credits a user can spend in a week or a month. Set a default limit for everyone with a role in a tenant, and override it for individual users. Use these endpoints to list, set and remove the limits in the tenants your MSP manages.

Who Can Call These Endpoints

The API key must belong to a user on your MSP (admin.hatz.ai) account whose role includes the Manage Usage Limits permission. Among the default MSP roles, Primary Admin, Admin, Tenant Manager and Billing Manager include it; Helpdesk does not.

Caller Result
MSP user with Manage Usage Limits Can manage limits in every tenant your MSP manages, or, if your MSP restricts users to their account teams, in the tenants assigned to them (others return 403)
MSP user without Manage Usage Limits 403
Tenant (company) user, including a tenant admin 403 with "Insufficient permissions"
Any user, for a tenant that belongs to another MSP 403
Missing or invalid API key 401

How Limits Work

Each limit has a period, a credit limit and an action.

  • Periods are independent. A user can have a weekly limit and a monthly limit at the same time.
    • monthly resets at 00:00 UTC on the first day of each month.
    • weekly resets every Wednesday at 12:00 America/New_York.
  • Credit limit is the number of credits allowed in the period, from 0 to 1,000,000,000,000. A limit of 0 is reached immediately.
  • Action is what happens when a user reaches the limit:
    • block stops further usage until the period resets.
    • auto_only lets the user keep working with Auto (Hatz's automatic model selection), restricted to the modes listed in auto_llm_mode_set (lite, performance, turbo). If two auto_only limits are reached at once, only the modes in both lists remain. If none remain, usage is blocked.

For each period, a user's effective limit is:

  1. Their user override for that period, if one exists. It applies whether it is higher or lower than the role default.
  2. Otherwise, the role default for their role in their tenant.
  3. Otherwise, no limit.

A monthly override replaces only the monthly role default. A weekly role default still applies.

Changing a limit never changes a user's role or permissions.

IDs

  • tenant_id is the tenant ID returned by List Tenants (GET /v1/admin/tenants), for example tenant_abc123. A tenant UUID also works.
  • role_id is a role HashID (role_...) from List Roles on the Admin - Roles page.
    • Built-in platform roles use role_source: "default".
    • Custom roles use role_source: "custom".
  • user_id is a user HashID (user_...). Get it from Get Tenant Users (GET /v1/admin/tenants/{tenant_id}/users) on the Admin - Tenant page.

The Limit Object

List Usage Limits returns each limit in this shape:

Field Description
credit_limit Credits allowed per period
action block or auto_only
auto_llm_mode_set Auto modes still allowed at the limit; null for block
subject_type role for a role default, user for a user override
subject_id The role or user HashID
period monthly or weekly
scope tenant for a limit set on this tenant. msp for a custom role defined across your MSP, whose limit applies in every tenant of your MSP.
role_source default or custom for role rows; null for user rows

List Usage Limits

List the role defaults and user overrides that apply to a tenant.

Endpoint

GET /v1/admin/tenants/{tenant_id}/usage-limits

Path Parameters

  • tenant_id (required): Tenant ID (e.g., "tenant_abc123")

Query Parameters

  • limit (optional): Rows per page (1-1000, default: 100)
  • offset (optional): Rows to skip (default: 0)

Pagination

total_count is the number of rows before limit and offset are applied. Increase offset by limit, and stop when the next offset would be equal to or greater than total_count. For example, with total_count 150 and limit 100, request offsets 0 and 100, then stop. An offset beyond total_count returns 400, not an empty page.

Example Query

curl 'https://ai.hatz.ai/v1/admin/tenants/tenant_abc123/usage-limits' \
  -H "X-API-Key: $HATZ_API_KEY"

Response

{
  "limits": [
    {
      "credit_limit": 750.0,
      "action": "auto_only",
      "auto_llm_mode_set": ["lite"],
      "subject_type": "role",
      "subject_id": "role_O8oZwaNGyJoDVCeKAL8N84wx5W",
      "period": "monthly",
      "scope": "tenant",
      "role_source": "default"
    },
    {
      "credit_limit": 200.0,
      "action": "auto_only",
      "auto_llm_mode_set": ["lite", "performance"],
      "subject_type": "role",
      "subject_id": "role_aEyZ6Vr5zOW8JH28MJzmEVp2an",
      "period": "weekly",
      "scope": "msp",
      "role_source": "custom"
    },
    {
      "credit_limit": 50.0,
      "action": "block",
      "auto_llm_mode_set": null,
      "subject_type": "user",
      "subject_id": "user_ExxypMkWV0PLDUAyLpdJlOEJ69",
      "period": "monthly",
      "scope": "tenant",
      "role_source": null
    }
  ],
  "total_count": 3
}

Set Role Usage Limit

Create or replace the default limit for one role and period. It applies to everyone with that role in the tenant who has no user override for the same period.

For a custom role defined across your MSP, the limit is stored once and applies in every tenant of your MSP. It appears with scope: "msp" when you list any of those tenants.

Endpoint

PUT /v1/admin/tenants/{tenant_id}/usage-limits/roles/{role_id}

Path Parameters

  • tenant_id (required): Tenant ID
  • role_id (required): Role HashID

Request Body

  • role_source (required): default for a built-in platform role, custom for a custom role. It must match the role; a mismatch returns 404.
  • period (required): monthly or weekly
  • credit_limit (required): Credits allowed per period (0 to 1,000,000,000,000)
  • action (required): block or auto_only
  • auto_llm_mode_set (required with auto_only, not allowed with block): One or more of lite, performance, turbo

Unknown fields are rejected with 422.

Example Request

curl -X PUT 'https://ai.hatz.ai/v1/admin/tenants/tenant_abc123/usage-limits/roles/role_O8oZwaNGyJoDVCeKAL8N84wx5W' \
  -H "X-API-Key: $HATZ_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "role_source": "default",
    "period": "monthly",
    "credit_limit": 750,
    "action": "auto_only",
    "auto_llm_mode_set": ["lite"]
  }'

Response

previous is the limit before the change, or null if there was none. previous and current hold only credit_limit, action and auto_llm_mode_set; call List Usage Limits for the full rows.

{
  "previous": {
    "credit_limit": 500.0,
    "action": "block",
    "auto_llm_mode_set": null
  },
  "current": {
    "credit_limit": 750.0,
    "action": "auto_only",
    "auto_llm_mode_set": ["lite"]
  }
}

Delete Role Usage Limit

Remove a role's default limit for one period.

Endpoint

DELETE /v1/admin/tenants/{tenant_id}/usage-limits/roles/{role_id}?period={period}&role_source={role_source}

Query Parameters

  • period (required): monthly or weekly
  • role_source (required): default or custom, matching the role

Example Request

curl -X DELETE 'https://ai.hatz.ai/v1/admin/tenants/tenant_abc123/usage-limits/roles/role_O8oZwaNGyJoDVCeKAL8N84wx5W?period=monthly&role_source=default' \
  -H "X-API-Key: $HATZ_API_KEY"

Response

{
  "deleted": true,
  "previous": {
    "credit_limit": 750.0,
    "action": "auto_only",
    "auto_llm_mode_set": ["lite"]
  }
}

Deleting a limit that doesn't exist is not an error: it returns 200 with "deleted": false and "previous": null.

Set User Usage Limit

Create or replace a user's override for one period. The user must belong to the tenant.

Endpoint

PUT /v1/admin/tenants/{tenant_id}/usage-limits/users/{user_id}

Path Parameters

  • tenant_id (required): Tenant ID
  • user_id (required): User HashID

Request Body

  • period (required): monthly or weekly
  • credit_limit (required): Credits allowed per period (0 to 1,000,000,000,000)
  • action (required): block or auto_only
  • auto_llm_mode_set (required with auto_only, not allowed with block): One or more of lite, performance, turbo

role_source is not accepted here; sending it returns 422.

Example Request

curl -X PUT 'https://ai.hatz.ai/v1/admin/tenants/tenant_abc123/usage-limits/users/user_ExxypMkWV0PLDUAyLpdJlOEJ69' \
  -H "X-API-Key: $HATZ_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "period": "monthly",
    "credit_limit": 50,
    "action": "block"
  }'

Response

{
  "previous": null,
  "current": {
    "credit_limit": 50.0,
    "action": "block",
    "auto_llm_mode_set": null
  }
}

A user who is not in the tenant gets 400 with the generic message "Database request failed". A user ID that matches no user returns 404.

Delete User Usage Limit

Remove a user's override for one period. Their role default applies again.

Endpoint

DELETE /v1/admin/tenants/{tenant_id}/usage-limits/users/{user_id}?period={period}

Query Parameters

  • period (required): monthly or weekly

Example Request

curl -X DELETE 'https://ai.hatz.ai/v1/admin/tenants/tenant_abc123/usage-limits/users/user_ExxypMkWV0PLDUAyLpdJlOEJ69?period=monthly' \
  -H "X-API-Key: $HATZ_API_KEY"

Response

{
  "deleted": true,
  "previous": {
    "credit_limit": 50.0,
    "action": "block",
    "auto_llm_mode_set": null
  }
}

As with role limits, deleting an override that doesn't exist returns 200 with "deleted": false.

Error Responses

Errors use the standard envelope:

{
  "error": {
    "type": "HTTPException",
    "message": "Custom role not found",
    "details": {},
    "path": "/v1/admin/tenants/tenant_abc123/usage-limits/roles/role_O8oZwaNGyJoDVCeKAL8N84wx5W"
  }
}
Status When
400 A malformed tenant, role or user ID, or a tenant HashID that matches no tenant ("Invalid tenant ID format…"). Also a user override for a user outside the tenant, or an offset beyond total_count, both with "Database request failed".
401 Missing or invalid API key
403 The caller is not allowed to manage limits in this tenant (see Who Can Call These Endpoints)
404 A tenant UUID that matches no tenant, a user ID that matches no user, or a role_source that does not match the role ("Custom role not found", "platform role not found")
422 Invalid body or query: missing fields, unknown fields, block with modes, auto_only without modes, a limit outside 0 to 1,000,000,000,000, or a period other than monthly/weekly (type is RequestValidationError)