Skip to main content

Object storage buckets API endpoints

These endpoints manage Cloider object storage buckets: create and delete them, read their endpoint and usage, make them public or private, serve them as static websites, and set bucket policies, versioning, lifecycle and CORS rules. To read and write the files inside a bucket you normally use any S3 client with an access key; the API's own file endpoints are on Bucket objects.

All paths are relative to https://cloider.com/api. See Authentication for the token header.

At a glance​

MethodPathAccess
GET/bucketsRead
POST/bucketsWrite
GET/buckets/regionsRead
GET/buckets/:hashed_idRead
GET/buckets/:hashed_id/statusRead
GET/buckets/:hashed_id/usageRead
PUT/buckets/:hashed_id/visibilityWrite
GET/buckets/:hashed_id/websiteRead
PUT/buckets/:hashed_id/websiteWrite
PUT/buckets/:hashed_id/policyWrite
DELETE/buckets/:hashed_id/policyWrite
GET/buckets/:hashed_id/versioningRead
PUT/buckets/:hashed_id/versioningWrite
GET/buckets/:hashed_id/lifecycleRead
PUT/buckets/:hashed_id/lifecycleWrite
GET/buckets/:hashed_id/corsRead
PUT/buckets/:hashed_id/corsWrite
DELETE/buckets/:hashed_idWrite

The bucket object​

{
"hashed_id": "b7r2x",
"bucket_name": "acme-assets",
"region": "eu-central-2",
"public": true,
"policy": null,
"status": "Ready",
"size_bytes": 734003200,
"size_sampled_at": "2026-10-20T09:00:04.118230Z",
"website": false,
"website_index": "index.html",
"website_error": "",
"endpoint": "https://s3.eu-central-2.cloider.com",
"url": "https://acme-assets.s3.eu-central-2.cloider.com",
"website_url": "",
"created_at": "2026-09-30T15:12:48.551021Z"
}
FieldTypeDescription
hashed_idstringThe bucket's id
bucket_namestringThe S3 bucket name. Unique across all of Cloider, and fixed once created
regionstringThe region code, for example eu-central-2
publicbooleantrue when anyone can read an object by its URL without a key. Listing stays private either way
policystring or nullThe bucket policy as you wrote it, a JSON document in a string, or null
statusstringCreating, Ready, Terminating or Failed
size_bytesintegerBytes stored, as of the last usage sample
size_sampled_atstring or nullWhen size_bytes was measured
websitebooleantrue when the bucket is served as a static website
website_index, website_errorstringThe website's index document (index.html by default) and error document (empty for the built-in page)
endpointstringThe region's S3 endpoint, for S3 clients
urlstringThe bucket's own address, https://<bucket>.<endpoint host>. Public objects are at <url>/<key>
website_urlstringThe website's address, https://<bucket>.s3-website.eu-central-2.cloider.com, while website is on, otherwise empty
domainsobject listOnly from GET /buckets/:hashed_id, and only when domains serve the website: each {"domain_name", "domain_type"} with a Bucket target pointing at it. domain_type is Subdomain or CustomDomain
created_atstringWhen the bucket was created

List buckets​

GET /buckets

Returns the account's buckets, newest first, without deleted ones.

Access: any token.

curl https://cloider.com/api/buckets \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
[
{
"hashed_id": "b7r2x",
"bucket_name": "acme-assets",
"region": "eu-central-2",
"public": true,
"policy": null,
"status": "Ready",
"size_bytes": 734003200,
"size_sampled_at": "2026-10-20T09:00:04.118230Z",
"website": false,
"website_index": "index.html",
"website_error": "",
"endpoint": "https://s3.eu-central-2.cloider.com",
"url": "https://acme-assets.s3.eu-central-2.cloider.com",
"website_url": "",
"created_at": "2026-09-30T15:12:48.551021Z"
}
]

List regions​

GET /buckets/regions

Returns the regions a bucket can be created in, each with the S3 endpoint its buckets answer on.

Access: any token.

