Credits and limits
Two things are metered on the platform: AI credits and storage bytes.
They are capped separately, refused separately, and — importantly — scoped
differently. Everything below applies identically whether you call the API with
a dashboard session or with a VIITE_API_KEY.
The tiers
Section titled “The tiers”| Free | Pro (€25/mo) | |
|---|---|---|
| Seats | 1 | 5 (more if you buy more) |
| AI credits | 5,000 one-off | 10,000 one-off |
| Storage | 100 MB | 1 GB |
The AI allowance is one-off, not monthly — it is a grant, not a refill. Every user starts with 5,000 credits; activating Pro tops the subscribing owner up by another 5,000. When it runs out you buy top-ups (10,000 / 25,000 / 100,000-credit packs at €10 / €25 / €100 — €1 buys 1,000 credits) rather than waiting for a reset. Storage is a standing ceiling: delete assets and the space comes back.
What spends a credit
Section titled “What spends a credit”Anything that calls a language or speech model on the platform’s account:
- the AI job steps (
agent,enrich,analyze,triage,implement_task,tts); - the social and blog composers (
createSocialFromLink,createBlogFromLink,createBlogFromPostDraft); - text-to-speech synthesis.
Deterministic steps never spend anything, and hybrid steps (watch,
collect_invoices) degrade to their deterministic behaviour rather than
refusing when there is no allowance left.
Charging is metered on actual token usage with a markup, so a single call typically costs a few to a few hundred credits. Charges are always whole credits, rounded up, with a minimum of 1 — your balance and every amount you read back is a whole number. Read your balance any time:
const credits = await client.credits.getMyBalance();Scoping: credits are per-user, storage is per-org
Section titled “Scoping: credits are per-user, storage is per-org”This trips people up, so it is worth stating plainly:
- Storage is scoped to the organization. Every member’s uploads count against the same ceiling.
- Credits are scoped to the user. An API key spends the balance of the admin who minted it — not a shared org pool.
So two keys minted by the same admin draw on one balance, while keys minted by two different admins draw on two. If you want a predictable meter for a server-side integration, mint its key from a single dedicated admin account — and note that a Pro org’s extra grant lands on the owner’s balance, so a key minted by a different admin sees only that admin’s own starting 5,000.
Being refused: HTTP 402
Section titled “Being refused: HTTP 402”Both limits refuse with 402 Payment Required and a message naming the limit you hit. Out of credits:
Out of credits — your plan’s one-time AI allowance is used up. Buy more credits or upgrade at /upgrade.
Over the storage ceiling:
Storage limit reached: this plan allows 100.0 MB, and this organization is already using 101.0 MB. Upgrade for more storage at /upgrade.
The refusal happens before the expensive work: no model is called and no bytes are written, so a 402 costs you nothing and is safe to retry after topping up. Handle it by status, not by string:
import { ApiRequestError } from '@viite-ai/platform-sdk';
try { await client.tasks.process(linkId);} catch (error) { if (error instanceof ApiRequestError && error.status === 402) { // Top up, then retry — nothing was consumed. }}Per-type upload caps
Section titled “Per-type upload caps”Independently of the quota, uploads are capped per media type (5 MB images, 50 MB audio). A file over its type cap is refused whatever your plan.
