Balance, tariff and charge estimate
const url = 'https://api.flotera.com/api/v1/billing';const options = { method: 'GET', headers: {cookie: '__Host-erm_session=<__Host-erm_session>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.flotera.com/api/v1/billing \ --cookie __Host-erm_session=<__Host-erm_session>Read-after-write view from Billing PG (short dedicated cache, never the generic 60 s dashboard TTL).
Authorizations
Section titled “Authorizations”Responses
Section titled “Responses”Billing view.
Wallet projection (14 §6.4): balance read after write from Billing PG, account lifecycle, subscription and the daily burn.
object
UUID (v7 for new entities; v4 accepted during migration).
May be negative: a daily charge is posted in full even when it takes the balance below zero. Debt is more honest than an under-charge (14 §3.4).
object
active — balance above zero, full plan capabilities.
grace — the daily charge took the balance to zero or below.
Nothing is taken away: the same capabilities, the same server-days,
the same charges. It exists so that a weekend without a payment does
not cost the tenant control of the farm (14 §3.4).
frozen — the grace deadline passed. No new server-days, telemetry is
acknowledged but not stored, and only the reads listed in 13 §5.4 stay
open. There is no active → frozen edge: a freeze always goes through
grace, so “frozen without warning” is impossible by construction.
Posting time of the charge that took the balance to zero or below.
Exact freeze boundary — always a UTC midnight, so a frozen day is frozen in whole and cannot be billed as a partially served day (14 §2.4). Repeated charges do not extend it: debt does not buy time.
RFC 3339 UTC with microsecond precision, or null.
Smallest top-up that takes the balance strictly above zero and therefore recovers the account. null when the account is active. The panel must show this number rather than let the user guess: paying exactly to zero does not unfreeze (14 §3.6).
object
Frozen price of the tenant’s current assignment, not the catalog row: a catalog price change must not restate what was already charged.
unassigned is not a plan: it means no assignment row exists yet, so nothing can be priced. Being on the free plan is active — free is a plan, not a subscription state (D-14).
object
UUID (v7 for new entities; v4 accepted during migration).
Direction at order time. It explains why the change is called a downgrade; it does not decide anything when the change fires — the rule is re-read then.
Internal catalog code. Not the public label — labels are not unique.
RFC 3339 UTC with microsecond precision.
First UTC day the new price applies to.
One day of the target plan at the current fleet size, when gated.
reserve_not_covered — the balance no longer covered the reserve when the change fired; direction_changed — the catalog price moved and an ordered downgrade would now be an upgrade, so it was refused instead of silently costing more.
RFC 3339 UTC with microsecond precision.
RFC 3339 UTC with microsecond precision, or null.
object
Billable managed server-days of the last closed UTC day (14 §2.4).
Decimal value serialized as a string, never a JSON number.
Current fleet size at the current daily rate. An empty paid fleet costs exactly zero — the price is per server and there is no landing fee — so this is 0 rather than a floor.
floor(balance / estimated_daily_charge_usd); null when nothing is being charged. Never render null as “unlimited”.
Spend of the current calendar month in timezone, computed by the same window expression that /billing/ledger?range=month cuts on. The invariant is load-bearing and tested: this tile equals minus the sum of the returned non-topup rows of the same period. Keeping it is a deliberate addition to the projection of 14 §6.4 — without it the journal and the tile could only be reconciled by eye.
When the next UTC day is posted: H+1:15 of the closed day.
IANA timezone the tenant’s calendar labels use. Settlement itself is UTC — this zone labels spent_mtd_usd and every /billing/ledger?range= window, so ledger timestamps must be rendered in it or rows and tiles describe different days.
RFC 3339 UTC with microsecond precision.
Example
{ "currency": "USD", "balance_usd": "12.340000", "lifecycle": { "state": "active" }, "subscription": { "status": "active", "pending_change": { "status": "scheduled", "direction": "upgrade", "effective_at": "2026-07-25T10:15:30.123456Z", "requested_at": "2026-07-25T10:15:30.123456Z" } }, "usage": { "yesterday_charge_usd": "12.340000", "estimated_daily_charge_usd": "12.340000" }, "spent_mtd_usd": "12.340000", "next_settlement_at": "2026-07-25T10:15:30.123456Z", "generated_at": "2026-07-25T10:15:30.123456Z"}Missing/invalid credentials (code=unauthorized).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Authenticated but not permitted. code=forbidden — role/scope mismatch; code=feature_not_entitled — the plan does not include the capability; code=account_frozen — the account is frozen and this operation is declared x-ermeon-frozen: deny. The three are deliberately distinct: only the last one is fixed by a top-up (13 §5.6).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}