Skip to content

Object Storage

POST /v1/object-storage/buckets · scope objectstorage:write · reversible · idempotent

Returns the same resource as GET /v1/object-storage/buckets/{bucket}. The backend’s create call responds with the raw registry row —a different shape, with a different date format— so it is re-read before responding: it costs one call and buys create and read returning the same object.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets \
-X POST \
-H "Authorization: Bearer $TRUO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"backups"}'

operationId: objectstorage.buckets.create

DELETE /v1/object-storage/buckets/{bucket} · scope objectstorage:write · destructive — cannot be undone · idempotent

A bucket with objects is not deleted: the request fails and touches nothing. ?purge=true deletes it along with all its contents, and that cannot be undone — there is no trash bin and no versioning. To know how many objects will be lost, empty it first with POST .../empty, which returns the count.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups \
-X DELETE \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.buckets.delete

POST /v1/object-storage/buckets/{bucket}/empty · scope objectstorage:write · destructive — cannot be undone · asynchronous · idempotent

Deletes every object and keeps the bucket with its configuration. It cannot be undone. On a large bucket it can take a while: deletion runs object by object against the storage.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups/empty \
-X POST \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.buckets.empty

GET /v1/object-storage/buckets/{bucket} · scope objectstorage:read

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.buckets.get

GET /v1/object-storage/buckets · scope objectstorage:read

Includes buckets created directly through the S3 protocol, which have no registry row: they are listed anyway —hiding them would hide data that exists— with created_at set to null and private access.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.buckets.list

GET /v1/object-storage/buckets/{bucket}/metrics · scope objectstorage:read

Storage, egress, and requests for the requested range. The series carry one point per UTC day and come back empty until there is data, rather than being padded with zeros that would be indistinguishable from a day without traffic.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups/metrics \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.buckets.metrics

PATCH /v1/object-storage/buckets/{bucket} · scope objectstorage:write · reversible · idempotent

Making the bucket public mints an anonymous read URL (public_url) and keeps it if the bucket later goes private: republishing returns the same URL, not a new one.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups \
-X PATCH \
-H "Authorization: Bearer $TRUO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"access":"private"}'

operationId: objectstorage.buckets.update

POST /v1/object-storage/keys · scope objectstorage:keys · reversible · idempotent

The only endpoint that returns secret_access_key, and it returns it exactly once: it is not stored in plaintext on our side and there is no way to recover it later. If it is lost, the way out is to delete the key and issue another. Keys coexist: issuing one does not revoke the previous ones. Limit each one to a bucket with scope so that losing one does not compromise the rest.

Terminal window
curl https://api.truo.cloud/v1/object-storage/keys \
-X POST \
-H "Authorization: Bearer $TRUO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"production-backups"}'

operationId: objectstorage.keys.create

DELETE /v1/object-storage/keys/{key_id} · scope objectstorage:keys · destructive — cannot be undone · idempotent

Revocation is immediate. Revoking a key also invalidates the presigned URLs signed with it, even if they have not expired: the signature is validated against the key, and a revoked key no longer exists. It is the only way to cut off a presigned URL early.

Terminal window
curl https://api.truo.cloud/v1/object-storage/keys/AKIA7QF2K3M9XZ4NPRTV \
-X DELETE \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.keys.delete

GET /v1/object-storage/keys · scope objectstorage:read

Active keys only, and never the secret.

Terminal window
curl https://api.truo.cloud/v1/object-storage/keys \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.keys.list

POST /v1/object-storage/buckets/{bucket}/objects/delete · scope objectstorage:write · destructive — cannot be undone · idempotent

Batch delete by key. It is a POST rather than a DELETE because the key list goes in the body: not every HTTP client sends a DELETE with a body. It cannot be undone. deleted can be lower than the number of keys requested: keys that did not exist do not count.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups/objects/delete \
-X POST \
-H "Authorization: Bearer $TRUO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"keys":["photos/logo.png"]}'

operationId: objectstorage.objects.delete

GET /v1/object-storage/buckets/{bucket}/objects · scope objectstorage:read

One level at a time, like a file explorer: entries with is_folder: true are prefixes, navigated by passing their key as prefix. It does not accept limit: the backend sets the page size (up to 1000 entries) and trimming here would silently drop objects as the cursor advances.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups/objects \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.objects.list

POST /v1/object-storage/buckets/{bucket}/presign · scope objectstorage:read · reversible

Returns a link that works without credentials until it expires. method: "GET" to download (requires objectstorage:read), method: "PUT" to upload (requires objectstorage:write). The URL is a bearer credential: it works for anyone who holds it, and the only way to cut it off before it expires is to revoke the S3 key that signed it. Request the shortest TTL that works for you. It also inherits the scope of that key: if the key is limited to one bucket or is read-only, the URL can do no more than the key can.

Terminal window
curl https://api.truo.cloud/v1/object-storage/buckets/backups/presign \
-X POST \
-H "Authorization: Bearer $TRUO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"key":"photos/logo.png"}'

operationId: objectstorage.objects.presign

GET /v1/object-storage · scope objectstorage:read

Usage, endpoint, and status. It is a per-account singleton: there is no listing and no id to pass. Storage and object counts come from the latest daily snapshot, not a live scan, so a freshly uploaded object can take a while to show up in the totals.

Terminal window
curl https://api.truo.cloud/v1/object-storage \
-H "Authorization: Bearer $TRUO_TOKEN"

operationId: objectstorage.tenant.get