curl https://cloider.com/api/buckets/regions \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
[
{"code": "eu-central-2", "name": "Europe", "endpoint": "https://s3.eu-central-2.cloider.com"}
]

Create a bucket​

POST /buckets

Creates a bucket. Unlike clusters and databases, a bucket is created while the request runs, which takes a few seconds, so the answer also tells you whether the name was free.

Access: Read & Write token.

Request body​

FieldTypeRequiredDescription
bucket_namestringYes3 to 63 characters: lower case letters, digits and -, starting and ending with a letter or digit. No dots. Names are shared by every Cloider account, so pick something specific
regionstringNoA region code from GET /buckets/regions. Default eu-central-2
publicbooleanNotrue to let anyone read objects by URL. Default false
versioningbooleanNotrue to keep every version of every object from the start. Default false
websitebooleanNotrue to serve the bucket as a static website from the start, with index.html as its index document. Needs public, or the request fails with an error under website. Default false
curl -X POST https://cloider.com/api/buckets \
-H "Authorization: Bearer $CLOIDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"bucket_name": "acme-backups", "region": "eu-central-2", "versioning": true}'
Response
{"hashed_id": "k5t1v"}

Check GET /buckets/k5t1v/status once: it is normally Ready right away.

Errors​

StatusFieldMessage
400bucket_nameBucket name must not be empty, Bucket name must be at least 3 characters, Bucket name must not exceed 63 characters, Bucket name can only have lowercase letters, numbers and "-", Bucket name must start and end with a letter or a number, Bucket name is reserved, This bucket name is already taken
400regionInvalid region
400_Free plan users can not create more than one bucket. UPGRADE NOW!
400_Your account is suspended. Upgrade to a paid plan to continue using our services.
400_Buckets aren't available at the moment!, Operation failed, Couldn't create the bucket!
403_This API token is read only!, or You have read-only access to this account, you can not create buckets! for a Restricted member

These names are reserved: names starting with xn--, sthree- or amzn-s3-demo-, names ending with -s3alias, --ol-s3, --x-s3 or --table-s3, and the name filemeta.

Get a bucket​

GET /buckets/:hashed_id

Returns one bucket, in the shape above. For a website bucket served on domains, it also has domains.

Access: any token.

curl https://cloider.com/api/buckets/s3w8q \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response (trimmed)
{
"hashed_id": "s3w8q",
"bucket_name": "acme-site",
"public": true,
"status": "Ready",
"website": true,
"website_index": "index.html",
"website_error": "404.html",
"url": "https://acme-site.s3.eu-central-2.cloider.com",
"website_url": "https://acme-site.s3-website.eu-central-2.cloider.com",
"domains": [
{"domain_name": "docs.example.com", "domain_type": "CustomDomain"}
]
}

A deleted bucket, or an id of another account, answers 404 Not Found (plain text).

Get a bucket's status​

GET /buckets/:hashed_id/status

Returns the status as plain text: Creating, Ready, Terminating or Failed.

Access: any token.

curl https://cloider.com/api/buckets/b7r2x/status \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
Ready

Once a deletion has finished, this answers 404.

Get a bucket's usage​

GET /buckets/:hashed_id/usage

Returns the bucket with its storage usage and cost: the last 31 days in daily_usage and this month's totals in monthly_usage. It is the bucket's entry from GET /usage.

Access: any token.

curl https://cloider.com/api/buckets/b7r2x/usage \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response (trimmed)
{
"hashed_id": "b7r2x",
"bucket_name": "acme-assets",
"status": "Ready",
"size_bytes": 734003200,
"daily_usage": [
{
"resource_type": "bucket",
"date": "2026-10-19T00:00:00Z",
"total_cost": 0.0042,
"metrics": {"storage": 0.68, "storage_cost": 0.0042}
}
],
"monthly_usage": {
"avg_storage_usage": 0.66,
"storage_total_cost": 0.08,
"total_cost": 0.08,
"days": 19,
"forecast_this_month": 0.13,
"forecast_next_month": 0.13
},
"forecast_rest_of_day": 0.002,
"date": "2026-10-20T00:00:00Z",
"month": "October 2026"
}

