Docs
Get Started

API reference

Every request goes to https://gateway.kuberns.cloud and carries your credential as HTTP Basic authentication. See Use buckets from your application for the basics.

The examples use cURL with two environment variables:

export KUBERNS_ACCESS_KEY_ID="KBS..."
export KUBERNS_SECRET="your-secret-access-key"

and a bucket identifier:

export BUCKET="kb-product-assets-3f9a1c2b7d4e"

Endpoints

What Method and path Needs
List buckets GET /buckets Read
Create a bucket POST /buckets Read & write
Get a bucket GET /buckets/{bucket} Read
Delete a bucket DELETE /buckets/{bucket} Read & write
Create a folder POST /buckets/{bucket}/folders Read & write
Upload a file PUT /{bucket}/{key} Read & write
Download a file GET /{bucket}/{key} Read
Get a file's details HEAD /{bucket}/{key} Read
Delete a file DELETE /{bucket}/{key} Read & write
List files GET /{bucket}/ Read
Get visibility GET /buckets/{bucket}/visibility Read
Set visibility PUT /buckets/{bucket}/visibility Read & write
Get a link POST /buckets/{bucket}/url Read

Needs is the access level the credential must have. {bucket} is the bucket identifier, and {key} is the file's name, such as reports/2026/summary.pdf.

Managing buckets

These endpoints take and return JSON. A successful answer has this shape, and the result is under data:

{
  "message": "Bucket created successfully.",
  "status": 201,
  "data": {}
}

List buckets

GET /buckets

Returns every bucket you own, with a summary of your storage.

curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" https://gateway.kuberns.cloud/buckets
{
  "message": "Buckets fetched successfully.",
  "status": 200,
  "data": {
    "buckets": [
      {
        "bucket": "kb-product-assets-3f9a1c2b7d4e",
        "public_id": "05f8ebb3-5e3d-494f-b251-4ef2937f49c9",
        "name": "product-assets",
        "aws_region": "ap-south-1",
        "status": "ACTIVE",
        "status_message": null,
        "size_bytes": 5242880,
        "object_count": 12,
        "usage_synced_at": "2026-10-17T07:54:12.778541Z",
        "created_at": "2026-10-17T07:54:09.901564Z"
      }
    ],
    "summary": {
      "used_bytes": 5242880,
      "limit_bytes": null,
      "bucket_count": 1,
      "bucket_limit": 50,
      "max_object_size_bytes": 1073741824,
      "create_blocked_reason": null
    }
  }
}
Field Meaning
bucket The identifier. Use it in every other request.
name The name you chose, as shown in the dashboard.
status ACTIVE when the bucket is ready to use.
size_bytes, object_count Total size and number of files. These are refreshed periodically, so they can lag a recent upload.
summary.used_bytes Total size of all your files.
summary.limit_bytes null, because there is no cap on total storage.
summary.bucket_count, summary.bucket_limit How many buckets you have, and the most you can have.
summary.max_object_size_bytes The largest file the dashboard accepts.
summary.create_blocked_reason null when you can create a bucket. Otherwise the reason you cannot, such as needing a running service.

Create a bucket

POST /buckets

Creates a bucket. Requires read & write.

Body field Description
name 3 to 40 characters: lowercase letters, numbers, and hyphens, starting and ending with a letter or number. Must be unique among your buckets.
curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  -X POST https://gateway.kuberns.cloud/buckets \
  -H "Content-Type: application/json" \
  -d '{"name": "product-assets"}'

Answers 201 Created with the bucket under data:

{
  "message": "Bucket created successfully.",
  "status": 201,
  "data": {
    "bucket": "kb-product-assets-3f9a1c2b7d4e",
    "public_id": "05f8ebb3-5e3d-494f-b251-4ef2937f49c9",
    "name": "product-assets",
    "aws_region": "ap-south-1",
    "status": "ACTIVE",
    "status_message": null,
    "size_bytes": 0,
    "object_count": 0,
    "usage_synced_at": "2026-10-17T07:54:12.778541Z",
    "created_at": "2026-10-17T07:54:09.901564Z"
  }
}

Save data.bucket. It is how you refer to this bucket from now on.

Answers 400 when the name is not valid, when you already have a bucket with that name, when your account is in a grace period, or when you have no running service and no bucket yet.

Get a bucket

GET /buckets/{bucket}

curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" "https://gateway.kuberns.cloud/buckets/$BUCKET"

Answers 200 with the same object that Create a bucket returns, under data. A bucket that does not exist, or belongs to someone else, answers 404.

Delete a bucket

DELETE /buckets/{bucket}

Permanently deletes the bucket and every file in it. There is no restore. Requires read & write.

curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  -X DELETE "https://gateway.kuberns.cloud/buckets/$BUCKET"
{
  "message": "Bucket deleted successfully.",
  "status": 200,
  "data": {}
}

Create a folder

POST /buckets/{bucket}/folders

Creates an empty folder, so that it shows up in the dashboard before it has any files. You do not need to create a folder before uploading into it, because uploading to reports/2026/summary.pdf creates the folders on its own. Requires read & write.

Body field Description
folder_path The folder, for example invoices or reports/2026.
curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  -X POST "https://gateway.kuberns.cloud/buckets/$BUCKET/folders" \
  -H "Content-Type: application/json" \
  -d '{"folder_path": "invoices"}'
{
  "message": "Folder invoices/ created successfully.",
  "status": 201,
  "data": {}
}

Working with files

These endpoints use the bucket identifier first, then the file's name: /{bucket}/{key}.

Upload a file

PUT /{bucket}/{key}

The request body is the file itself. Requires read & write.

