Folders
Folder endpoints of the REST API
All endpoints below require the API-Key
header.
Folder objects in responses have this shape:
{
"id": "9c8b7a6d-...",
"name": "demo",
"key": "projects/demo",
"parentId": "3e2d1c0b-...",
"createdAt": "2026-07-15 12:00:00",
"updatedAt": "2026-07-15 12:00:00"
}key is the folder's path relative to the storage root. The root folder's
key is the empty string.
Browse a folder
GET /api/folders
GET /api/folders?id=<folder-id>
GET /api/folders?key=<folder/key>Returns the files and direct subfolders of a folder. With no id or key,
the root folder is returned. The files list supports the list query
parameters.
curl "https://files.example.com/api/folders?key=projects/demo&orderBy=name&orderDirection=ASC" \
-H "API-Key: your-api-key"{
"data": {
"files": [ ... ],
"folders": [ ... ]
},
"error": null
}Responds 404 when the folder doesn't exist. path is accepted as an alias
for key.
Create a folder
POST /api/foldersJSON body — a path relative to the root folder; intermediate folders are created automatically:
{ "folder": "projects/demo/assets" }{ "data": { "folder": { ... } }, "error": null }Folder names may contain dots (release/v1.0 is fine). What is rejected with
400 is anything that could escape the storage root: the segments . and
.., path separators inside a name, and NUL bytes. An existing folder
responds 409.
Rename a folder or set visibility in bulk
PUT /api/foldersJSON body — name, visibility, or both. At least one is required:
{ "id": "<folder-id>", "name": "new-name" }The new name must be a single path segment. Renaming also rewrites the keys
of every file and subfolder inside. A sibling folder with the same name
responds 409.
visibility cascades: it applies public or private to every file in the
folder and all its subfolders, in one transaction.
{ "id": "<folder-id>", "visibility": "private" }Folders do not themselves carry a visibility — this is a bulk write over the files beneath them, not an inherited setting, so a file uploaded afterwards takes the instance default rather than the folder's last cascade. Unlike rename, the root folder is a valid cascade target, which is how you lock down an entire instance in one call.
Move a folder
POST /api/folders/moveJSON body, with the destination given as either folderId or folder:
{ "id": "<folder-id>", "folder": "archive/2025" }folderId names an existing folder; folder is a key that is created if
missing, and "" is the root. The folder keeps its name and takes everything
inside it along, so the key of every file and subfolder below it is rewritten in
one transaction. Public links and signed URLs pointing at the old keys stop
working.
{ "data": { "folder": { "key": "archive/2025/demo", ... } }, "error": null }| Status | Meaning |
|---|---|
400 | Missing id or destination, an invalid key, the root folder, or a destination inside the folder itself |
404 | No such folder, or no folder with that folderId |
409 | A file or folder with the same name already exists in the destination |
Moving a folder into the folder it is already in succeeds without changing anything.
Download a folder as a zip
GET /api/folders/download?id=<folder-id>
GET /api/folders/download?key=<folder/key>
GET /api/folders/downloadStreams the folder and everything below it as one zip, private files included.
Entries sit under a top-level directory named after the folder, so
projects/demo downloads as demo.zip containing demo/..., and empty
subfolders are kept. With no id or key, the root folder is archived as
files.zip, a copy of every file on the instance.
curl -OJ "https://files.example.com/api/folders/download?key=projects/demo" \
-H "API-Key: your-api-key"Responds 404 when the folder doesn't exist. A file whose bytes are missing
from disk is left out rather than failing the whole archive. As with
downloading several files,
entries are stored uncompressed with an exact Content-Length, archives over
4 GB use ZIP64, and the download cannot be resumed with a byte range.
Delete a folder
DELETE /api/foldersJSON body:
{ "id": "<folder-id>" }Deletes the folder recursively, including all files and subfolders inside it. This cannot be undone.
The root folder cannot be renamed or deleted — both respond 400. Removing
it would take the entire storage tree with it. A visibility cascade against the
root is allowed.
Vaze