Skip to content
sistemo.io beta

Billing & usage

Read what you have spent, what it was spent on, and what is left in the wallet. Everything on this page is a GET and needs only a read-scope key.

The routes that move money — topping up, adding a card, opening the Stripe portal — are deliberately not reachable with an API key at all. They require a signed-in dashboard session. A leaked read-only key must not be able to change the card on file or start a payment.

Route What it answers
GET /v1/billing/balance How much credit is left
GET /v1/billing/rates What things cost right now
GET /v1/billing/usage What I consumed over a period
GET /v1/billing/usage/by-resource Which machine spent it
GET /v1/billing/usage/series Daily cost, for a chart

Everything is in micro-euros

…_micros fields are integers where 1 000 000 = €1. Money is never a float here. Divide by 1e6 only at the moment you display it.

Balance

GET /v1/billing/balance
{
  "balance_micros": 4780000,
  "tier": "free",
  "transactions": [],
  "trial_bonus_micros": 25000000,
  "trial_bonus_available": true,
  "tax_enabled": false,
  "has_payment_method": false
}
Field Meaning
balance_micros Credit remaining. May be negative — see below
tier free until your first real top-up, then payg
transactions Recent wallet movements (top-ups, refunds). [] when there are none
trial_bonus_micros The bonus adding a card would unlock
trial_bonus_available true only while it is still claimable
tax_enabled Whether VAT is being applied to top-ups
has_payment_method Whether a card is on file
depleted_at Only present at €0 — when the balance ran out
grace_days Only present at €0 — 3 (free) or 30 (paid)
deletion_at Only present at €0 — when idle resources get reclaimed

The last three are omitted entirely while the wallet is healthy, so test for their presence rather than for a zero value.

A negative balance is normal, not a bug

Compute hard-stops at €0, but storage keeps accruing on disks that still exist, so the balance can dip slightly below zero between the stop and your next top-up. It is not clamped, on purpose: clamping would break the balance == credits − debits identity that the nightly auditor checks. Top up and it clears.

The three depleted_at / grace_days / deletion_at fields are the countdown to your resources being deleted. If they are present, act on them.

Rates

GET /v1/billing/rates
{
  "vcpu_hour_micros": 35000,
  "ram_gb_hour_micros": 12000,
  "storage_gb_month_micros": 50000
}

Read this rather than hardcoding prices. It is the same rate card the meter charges from, so an estimate built on it cannot drift from the bill. Rates are effective-dated: a price change adds a new row and never rewrites what you were already charged.

Billing is per second, quoted per hour. There is no minimum and no rounding up to the next hour. Compute (vCPU + RAM) bills while a machine is running; storage bills while a disk exists, running or stopped.

Usage totals

GET /v1/billing/usage?from=&to=

from / to are RFC 3339 and default to the current billing month. The window is capped at 366 days.

{
  "vcpu_hours": 12.5,
  "ram_gb_hours": 12.5,
  "storage_gb_month": 0.42,
  "snapshot_gb_month": 0.0,
  "total_cost_micros": 458750,
  "tier": "free"
}

Per-resource breakdown

GET /v1/billing/usage/by-resource?type=&from=&to=&page=&page_size=&format=

The answer to "why was this month expensive". Cost-sorted, paginated, with a per-type subtotal.

Parameter Notes
type machine, volume or snapshot. Omit for all three
from / to RFC 3339; defaults to the current billing month
page / page_size Standard pagination
format=csv Streams every row as CSV for an accounting export
{
  "from": "2026-09-01T00:00:00Z",
  "to": "2026-10-01T00:00:00Z",
  "total_cost_micros": 458750,
  "by_type": [ { "type": "machine", "count": 3, "cost_micros": 441000, "pct": 96.1 } ],
  "resources": [
    { "type": "machine", "ref": "ee17cec6…", "name": "nightly-agent",
      "cost_micros": 402000, "pct": 87.6,
      "vcpu_hours": 11.2, "ram_gb_hours": 11.2,
      "storage_gb_months": 0.31, "snapshot_gb_months": 0.0 }
  ],
  "page": 1, "page_size": 50, "total": 4
}

A destroyed resource still shows up

Costs are attributed to the resource that incurred them, and the row survives the resource. A machine you deleted last week still appears in this month's breakdown with what it cost while it lived — which is exactly what you want when the bill is bigger than expected.

Pair this with the Activity log: this endpoint says which machine spent the money, the Activity feed says what it was doing and who started it.

Daily series

GET /v1/billing/usage/series?from=&to=

Daily cost split by resource type — what the dashboard's chart is drawn from.

[
  { "date": "2026-09-21", "compute_micros": 18400, "ram_micros": 6300,
    "storage_micros": 1700, "snapshot_micros": 0 }
]

Not available through the API

Why
Top up · add a card · billing portal Session-only. An API key must not be able to spend money or change the card on file
Invoices Not built yet. Top-ups are receipted by Stripe
Usage reported to Stripe Never happens. Stripe processes top-ups; metering is entirely ours
  • Usage & billing guide — the wallet, the grace window, worked cost examples
  • Quotas — the ceilings the wallet cannot express
  • Activity — who did what, including the spend guard stopping a machine