storage and avg_storage_usage are in GiB. 404 with Bucket not found! for an unknown id. See Usage and billing.

Make a bucket public or private​

PUT /buckets/:hashed_id/visibility

Makes the bucket public, so anyone can download an object from <url>/<key> without a key, or private again. Listing the bucket's contents always needs a key.

Access: Read & Write token. The bucket must be Ready.

FieldTypeRequiredDescription
publicbooleanYestrue for public, false for private
curl -X PUT https://cloider.com/api/buckets/b7r2x/visibility \
-H "Authorization: Bearer $CLOIDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"public": true}'
Response
{"success": true}
StatusMessage
400The bucket must be ready to change its visibility.
400The bucket's policy allows everyone ("*"), remove those statements first. (making it private while the policy grants everyone access)
400The bucket's website needs it public, turn the website off first. (making it private while its website is on)
400Another change to this bucket is in progress, try again in a moment!
400Couldn't change the bucket's visibility, try again in a moment!
403This API token is read only!, You have read-only access to this account, you can not change buckets!

See Public and private buckets.

Get a bucket's website​

GET /buckets/:hashed_id/website

Returns the bucket's static website settings.

Access: any token.

curl https://cloider.com/api/buckets/s3w8q/website \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
{
"enabled": true,
"index_document": "index.html",
"error_document": "404.html",
"url": "https://acme-site.s3-website.eu-central-2.cloider.com"
}
FieldTypeDescription
enabledbooleanWhether the bucket is served as a website
index_documentstringThe file served for / and every path ending in /, index.html by default
error_documentstringThe key served with a 404 for anything missing. Empty for the built-in page
urlstringThe website's address while enabled, otherwise empty

Turn the website on or off​

PUT /buckets/:hashed_id/website

Turns the bucket's static website on or off and sets its documents. Every field is applied, so send the ones you want to keep too. Changes take up to about 30 seconds to show on the website. To serve the website on a domain, create a Bucket target.

Access: Read & Write token. The bucket must be Ready, and public to turn the website on.

FieldTypeRequiredDescription
enabledbooleanYestrue to serve the bucket as a website, false to stop
index_documentstringNoA file name without /, up to 255 characters. Empty means index.html
error_documentstringNoA key in the bucket, up to 1024 characters, not starting with / and without . or .. segments. Empty means the built-in page
curl -X PUT https://cloider.com/api/buckets/s3w8q/website \
-H "Authorization: Bearer $CLOIDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true, "index_document": "index.html", "error_document": "404.html"}'

The response has the shape of GET /buckets/:hashed_id/website.

StatusFieldMessage
400index_documentThe index document is a file name without a slash, like index.html
400error_documentThe error document is a key in the bucket, like 404.html, not starting with a slash
400_Make the bucket public first, its website is read without a key.
400_Domains still point at this website, remove their targets first. (turning it off while Bucket targets point at it)
400_The bucket must be ready to change its settings., Another change to this bucket is in progress, try again in a moment!
403_This API token is read only!, You have read-only access to this account, you can not change buckets!

Set a bucket policy​

PUT /buckets/:hashed_id/policy

Sets the bucket's policy, an AWS style JSON document that allows or denies S3 actions to access keys or to everyone. The policy replaces any previous one. It is checked before it is applied, and a rejected policy says why.

Access: Read & Write token. The bucket must be Ready.

FieldTypeRequiredDescription
policystringYesThe policy document as a string (JSON inside JSON), up to 16 KB. Version must be 2012-10-17
policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": {"AWS": ["CLDR4N7TQ2WB9XK0HJ3E"]},
"Action": ["s3:DeleteObject"],
"Resource": ["arn:aws:s3:::acme-backups/*"]
}
]
}

Build the request body with jq, which turns the file into a string:

jq -n --rawfile policy policy.json '{policy: $policy}' | \
curl -X PUT https://cloider.com/api/buckets/k5t1v/policy \
-H "Authorization: Bearer $CLOIDER_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @-
Response
{"policy": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [ ... ]\n}"}

