Inventory and monitoring
Almost every client needs a fleet summary: how many VMs there are, how many are running, how many are being created, how many are broken. You neither need to nor should compute that by walking list pages — there are server-side counts that do not depend on project size.
One request for the whole summary
The counts endpoint returns total plus two breakdowns: byStatus over lifecycle statuses and
byPowerState over power. The counts are computed server-side, so they stay accurate no matter how many
VMs the project holds.
curl --request GET \
--url 'https://api.zennohosting.com/v1/projects/{projectId}/vms/state-counts' \
--header 'Authorization: Bearer <token>' \
--header 'Accept: application/json'
Reading the two breakdowns
All five statuses are always present in
byStatus: a status with no VMs is reported as0. The fields sum tototal.Each
byStatusfield equals the number of rows the VM list returns for the matchingstatus==filter on the same data. That makes "count tile → filtered list" navigation exact.byPowerStatehas onlyrunningandstopped. VMs that do not have a power state yet, because they are still being created, are excluded — so these two fields can sum to less thantotal. That is expected behaviour, not a data mismatch.
The counts are not cached
Two calls made while VMs are changing may return different numbers. For a dashboard that is fine: do not build logic that assumes two consecutive responses agree, and do not reconcile the counts against a list fetched by a separate request at a different moment.
Project-level counts
A project response carries resourceCounts with vms, networks and
publicIps. That is what a project list needs: one request per project, no walking nested collections.
The vmCount field in the same response is deprecated — use resourceCounts.vms.
When you do need the list
Counts answer "how many". When you need "which ones", use the VM list with paging, sorting and filters.
pagestarts at 1;pageSizedefaults to 20 and the server clamps it to 1–100.Sorting goes through
sorts, where a-prefix means descending. VMs default to-createdAt,name.Filters go through
filtersasfield<operator>value, for examplestatus==activeorcpu>=4. Each endpoint documents its own allow-list of fields in the reference.
curl --request GET \
--url 'https://api.zennohosting.com/v1/projects/{projectId}/vms?page=1&pageSize=20&filters=status==active&sorts=-createdAt,name' \
--header 'Authorization: Bearer <token>' \
--header 'Accept: application/json'
- 1
Build the summary on counts
One request per project gives you "total", "running", "creating" and "needs attention" tiles. Do not start from the list: on a large project that is dozens of requests for numbers the server already has.
- 2
Wire each tile to a filtered list
Clicking a status count opens the list filtered by
status==for the same value, and the numbers agree because both come from the same data. - 3
Surface failed separately
failedmeans the resource will not recover on its own and the provider's team has to step in. It is the only status worth flagging as actionable — the others clear by themselves. - 4
Add what is left of the quota
Next to the summary it helps to show the remainder from
GET /limits: how many VMs, networks and addresses can still be created, and how much CPU, memory and disk is left.
VM metrics are not usable yet
The metrics endpoint exists but currently returns deterministic mock data — wiring real metrics is a separate pending task. Do not build charts or alerts on it: the response shape is in the reference, but until it is wired up, do not present those numbers in a UI as if they were real.
Related endpoints
/projects/{projectId}/vms/state-countsSummarise a project by VM status and power state.
/projects/{projectId}/vmsList VMs with filters and sorting.
/projectsList projects together with their resourceCounts.
/limitsShow remaining quota next to the summary.
/projects/{projectId}/operationsInvestigate why a VM ended up in an unexpected state.