Account
Balance
One number, read from the gateway with a key, and a 402 that tells you where to add to it.
Live Built and working today on the surface this card describes.
What it does
The balance lives on the gateway, and GET /usage is where you read it. It is not on any of the billing endpoints, on purpose: money is owed in one place and reported from one place.
The figure to show as available is total_sparks, which is the allowance plus the balance plus any agreed overdraft. balance_micro in micro-CHF is the value of record and can be negative down to that overdraft.
When the credit block is absent, that deployment is not debiting a balance at all. Render that fact, never a zero.
A call the balance will not cover is refused with a 402 carrying insufficient_credit, whose message names the URL to add credit. Key on the code. The URL is text in that message, not a field of its own, and the balance is not in the envelope.
A new account gets a one-time welcome grant of 5,000 Sparks. Once, at signup.
Inputs and outputs
| Read it | GET /api/prima/v1/usage, with the X-API-Key header. |
|---|---|
| Available | credit.total_sparks, with credit.unit as the glyph to print beside it. |
| Value of record | credit.balance_micro, micro-CHF, integer, may be negative. |
| No ledger row yet | credit.exists: false. |
| Refused for lack of credit | 402, error.type: insufficient_quota, error.code: insufficient_credit. The message names the top-up URL; nothing carries it as a field. |
Configuration
| Credential | A gateway key. A signed-in Labs session is not accepted here. One the deployment can verify is refused with 503 identity_provider_unavailable and a Retry-After header, because the introspection half of that seam is not built; one it cannot verify is a 401 invalid_api_key, and the wiki records that the standalone service cannot yet verify a Labs JWT. Not measured on api.prima.li. |
|---|---|
| Where it is shown | The developer portal's account page, on the w6-konto branch of prima-developer. At sign-in the portal mints an ai key, POST /api/developer/keys with scopes: ["ai"] exactly, expires_in_days: 1 (the smallest expiry Labs accepts) and a name carrying the first eight characters of a local session id, and reads /usage, the tiers, the instruction and the history with it as X-API-Key and no Authorization header; the three writes, a top-up and PUT and DELETE on the auto top-up instruction, keep the session, and sign-out revokes the key. That is the chat's pattern and decision A-2 (a) of 2026-09-11: built, not deployed, not measured against api.prima.li. The chat's rail shows chat tokens used against the period's included amount, read from the same /usage call; it does not show the Sparks balance yet, and the panel that will is planned. |
Limits
- Sparks figures are floored.
balance_chfis a six-decimal string for display only; do not do arithmetic on it. - The allowance bucket is zero for every prepaid tenant, so allowance and balance are the same number today.
- The account page the 402's URL points at is built on the
w6-kontobranch and not deployed. Until it is, the link is the right destination and the page behind it is not there. - There is no per-alias and no per-day breakdown. The meter records both on every event; nothing exposes them.
Example
read the balance
curl https://api.prima.li/api/prima/v1/usage \
-H "X-API-Key: $PRIMA_API_KEY" Source of truth
prima/prima/credits.py (`get_account_state`: every field of the credit block, the floored Sparks, the negative floor at the credit limit, `exists`)prima/prima/errors.py (the 402: `insufficient_quota`, `insufficient_credit`, the top-up URL inside the message, and the deliberate absence of the balance)prima/prima/seams/identity.py (`_resolve_jwt`: a Labs token with an unknown `kid` or a failed signature is undecodable and, with no key, a 401 `invalid_api_key`)prima/prima/auth/sessions.py (`_unavailable()`: the 503 `identity_provider_unavailable` a verified Labs token reaches)philosophers_stone/platform/primaapi.md § Open items (a Labs JWT cannot yet be verified by the standalone service)prima-developer/src/lib/gateway-key.ts, branch `w6-konto` @ d5f9aa8 (the mint: `scopes: ["ai"]` exactly, `expires_in_days: 1`, one key per sign-in named after the session, revoked at sign-out; A-2 (a))prima-developer/src/lib/prima-api.ts, branch `w6-konto` @ d5f9aa8 (`auth: "key"`: `X-API-Key` and no `Authorization` on `GET /usage` and the three billing reads; the top-up and the `PUT` and `DELETE` on the instruction stay on the session; `signOut` revokes the key)philosophers_stone/operations/prima-onboarding-phase2-report.md § 5.A, the A-2 block (decided 2026-09-11: option (a), a per-sign-in `ai` key, revoked at sign-out)philosophers_stone/platform/primaapi.md § Self-serve signup (the one-time 5,000 Sparks welcome grant)philosophers_stone/operations/prima-onboarding-implementation-plan.md § D7 (the welcome grant is once, never per month) and § W6 (the account page, since built on `w6-konto` and not deployed)prima-chat/web/src/App.tsx (the rail prints `usage.chat.used` against `usage.chat.included`; no Sparks figure)philosophers_stone/operations/prima-onboarding-implementation-plan.md § D3 and § W5 (a compact billing panel inside the chat, planned)