A policy that doesn't pass the checks answers 400 with the reason on policy, naming the statement:

Response (400)
{
"errors": {"policy": ["Statement 1: Action \"s3:PutBucketAcl\" can't be allowed by a policy, only object actions can"]},
"data": null
}

Other messages on policy include The policy is empty, The policy is over 16 KB, Version must be "2012-10-17", The policy has no statements, Effect must be "Allow" or "Deny", Principal is required, Action is required, Resource is required and Storage rejected the policy (...). General errors are The bucket must be ready to change its policy., Another change to this bucket is in progress, try again in a moment! and Couldn't apply the policy, try again in a moment!.

Principals name access keys by their access key id (CLDR...). Bucket policies explains which actions, principals and conditions are supported.

Remove the bucket policy​

DELETE /buckets/:hashed_id/policy

Removes the bucket's policy. Removing a policy from a bucket that has none succeeds and changes nothing.

Access: Read & Write token.

curl -X DELETE https://cloider.com/api/buckets/k5t1v/policy \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
{"policy": null}

Get the versioning status​

GET /buckets/:hashed_id/versioning

Returns whether the bucket keeps old versions of objects. It reflects changes made through the S3 API too.

Access: any token. The bucket must be Ready.

curl https://cloider.com/api/buckets/k5t1v/versioning \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
{"status": "Enabled"}

status is Enabled, Suspended (versioning was on and is now off; existing versions are kept) or an empty string (versioning was never turned on).

Turn versioning on or off​

PUT /buckets/:hashed_id/versioning

Turns versioning on, so every overwrite and delete keeps the previous version, or suspends it. A bucket that has had versioning can't go back to never versioned: turning it off suspends it.

Access: Read & Write token. The bucket must be Ready.

FieldTypeRequiredDescription
enabledbooleanYestrue to enable, false to suspend
curl -X PUT https://cloider.com/api/buckets/k5t1v/versioning \
-H "Authorization: Bearer $CLOIDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
Response
{"status": "Enabled"}

See Versioning. Old versions are stored and billed like any other data, so pair versioning with a lifecycle rule that expires noncurrent versions.

Get the lifecycle rules​

GET /buckets/:hashed_id/lifecycle

Returns the bucket's lifecycle rules, which delete objects, old versions and abandoned uploads after a number of days.

Access: any token. The bucket must be Ready.

curl https://cloider.com/api/buckets/k5t1v/lifecycle \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
{
"rules": [
{
"id": "expire-logs",
"prefix": "logs/",
"enabled": true,
"expire_days": 30,
"noncurrent_days": 7,
"abort_multipart_days": 2
}
],
"unsupported_rules": 0
}
FieldDescription
idThe rule's name
prefixThe rule applies to keys that start with it. Empty for the whole bucket
enabledWhether the rule is active
expire_daysDelete objects this many days after they were written. 0 for never
noncurrent_daysDelete old versions this many days after they were replaced. 0 for never
abort_multipart_daysAbort unfinished multipart uploads after this many days. 0 for never
unsupported_rulesRules set through the S3 API with features these fields can't show, such as tag filters or transitions. They are counted, not returned

Replace the lifecycle rules​

PUT /buckets/:hashed_id/lifecycle

Replaces all of the bucket's lifecycle rules with the list you send, including rules set through the S3 API that the dashboard can't show. An empty list removes the lifecycle configuration.

Access: Read & Write token. The bucket must be Ready.

FieldTypeRequiredDescription
rulesobject listYesUp to 100 rules, each with the fields above

Each rule must have an id of 1 to 255 letters, digits, ., _ or -, unique in the list; a prefix of at most 1024 characters without a leading /; and at least one of the three day counts set, each between 1 and 36500.

curl -X PUT https://cloider.com/api/buckets/k5t1v/lifecycle \
-H "Authorization: Bearer $CLOIDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{"id": "expire-logs", "prefix": "logs/", "enabled": true, "expire_days": 30, "noncurrent_days": 7, "abort_multipart_days": 2}
]
}'
Response
{
"rules": [
{"id": "expire-logs", "prefix": "logs/", "enabled": true, "expire_days": 30, "noncurrent_days": 7, "abort_multipart_days": 2}
],
"unsupported_rules": 0
}