Header Description
Content-Type The file's type, such as image/png. Stored with the file and returned when it is downloaded.
Content-Length Set by your HTTP client. Required.
curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  -X PUT "https://gateway.kuberns.cloud/$BUCKET/reports/2026/summary.pdf" \
  -H "Content-Type: application/pdf" \
  --data-binary @summary.pdf
{
  "bucket": "kb-product-assets-3f9a1c2b7d4e",
  "key": "reports/2026/summary.pdf",
  "size": 48213
}

Uploading to a name that already exists replaces the file, and the new file is private. Answers 402 when your account is in a grace period and uploads are paused.

Download a file

GET /{bucket}/{key}

Returns the file's bytes, with its Content-Type, Content-Length, ETag, and Last-Modified headers.

curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  "https://gateway.kuberns.cloud/$BUCKET/reports/2026/summary.pdf" \
  -o summary.pdf

A file that does not exist answers 404 with {"error": "That file does not exist."}.

Get a file's details

HEAD /{bucket}/{key}

Returns the same headers as a download, without the file. Use it to check that a file exists or to read its size.

curl -I -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  "https://gateway.kuberns.cloud/$BUCKET/reports/2026/summary.pdf"
200 OK
content-type: application/pdf
content-length: 48213
etag: "5d41402abc4b2a76b9719d911017c592"
last-modified: Sat, 17 Oct 2026 07:54:15 GMT

Delete a file

DELETE /{bucket}/{key}

Permanently deletes a file. Requires read & write. It answers 204 No Content with an empty body, and the same answer if the file was already gone, so you can safely repeat it.

curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  -X DELETE "https://gateway.kuberns.cloud/$BUCKET/reports/2026/summary.pdf"

List files

GET /{bucket}/

Lists one level of a bucket: the files and the folders directly inside a path. It does not list everything underneath.

Query parameter Description
prefix List inside this folder, for example reports or reports/2026. Leave it out for the top of the bucket.
limit The most entries to return in one page. The default is 100 and the most is 1,000.
token The next_token from the previous page, to continue.
curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  "https://gateway.kuberns.cloud/$BUCKET/?prefix=reports"
{
  "bucket": "kb-product-assets-3f9a1c2b7d4e",
  "prefix": "reports/",
  "folders": ["reports/2026/"],
  "objects": [],
  "next_token": null
}

A file looks like this:

{
  "key": "logo.png",
  "size": 4096,
  "etag": "3bdaf5969285188ac756c339f69f5c79",
  "last_modified": "2026-10-17T07:54:15Z"
}

Paging. When there is more to list, next_token holds a value. Call again with it as token, and repeat until next_token is null. Folders and files can arrive on different pages, and a page can have a null or empty folders or objects, so treat null as empty and keep going until next_token is null.

A token that is not valid answers 400 with {"error": "That page token is not valid."}.

Get visibility

GET /buckets/{bucket}/visibility?key={key}

Tells you whether a file is public or private, and gives you a link to it.

curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  "https://gateway.kuberns.cloud/buckets/$BUCKET/visibility?key=logo.png"
{
  "message": "Visibility fetched successfully.",
  "status": 200,
  "data": {
    "object_key": "logo.png",
    "visibility": "private",
    "url": null,
    "share_url": "https://buckets.kuberns.cloud/private/kb-product-assets-3f9a1c2b7d4e/logo.png?Expires=1792227857&Signature=...&Key-Pair-Id=...",
    "share_expires_at": "2026-10-17T08:04:17.024448+00:00"
  }
}
Field Meaning
visibility public or private.
url The permanent link of a public file. null for a private file.
share_url A temporary link for a private file. null for a public file.
share_expires_at When share_url stops working.

Set visibility

PUT /buckets/{bucket}/visibility

Makes a file public or private. Requires read & write.

Body field Description
object_key The file's name.
visibility public or private.
curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  -X PUT "https://gateway.kuberns.cloud/buckets/$BUCKET/visibility" \
  -H "Content-Type: application/json" \
  -d '{"object_key": "logo.png", "visibility": "public"}'
{
  "message": "This file has been made publicly accessible. Anyone with the link can open it.",
  "status": 200,
  "data": {
    "object_key": "logo.png",
    "visibility": "public",
    "url": "https://buckets.kuberns.cloud/public/kb-product-assets-3f9a1c2b7d4e/logo.png",
    "share_url": null,
    "share_expires_at": null
  }
}

Making a file private again returns its share_url instead, and the permanent link stops working within about a minute.

POST /buckets/{bucket}/url

Returns one link to a file, the right kind for its state: a permanent link for a public file, and a temporary link for a private one. Use this when you only want a link and do not care which kind it is.

Body field Description
object_key The file's name.
curl -u "$KUBERNS_ACCESS_KEY_ID:$KUBERNS_SECRET" \
  -X POST "https://gateway.kuberns.cloud/buckets/$BUCKET/url" \
  -H "Content-Type: application/json" \
  -d '{"object_key": "logo.png"}'
{
  "message": "URL generated successfully.",
  "status": 200,
  "data": {
    "bucket": "kb-product-assets-3f9a1c2b7d4e",
    "key": "logo.png",
    "visibility": "private",
    "url": "https://buckets.kuberns.cloud/private/kb-product-assets-3f9a1c2b7d4e/logo.png?Expires=1792227857&Signature=...&Key-Pair-Id=...",
    "expires_at": "2026-10-17T08:04:17.619831+00:00"
  }
}

For a public file, url is the permanent link and expires_at is null. A file that does not exist answers 400 with {"message": "That file does not exist."}.

A read-only credential may call this endpoint, because a link only lets someone read the file.

Errors

Every error uses a standard HTTP status. See Errors and troubleshooting for the full list and what to do about each.