Per-User Spending Limits
Relai allows you to set dollar-based spending limits for individual end-users. This enables fine-grained cost control when building applications where multiple users consume AI resources.
How It Works
Pass the user field in your chat completion requests to identify end-users. Relai tracks spend per user and enforces quotas you configure.
{
"model": "anthropic/claude-sonnet-4",
"messages": [{"role": "user", "content": "Hello"}],
"user": "user_abc123"
}Quota Types
| Quota | Description | Resets |
|---|---|---|
| monthly_quota_dollars | Maximum spend per calendar month | 1st of each month (UTC) |
| daily_quota_dollars | Maximum spend per day | Midnight UTC |
Setting Quotas
Organization Defaults
Set default quotas that apply to all new users in your organization via the dashboard settings or API:
PATCH /v1/orgs/{org_id}/settings
{
"default_user_monthly_quota_dollars": 10.00,
"default_user_daily_quota_dollars": 1.00,
"default_alert_threshold": 0.8
}Per-User Overrides
Override defaults for specific users:
POST /v1/users
{
"external_id": "user_abc123",
"monthly_quota_dollars": 50.00,
"daily_quota_dollars": 5.00,
"alert_threshold": 0.9
}Soft Alerts (Warnings)
When a user exceeds their alert_threshold (default 80%), Relai adds a warning to the response. The request still succeeds.
Non-Streaming Response
Warnings appear in the relai.warnings array:
{
"id": "gen-abc123",
"choices": [...],
"usage": {...},
"relai": {
"warnings": [
{
"code": "end_user_quota_soft_threshold",
"message": "End user has reached 85% of monthly quota ($0.85 of $1.00)",
"period": "monthly",
"percent": 0.85
}
]
}
}Streaming Response
Warnings are sent as a final SSE event before [DONE]:
event: relai.warning
data: {"code":"end_user_quota_soft_threshold","period":"monthly","percent":0.85}
data: [DONE]Hard Caps (Blocking)
When a user reaches 100% of their quota, requests are rejected with HTTP 429:
{
"error": {
"code": "end_user_quota_exceeded",
"message": "End user monthly quota exceeded",
"type": "api_error"
}
}Important: Requests without a user field are unaffected and continue using the organization balance normally.
Checking User Spend
Get a user's current spend and quotas:
GET /v1/users/user_abc123
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"external_id": "user_abc123",
"monthly_quota_dollars": 10.00,
"daily_quota_dollars": 1.00,
"alert_threshold": 0.8,
"monthly_spend_dollars": 3.45,
"daily_spend_dollars": 0.72,
"created_at": "2026-05-01T10:00:00Z"
}User Management API
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/users | Create or update a user |
| GET | /v1/users | List all users with spend data |
| GET | /v1/users/{external_id} | Get user details and spend |
| PATCH | /v1/users/{external_id} | Update user quotas |
| DELETE | /v1/users/{external_id} | Delete a user |
Best Practices
- Set organization defaults — Configure sensible defaults so new users are protected automatically.
- Monitor warnings — Check for
relai.warningsin responses to notify users before they hit hard caps. - Use both quotas — Daily limits prevent runaway spend within a month; monthly limits control total cost.
- Adjust thresholds — Lower the
alert_thresholdfor users who need more warning time.
Example: SaaS with Tiered Plans
// Free tier: $1/month
await fetch("/v1/users", {
method: "POST",
headers: { "Authorization": "Bearer " + apiKey },
body: JSON.stringify({
external_id: user.id,
monthly_quota_dollars: 1.00,
daily_quota_dollars: 0.10,
}),
});
// Pro tier: $50/month
await fetch("/v1/users", {
method: "PATCH",
headers: { "Authorization": "Bearer " + apiKey },
body: JSON.stringify({
monthly_quota_dollars: 50.00,
daily_quota_dollars: 5.00,
}),
});Next Steps
- API Reference — Full endpoint documentation
- Error Codes — Handle quota errors gracefully