Validation errors are on rules and name the rule, for example Rule 2: another rule already has the ID "expire-logs", Rule 1: set at least one of the day counts or A bucket can have up to 100 lifecycle rules. See Lifecycle rules.

Get the CORS rules​

GET /buckets/:hashed_id/cors

Returns the bucket's CORS rules, which decide the websites that can use it from a browser. An empty list means any website can. The rule that keeps the Cloider dashboard working isn't returned.

Access: any token. The bucket must be Ready.

curl https://cloider.com/api/buckets/k5t1v/cors \
-H "Authorization: Bearer $CLOIDER_TOKEN"
Response
{
"rules": [
{
"id": "web-app",
"allowed_origins": ["https://app.example.com"],
"allowed_methods": ["GET", "PUT"],
"allowed_headers": ["Content-Type"],
"expose_headers": ["ETag"],
"max_age_seconds": 3000
}
]
}
FieldDescription
idThe rule's name, "" for none
allowed_originsOrigins a browser lets use the bucket, such as https://app.example.com. https://*.example.com matches its subdomains, * any website
allowed_methodsAny of GET, HEAD, PUT, POST and DELETE
allowed_headersRequest headers a page may send. * for any, or a prefix like x-amz-*
expose_headersResponse headers a page's script may read
max_age_secondsHow long browsers may reuse a preflight answer. 0 leaves it to the browser

Replace the CORS rules​

PUT /buckets/:hashed_id/cors

Replaces all of the bucket's CORS rules with the list you send, including rules set through the S3 API. An empty list removes the CORS configuration, so any website can use the bucket again. The rule that keeps the Cloider dashboard working is added ahead of yours.

Access: Read & Write token. The bucket must be Ready.

FieldTypeRequiredDescription
rulesobject listYesUp to 99 rules, each with the fields above

Each rule needs at least one origin and one method. Origins are * or a scheme, host and optional port without a path, with a * only right after the scheme; they come back in lower case, and methods in upper case. An id is optional, up to 255 characters, unique in the list. max_age_seconds is 0 to 86400.

curl -X PUT https://cloider.com/api/buckets/k5t1v/cors \
-H "Authorization: Bearer $CLOIDER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{"id": "web-app", "allowed_origins": ["https://app.example.com"], "allowed_methods": ["GET", "PUT"], "allowed_headers": ["Content-Type"], "expose_headers": ["ETag"], "max_age_seconds": 3000}
]
}'
Response
{
"rules": [
{"id": "web-app", "allowed_origins": ["https://app.example.com"], "allowed_methods": ["GET", "PUT"], "allowed_headers": ["Content-Type"], "expose_headers": ["ETag"], "max_age_seconds": 3000}
]
}

Validation errors are on rules and name the rule, for example Rule 1: the origin "example.com" isn't an origin like https://app.example.com, Rule 2: allow at least one method or A bucket can have up to 99 CORS rules. See CORS.

Delete a bucket​

DELETE /buckets/:hashed_id

Deletes the bucket and every object in it. This can't be undone. The bucket's policy is removed first, and the targets that point domains at its website are deleted (the domains stay), then the bucket goes to Terminating while its objects are deleted in the background, which can take a while for a large bucket. When it is done, the bucket disappears and its status answers 404. The name becomes free for anyone to take.

Access: Read & Write token.

curl -X DELETE https://cloider.com/api/buckets/k5t1v \
-H "Authorization: Bearer $CLOIDER_TOKEN"

The response is the account's bucket list, with this bucket Terminating.

StatusMessage
400This bucket is still being created!
400This bucket is already being deleted!
400Another change to this bucket is in progress, try again in a moment!
400Couldn't remove the bucket's policy, try again in a moment!
403This API token is read only!, You have read-only access to this account, you can not delete buckets!
404Not Found (plain text)

See Delete a bucket.