Skip to main content

Cost Limits

The platform gives you three independent spending ceilings. Each is set in a different place, each covers a different scope, and none of them changes what you are charged. A limit refuses requests; it never alters your prices.

LimitScopeWindowSet fromWho can set it
Personal daily limitYour own requestsOne day, UTCProfileYou
Organization spending capEvery memberOne billing periodBillingOwners and admins
Per-API-key daily spend capOne API keyOne dayAPI KeysThe key's creator
The first ceiling reached wins

These are independent ceilings, not a hierarchy you configure in one place. A request is refused as soon as it would cross any of them. Setting a generous organization cap does not lift your personal daily limit, and clearing your personal limit does not lift a cap on the key you are using.

All three refuse with HTTP 402 and an insufficient_quota error carrying a distinct error.code, so your client can tell which ceiling stopped it and act on the right one. The full list is in Error Handling.

On a prepaid account there is a fourth ceiling you do not configure — your own wallet balance. See Your balance is a ceiling too.

Personal daily limit

Your own daily spending ceiling. Once your spend for the day reaches it, your requests are refused until the limit resets. Nobody else's traffic is affected.

Viewing and setting it

  1. Open Profile in the sidebar.
  2. Find the Daily Spending Limit section.

The section shows your Effective Limit, the badge naming where it comes from, and the Maximum allowed for your account.

To set your own value, enter it under Set Custom Limit and save. To go back to whatever your organization or the platform provides, use Reset to Default.

Where the limit comes from

Your effective limit is the lowest applicable ceiling. The badge names its source:

BadgeMeaning
Custom LimitYou set this value yourself
Organization LimitYour organization's ceiling applies
Platform DefaultThe platform-wide default applies

A plan can also carry a ceiling. If you set a custom limit above what your plan permits, the value is clamped to the plan's ceiling and reported back as coming from the plan rather than from you.

Constraints

  • Minimum $0.01.
  • You cannot exceed your organization's limit. Attempting to shows "Cannot exceed organization limit of ${max}."
  • Setting a lower value than the default is always allowed; that is the normal use.

Resets

Daily limits reset at midnight UTC, and the alert thresholds below reset with them.

What happens at the limit

Your requests are refused with HTTP 402 and the error code daily_cost_cap_exceeded, carrying a Retry-After header and a reset_at counting down to midnight UTC. The message names the amounts -- what you have spent against what you are allowed -- and points at the Profile page, because raising your own limit lifts the block immediately. Playground requests fail with the same message. Requests from your colleagues are unaffected.

A spend stop is a 402, not a 429

This refusal used to be a 429. An OpenAI-compatible SDK maps 429 to RateLimitError and does not map 402, so client code that caught this as a rate-limit error and backed off needs an explicit 402 branch. See migrating your error handling.

Organization spending cap

The ceiling most organizations actually reach. It is set per billing period, it is self-service, and it applies to every member of the organization at once.

Owners and admins set it from the Organization spending cap card on Billing. The field is Cap per billing period (USD); the value must be greater than zero with at most two decimals, and a new cap applies from your next API request with no waiting period.

Zero is not a way to switch the cap off. Use Remove cap.

What happens at the cap

Requests from every member are refused with HTTP 402 and the error code payg_spend_cap_exceeded. The refusal states the period's spend against the cap and names the Organization spending cap control on the Billing page as the place to change it -- there is no operator-side lever to raise it for you. Raising or removing the cap restores service within about a minute. If the cap is left alone, requests resume when the billing period ends. The portal shows the same amounts and the same remedy when a request is refused in the browser.

A depleted prepaid wallet is a different refusal, reported as a wallet-balance block rather than a spend-cap one, and it is fixed by adding credits rather than by touching the cap. See Your balance is a ceiling too and Error Handling.

The cap counts more than your bill

The cap is measured against all usage recorded in the period, at its full undiscounted cost and at the prices that apply to your organization. That total includes usage already covered by a plan or a commitment, and it includes audio spend. If a price has been negotiated for you, that is the price the cap counts, not the list price. The figure it watches can therefore be well above the amount you are invoiced. Treat it as a traffic ceiling rather than a budget.

The request that crosses the cap still completes and is still billed; the next one is refused. Usage can therefore end slightly above the number you set.

If your organization has no open billing period, the cap is not applied.

Per-API-key daily spend cap

A ceiling on a single key, useful for containing one application or one environment without touching anyone's personal limit.

Set it when creating the key: expand Advanced settings and fill in Daily spend cap (USD). The help text reads "Requests stop when this key reaches its daily spend cap."

Once the key reaches its cap, requests presented with that key are refused with HTTP 402 and the error code api_key_spend_cap_exceeded. Other keys, including other keys belonging to you, carry on.

