Skip to main content
A tenant on your free plan should not be able to spend your monthly budget in an afternoon. Usage limits stop that, and they stop it before the model is called rather than after the bill arrives. Tenant tiers

A rule is four things

Rules combine. 200k tokens every 3 hours and €50 a month can both apply; every applicable rule is evaluated and the most restrictive one blocks. The scope choice is worth pausing on:

Tenant

One pool for the whole customer organisation.

Per subtenant

The same ceiling applied to each subtenant separately.

One subtenant

An override for a specific user — the trial account that needs more, or less.

Plans (tiers)

A tier is a named set of rules — Free, Pro, Enterprise — assigned to tenants.
Tiers are assigned by live reference, not by copy. A tenant stores which tier it is on; editing the tier propagates to every tenant on it immediately. Raising the Pro limit is one edit, not a migration.
One tier can be marked as the default, which is what a newly seen tenant gets without anyone assigning anything. A tenant’s own page shows the plan it is on, what it has consumed against each applicable rule, any ad-hoc override, and the history window by window: A tenant's usage against its limits
Each closed window is snapshotted with its consumption and its limit at the time, so utilisation stays meaningful even for sub-day windows that a cost aggregate could not reconstruct afterwards.

What happens at the ceiling

The request is refused with 429 before any model call, and Devic leaves a visible trace so the block is explainable rather than mysterious:
  • In a conversation, the chat is marked as paused by limit, with which rule blocked, the current value, the ceiling and when the window resets. The mark clears itself as soon as a later message goes through.
  • For an agent, a run is recorded in a LIMIT_EXCEEDED state. It is terminal — the queue does not pick it up again — and repeated blocked requests within the same window collapse into one marker rather than flooding the list.
Limit checking fails open. If the counter store is unreachable, the request is allowed rather than refused. Denying real customers because of an infrastructure blip is the worse failure of the two — but it does mean limits are a business control, not a security boundary.

Upgrading from your own checkout

The usual shape: your billing system completes a payment and calls Devic to move the tenant to the new plan.
The change is recorded with its source, so the history of who moved between plans and why is auditable. Counters can be reset at the same time — the natural thing when someone upgrades mid-window.
The tenant-admin endpoints are privileged. Keys restricted for browser use are refused at the gateway, so a key that ships in your bundle cannot promote its own tenant to Enterprise. Call these from your server.

Charging usage Devic didn’t measure

Not everything a tenant consumes goes through Devic. A batch job in your own product, a third-party transcription, credits you meter yourself — if they should count against the same allowance, push them in:
The amounts consume the tenant’s quota exactly like a call Devic measured: cross a window’s ceiling this way and the next real request is refused with the same 429. The response comes back with every rule’s usage after the injection, so the remaining allowance is visible without a second call. source is a free tag ([a-z0-9_-], defaults to external) that keeps the origin of injected usage separate. It is what lets the usage panel split a tenant’s consumption into what Devic measured and what was pushed in, per source — a bar sitting at 90% means something different depending on which half it came from. Each rule also reports externalConsumption, the injected slice of its current. Use the subtenant variant, /v1/tenant-admin/{tenantId}/subtenants/{subtenantId}/add-usage, to attribute the usage to one end user within the tenant.
add-usage only adds. Negative amounts are refused: clearing counters is what /usage-limits/reset is for. Like the rest of tenant-admin, it is a server-side call — a browser key cannot inject usage, and neither can a tenant session token acting on its own tenant.
A tenant with no plan and no ad-hoc rules has no quota to consume. The injection is still recorded for cost reporting, and the response says so with applied.countedTowardLimits: false.

Reading consumption

The read-only side lives in its own subtree, /v1/tenant-usage/*, safe to grant to a browser key — which is what lets a widget show a user how much of their allowance is left: