Docs
Get Started

Pagination

A list can be long, so the API sends it a page at a time. You ask for a page, then ask for the next one, until there are no more.

Two endpoints return lists, and both work the same way:

Endpoint What it lists Default page Most per page
List files The files and folders inside one folder. 100 1,000
List buckets Your buckets. 50 100

You can have at most 50 buckets, so one answer of List buckets holds them all unless you ask for a smaller limit. See List page size.

How it works

You use two query parameters and read two fields from the answer.

Name Where What it does
limit Query parameter The most entries to return in one page. Optional.
page Query parameter Which page to return. Leave it out for the first page. Otherwise send the next_page of the previous answer.
has_next Answer field true when there is another page after this one. false on the last page.
next_page Answer field What to send as page to get the next page. null on the last page.

The steps:

  1. Ask for the first page, without page.
  2. Use what is in the answer.
  3. If has_next is true, ask again with the same other parameters and page set to next_page. Go back to step 2.
  4. If has_next is false, you have everything.

page is not a page number, so page=2 does not work. It is a bookmark that marks where the last page ended. Send it back exactly as you received it. Do not read it, change it, or build one yourself. It can contain +, /, and =, so let your HTTP client put it in the address for you. The examples below do.

A page works this way, not by number, so that a file or bucket added or removed while you read does not make you see an entry twice or miss one.

What a page looks like

This is the first page of a bucket with two folders and two files, requested with limit=1:

{
  "bucket": "kb-product-assets-3f9a1c2b7d4e",
  "folder": "",
  "folders": [
    "invoices/"
  ],
  "has_next": true,
  "next_page": "1YsArNwnJgeAHhJPrz0DUmetRWnV9BHKt/RrOEl0yGjnZF0ZT60PMw6nGL9Skqm0SJw8Hsd0vAvQ=",
  "objects": []
}

Asking again with that next_page as page returns the second page:

{
  "bucket": "kb-product-assets-3f9a1c2b7d4e",
  "folder": "",
  "folders": [],
  "has_next": true,
  "next_page": "1lffGDmvdPzAducR3FgB8wix041m6Acrvl8eOaG45WcvpVQ02FS/rs4tIxgksT4SkYIMuoK1wWPQ=",
  "objects": [
    {
      "etag": "3bdaf5969285188ac756c339f69f5c79",
      "key": "logo.png",
      "last_modified": "2026-10-17T07:54:15Z",
      "size": 4
    }
  ]
}

On the last page has_next is false and next_page is null. This is also the answer when everything fits in one page:

{
  "bucket": "kb-product-assets-3f9a1c2b7d4e",
  "folder": "",
  "folders": [
    "invoices/",
    "reports/"
  ],
  "has_next": false,
  "next_page": null,
  "objects": [
    {
      "etag": "3bdaf5969285188ac756c339f69f5c79",
      "key": "logo.png",
      "last_modified": "2026-10-17T07:54:15Z",
      "size": 4
    },
    {
      "etag": "4358b5009c67d0e31d7fbf1663fcd3bf",
      "key": "notes.txt",
      "last_modified": "2026-10-17T07:54:15Z",
      "size": 5
    }
  ]
}

In List buckets the same two fields are inside data, as data.has_next and data.next_page.

Things to expect

What you may see What to do
folders or objects is an empty list. Normal. A page can have only folders, only files, or both. Collect both on every page.
A page with fewer entries than limit. Normal. Only has_next tells you whether there is more.
A page with no files and no folders, and has_next is true. Keep going. An empty page is not the end.
has_next is false. This is the last page. Stop.

In List files, limit counts files and folders together.

An invalid page

A page that is not valid answers 400:

{
  "error": "That page is not valid. Use the next_page value from the previous response."
}

This happens when page was changed, cut short, is a number, or was not one that a listing gave you. Do not send the same page again. Start over from the first page, without page. The answer from List files has the simple error format. The answer from List buckets has the refusal format, with the same text in message.

Read every page

This code reads every page of one folder and collects the folders and files. It sends the same folder each time and stops when has_next is false.

Python
import os
 
import requests
 
BUCKET = "kb-product-assets-3f9a1c2b7d4e"
FOLDER = "reports"
 
folders = []
files = []
page = None
 
while True:
    params = {"folder": FOLDER, "limit": 100}
    if page:
        params["page"] = page
 
    response = requests.get(
        f"https://gateway.kuberns.cloud/{BUCKET}/",
        auth=(os.environ["KUBERNS_ACCESS_KEY_ID"], os.environ["KUBERNS_SECRET"]),
        params=params,
    )
    response.raise_for_status()
    answer = response.json()
 
    folders.extend(answer["folders"])
    files.extend(answer["objects"])
 
    if not answer["has_next"]:
        break
    page = answer["next_page"]
 
print(f"{len(folders)} folders and {len(files)} files")
JavaScript
const BUCKET = "kb-product-assets-3f9a1c2b7d4e";
const FOLDER = "reports";
 
const credentials = Buffer.from(
  `${process.env.KUBERNS_ACCESS_KEY_ID}:${process.env.KUBERNS_SECRET}`
).toString("base64");
 
const folders = [];
const files = [];
let page = null;
 
while (true) {
  const params = new URLSearchParams({ folder: FOLDER, limit: "100" });
  if (page) {
    params.set("page", page);
  }
 
  const response = await fetch(
    `https://gateway.kuberns.cloud/${BUCKET}/?${params}`,
    { headers: { Authorization: `Basic ${credentials}` } }
  );
  if (!response.ok) {
    throw new Error(`List files failed with status ${response.status}`);
  }
  const answer = await response.json();
 
  folders.push(...answer.folders);
  files.push(...answer.objects);
 
  if (!answer.has_next) break;
  page = answer.next_page;
}
 
console.log(`${folders.length} folders and ${files.length} files`);

To list the top of the bucket, set FOLDER to an empty string. To go into a subfolder, set it to the folder, for example reports/2026.

To read every bucket, do the same with GET /buckets, read data.buckets, and use data.has_next and data.next_page.

Older names

The first version of List files called these parameters and fields prefix, token, and next_token. They still work, so code written for them does not need to change. Use folder, page, has_next, and next_page in new code.