The cap covers the realtime WebSocket path as well as ordinary HTTP requests, so a key cannot spend past its cap by switching transport.

Raising the cap lifts the block straight away. If the key's cap is raised, the block clears on the next request instead of latching until midnight UTC. The refusal message names the daily reset as the way out, and that still works too -- it is simply no longer the only one.

See API Keys.

Your balance is a ceiling too

The three limits above are ceilings you configure. On a prepaid account there is a fourth you do not: your wallet balance.

The estimated cost of a request is held against your available balance before the request runs, and released when it ends. If the whole estimate cannot be covered, nothing is held and the request is refused with HTTP 402 and the error code insufficient_credits, carrying limit_type: wallet_balance. Nothing is charged for a refused request, and the same request succeeds on a plain retry once you have added credits.

What that means in practice:

  • Concurrency no longer gets past your balance. Requests sent at the same time each take their own hold, so the ones your balance covers run and the rest are refused. Previously a burst could be admitted against one balance and overshoot it.
  • A single oversized request is refused before it starts, not after the tokens have been generated. The estimate is the worst case — your input plus the largest output the request could produce, its max_tokens or a platform default.
  • Audio is priced exactly, not estimated, and is refused before the request is sent upstream.
  • A realtime session that runs out of balance mid-session closes cleanly rather than failing as a transport error.
  • A held amount is not a charge. You pay for the usage you actually got; the hold is released when the request finishes.

This ceiling does not apply to a postpaid account, which is admitted against its credit limit instead (credit_limit_exceeded / no_credit_line), nor to usage covered by a plan's included allowance.

The full code table and the branching advice are in Error Handling; the wallet side is described under Billing.

Spending alerts

When you have a personal daily limit configured, the platform emails you as you approach it, so you can adjust before requests stop.

ThresholdTrigger
80%Your daily spend reaches 80% of your effective limit
90%Your daily spend reaches 90% of your effective limit

Each email includes your current spend for the day, your daily limit, and the reset time.

  • One alert per threshold per day. You will not receive duplicates for the same threshold.
  • Alerts are informational. Your access continues normally until you reach 100%.
  • Thresholds reset daily, alongside the limit itself at midnight UTC.

Choosing sensible limits

During development, set a low personal limit. It caps the damage from a retry loop or a runaway test, and it costs nothing to raise later.

In production, size the organization cap from your observed usage with headroom for legitimate spikes, remembering that it is measured at list price, so it should sit comfortably above what you expect to be billed. Give each application its own API key with its own daily spend cap so one misbehaving integration cannot consume the whole organization's ceiling.

To review what you have been using, open Usage for volume and Billing for value.

API Reference

warning

Cost limit endpoints require JWT authentication (login with email and password). API keys cannot access them.

The personal daily limit is managed through three endpoints. The organization spending cap has its own endpoints, documented under Billing.

Get your daily limit

curl https://api.bulutistan.ai/api/v1/profile/cost-limit \
-H "Authorization: Bearer <your-jwt-token>"
{
"cost_per_day": 30.00,
"effective_limit": 30.00,
"source": "user",
"tenant_limit": 50.00
}
FieldDescription
cost_per_dayYour custom daily limit, or null when you are on a default
effective_limitThe limit that actually applies
sourceWhere the effective limit comes from: user, tenant, plan or platform
tenant_limitYour organization's limit, and the maximum you may set

Set your daily limit

curl -X PUT https://api.bulutistan.ai/api/v1/profile/cost-limit \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{ "cost_per_day": 25.00 }'

The body carries exactly one field, cost_per_day, between 0.01 and 100000. Any unrecognised field in the body is rejected with 422. The response has the same shape as the GET.

Reset to the default

curl -X DELETE https://api.bulutistan.ai/api/v1/profile/cost-limit \
-H "Authorization: Bearer <your-jwt-token>"

Clears your custom value. The response is the same shape, with cost_per_day now null and source falling back:

{
"cost_per_day": null,
"effective_limit": 50.00,
"source": "tenant",
"tenant_limit": 50.00
}

Python example

import requests

jwt_token = "<your-jwt-token>"
base_url = "https://api.bulutistan.ai"
headers = {"Authorization": f"Bearer {jwt_token}"}

limit = requests.get(
f"{base_url}/api/v1/profile/cost-limit", headers=headers
).json()
print(f"Effective limit: ${limit['effective_limit']} (from {limit['source']})")

updated = requests.put(
f"{base_url}/api/v1/profile/cost-limit",
headers={**headers, "Content-Type": "application/json"},
json={"cost_per_day": 20.00},
).json()
print(updated)