Watch your credits and scale down

Credits are prepaid, so running out blocks API calls instead of creating a bill. Topping up is human-only, so your job is to see it coming early enough that your human can act, and to cut the spend when it is more than the work needs.

What to poll

GET /v1/billing/balance

It carries what is left, split grant vs paid, the spend per hour, and runway_hours, the hours left at that rate. Watch runway_hours: the balance alone does not tell you how long you have.

Responses also carry an X-Credits-Low header once the balance is close enough to the cutoff to act on, so it reaches you on calls you were making anyway. Read the balance when you see it.

Where the money is going

GET /v1/usage?group_by=meter       which meter the money goes to
GET /v1/usage?group_by=resource    which VM, volume or snapshot

The hour in progress is flagged provisional until it closes; windows and the other fields: Usage and billing.

GET /v1/billing/ledger is the full record, newest first, every debit linked to the usage that caused it. It is mostly debits, so ?exclude=debit shows whether a payment arrived.

Scale down

Start from the meter at the top of group_by=meter, and do it while there is runway left: every call below is a mutation, and the cutoff blocks those.

Stopping a VM stops its RAM charge and nothing else — the root disk, the address, its snapshots and its volumes bill whether it runs or not (lifecycle).

Cut what you do not use

In this order:

  1. Delete snapshots you do not need (snapshot-* meters). Each bills at half the rate of the storage it covers, for as long as it exists; deleting it stops the charge within the minute.
  2. Delete detached volumes (volume-tb-hours). A detached volume costs the same as an attached one.
  3. Delete stopped VMs (disk-tb-hours, ip-hours). Their disk and address bill whether they run or not.
  4. Stop what is idle. Last, because it saves only the RAM charge.

Shrink what you use

When the spend is still too high for the work:

Copy to a smaller volume

POST /v1/volumes {"name":"data2","size_gb":250}   + Idempotency-Key
POST /v1/volumes/{new}/actions {"type":"attach","vm_id":"vm_..."}

# in the guest: make a filesystem on the new disk and mount it, copy with
# rsync -aHAX, stop whatever writes to the old one, copy again, then point
# /etc/fstab at the new UUID and unmount the old

POST /v1/vms/{id}/actions      {"type":"stop"}
POST /v1/volumes/{old}/actions {"type":"detach"}
POST /v1/vms/{id}/actions      {"type":"start"}
DELETE /v1/volumes/{old}

The detach refuses a volume the VM's snapshots include (409 volume_in_snapshots, naming them); delete those first. Both volumes bill, and count against the project's volume quota, until the old one is deleted. Mounting by UUID: Volumes.

When it reaches zero

402 credit_cutoff. Mutating calls are blocked; reads stay open, and so do all of /v1/support and /v1/compliance, because case deadlines keep running at zero. Running VMs are not killed.

After 7 days at zero the VMs are stopped, disks intact, and 30 days after that anything still there is deleted. A top-up at any point resumes everything.

Getting more

POST /v1/billing/topup and PUT /v1/billing/refill answer 403 human_required, always, and retrying does not help. GET /v1/billing/refill works with your key and reports the automatic refill ceiling — read it before assuming a refill will cover what is coming.

So: watch runway_hours, tell your human what is spending and how long is left, and scale down when the spend is more than the work needs or they are not reachable. Top-ups happen in the dashboard, so there is no request to give them.

Reference: Usage and billing.