API standards
qibdo Cloud’s API follows the API Improvement Proposals (AIP).
Every service exposes the same resource-oriented shape, so once you learn how one service works, you know
how they all work.
Why AIP
Section titled “Why AIP”The API Improvement Proposals are a well-documented, openly
standardised set of rules, best practices, and patterns for API design. We adopted them
deliberately: rather than invent platform-specific conventions, every service inherits one mature,
consistent design language, the same one that large public clouds already use. Resources,
collections, and the verbs that act on them follow the same rules everywhere, so learning one
service lets you predict the rest, and an engineer who has used a public cloud is productive on
qibdo from day one.
That choice is reinforced by how the API is built. Each service is defined once in gRPC and Protocol Buffers, which gives us a single, strongly-typed, well-defined contract. A gateway then transcodes between REST/JSON and gRPC in both directions, following AIP-127 (HTTP and gRPC transcoding): REST clients call ordinary HTTP/JSON endpoints, gRPC clients use the typed interface, and both reach the exact same API. There is no separate, hand-written REST layer that can drift from the contract.
Because that one contract is the source of truth, the OpenAPI specification, the generated SDKs, and these reference pages are all derived from it. What you read here is what the API actually does.
Resource-oriented design
Section titled “Resource-oriented design”Resource-oriented design is the RESTful model: the API is organized around resources
(a VM, a bucket, a role) grouped into collections, each addressed by a URL and manipulated
with standard HTTP methods. qibdo adopts that model through AIP’s resource conventions
(AIP-121) and exposes it over REST by transcoding the gRPC
contract. URLs are hierarchical and name each parent in the path; the target resource is
identified by {id}, and parents are named by their resource type.
# A workspace in Taxonomy/taxonomy/v1/organisations/{organisation}/workspaces/{id}
# A virtual machine in Compute/compute/v1/workspaces/{workspace}/zones/{zone}/engines/qibdo/vms/{id}Most resources are scoped to a workspace, the boundary that every service uses to isolate your teams, environments, and projects (see Taxonomy).
Standard methods
Section titled “Standard methods”Five standard methods cover the lifecycle of every resource. The verb, URL, and request body are consistent across services:
| Method | HTTP | Path | Body |
|---|---|---|---|
| Get | GET | …/<collection>/{id} | (none) |
| List | GET | …/<collection> | (none) |
| Create | POST | …/<collection> | the resource |
| Update | PATCH | …/<collection>/{id} | the resource + an update mask |
| Delete | DELETE | …/<collection>/{id} | (none) |
For example, to create and then fetch a VM:
# Create (returns an operation, see Standard responses)curl --request POST \ --url https://api.qibdo.example.com/compute/v1/workspaces/$WS/zones/$ZONE/engines/qibdo/vms \ --header "Authorization: Bearer $QIBDO_API_TOKEN" \ --header 'Content-Type: application/json' \ --data '{ "name": "web-1", "cpu": { "v_cpus_boot": 2 } }'
# Getcurl --url https://api.qibdo.example.com/compute/v1/workspaces/$WS/zones/$ZONE/engines/qibdo/vms/$ID \ --header "Authorization: Bearer $QIBDO_API_TOKEN"Custom methods
Section titled “Custom methods”Actions that don’t map cleanly to create/read/update/delete use a custom method: a verb appended to the resource URL after a colon. Lifecycle actions on a VM, for instance:
POST …/vms/{id}:startPOST …/vms/{id}:stopPOST …/vms/{id}:restartPOST …/vms/{id}:suspendPOST …/vms/{id}:resumePOST …/vms/{id}:resetOther examples include …/workspaces/{id}:move and /iam/v1/tokens:revoke. Like the standard
mutations, these custom methods return an operation.
Updating resources
Section titled “Updating resources”Updates use PATCH with a field mask so you change only the fields you intend to:
- Send the resource with the fields you want to set, plus an
update_masklisting those field paths. Only the masked fields are written; everything else is left untouched. - Omit the mask to update every field present in your request body.
- Use
*as the mask for a full replacement (PUT-style semantics).
This makes partial updates safe and explicit: you never accidentally clear a field you didn’t send.
Listing: pagination, filtering, and ordering
Section titled “Listing: pagination, filtering, and ordering”Every List endpoint accepts exactly four standard query parameters, and nothing else for narrowing results:
| Parameter | Purpose |
|---|---|
page_size | Maximum items per page (default 20, capped at 100). |
page_token | Opaque cursor for the next page (from a prior response’s next_page_token). |
filter | An AIP-160 filter expression to narrow results. |
order_by | A comma-separated list of fields to sort by (append desc to reverse). |
There are no per-field filter parameters; all filtering goes through the single filter
string. See Filtering for the language, and
Standard responses for the list response shape.
Cross-collection reads
Section titled “Cross-collection reads”Some Get endpoints let you fetch a resource by its id without knowing which parent it lives
under, by using - as that parent path segment (AIP-159). For
example, to read a resource pool by id across every region and zone:
GET /topology/v1/regions/-/zones/-/resource-pools/{id}You can substitute - for any parent the endpoint marks as supporting it, and you need
permission at a scope that covers the resolved resource. Each resource’s reference notes which
parents accept -; List endpoints do not (listing resource pools, for instance, is scoped to a
single region and zone) and require every parent to be a concrete id.
Versioning
Section titled “Versioning”The major version is part of the path (/compute/v1/..., /iam/v1/...). A new major version
is introduced only for breaking changes and is served alongside the previous one; within a
major version, changes are additive and backward-compatible.
Conventions worth knowing
Section titled “Conventions worth knowing”snake_casefields. JSON field names mirror the Protobuf fields, insnake_case.- Server-managed fields are read-only. Fields such as
id,created, andupdatedare output-only; if you send them on create or update, they’re ignored. - Timestamps are RFC 3339. For example
2026-06-04T12:30:00Z.