Buckets and objects
Storage uses a simple two-level model: workspace-scoped buckets that hold objects. This page explains what each one is and how it behaves. It stays conceptual; the API reference is where the exact fields, methods, and limits live.
Buckets
Section titled “Buckets”A bucket is a container for objects. Every bucket belongs to one workspace and is provisioned on a cloud provider. It has a human-readable name that is unique within its workspace, an optional description, and a default storage class, a reference to one of the storage classes available to it.
On qibdo’s own engine, a bucket lives in a single region, chosen when you
create it and fixed afterward, and supports versioning. With versioning on,
the service keeps prior copies of an object instead of discarding them when it
changes, so you can recover an earlier one. See
Object versioning below.
A bucket must be empty before it can be deleted. The service refuses to delete a bucket that still holds objects, so remove its objects first.
Objects
Section titled “Objects”An object is a single piece of stored data, for example an image, an archive, or
a backup, together with the metadata that describes it. Each object is
identified by a key within its bucket, a path-like string such as
images/2026/logo.png. The key looks like a file path, but objects live in a
flat namespace: the slashes are part of the name, not real folders. You can
still list objects by a shared prefix to browse them as if they were
directories.
Along with its bytes, every object carries metadata you can read without downloading the body:
- its size,
- a content type, the MIME type such as
image/png, - a checksum that fingerprints the stored content,
- the last-modified time,
- an optional set of user metadata key-value pairs you attach yourself,
- the storage class the object is stored in,
- and, when the bucket has versioning on, a version identifier.
Listing objects
Section titled “Listing objects”Object listings are narrowed with prefix and delimiter, not with the platform’s filter
parameter. prefix restricts results to keys that begin with a string, and delimiter collapses
everything after its next occurrence into a shared prefix, which is how a flat namespace is browsed
as though it had folders:
curl --get https://api.qibdo.example.com/storage/v1/workspaces/$WORKSPACE/engines/qibdo/buckets/$BUCKET/objects \ --header "Authorization: Bearer $QIBDO_API_TOKEN" \ --data-urlencode "prefix=images/2026/" \ --data-urlencode "delimiter=/"This listing accepts no filter, and that is a property of object storage rather than a gap in
the API. A bucket is a flat keyspace, not a table. There are no indexed columns for a predicate to be
evaluated against, so answering a query like “objects larger than 10 MB” would mean reading the
metadata of every object in the bucket and discarding most of it. On a bucket holding millions of
keys that is not a filter, it is a full scan billed to the caller.
What the keyspace is built for is ordered traversal by key, which is exactly what prefix and
delimiter express. Narrow by prefix first, then apply any further conditions on the page you get
back. Listing multipart uploads follows the same reasoning and takes prefix only.
Every other qibdo Cloud listing uses the AIP-160 filter language described in
Filtering.
Object versioning
Section titled “Object versioning”Versioning is a per-bucket setting with three positions, not two. Disabled, writing to an existing key replaces the object in place. Enabled, each write preserves the previous content as a distinct version, addressable by its own version identifier, so you can recover or roll back to an earlier copy. Suspended stops new versions being created but keeps every version already written, which goes on costing storage: it is not the same as off, and it is the state a bucket lands in when someone tries to turn versioning back off.
That last point is a one-way door. Once a bucket has been versioned it can be suspended but never returned to disabled, because the versions already written have to stay addressable.
The consequence worth knowing before you turn it on is what happens when you
delete. Upload images/logo.png twice and then delete it:
| Step | Versions of images/logo.png | Stored |
|---|---|---|
| upload | v1 (2.1 MB) — current | 2.1 MB |
| upload again | v1 (2.1 MB) — previous v2 (2.4 MB) — current | 4.5 MB |
| delete | v1 (2.1 MB) — previous v2 (2.4 MB) — previous v3 — delete marker | still 4.5 MB |
The object stops appearing in listings and reads return a not-found error, but nothing was deleted and nothing was freed — the delete added a marker rather than removing anything. That is what makes the deletion recoverable, and it is also why a versioned bucket keeps growing until you remove the versions themselves.
Object lifecycle covers this in full: how to recover a deleted object, and which operation actually frees storage.
Object integrity
Section titled “Object integrity”Every object carries a checksum derived from its content. Because identical content always yields the same checksum, you can compare the value the service reports against one you compute locally to confirm an upload or download arrived intact. Objects assembled from several parts use a checksum computed from those parts, so treat it as an identifier for that specific assembly rather than a plain digest of the whole.
Related concepts
Section titled “Related concepts”- Storage classes: how a bucket’s default storage class selects the tier objects are stored in.
- Create a bucket.