Files
Single-request upload and managing the files of a bucket. Every method needs a FULL token.
The file in a response
Every method that returns a file returns it in the same shape:
{
"id": "Xk3f9QaLm2Pw",
"name": "photo.webp",
"folder": "avatars",
"content": {
"size": 444,
"mime": "image/webp",
"extension": "webp",
"hash": "57faddf4ac10468a87ad4e986af5da30d519785f908184284526e3d9ccda3645"
},
"public": true,
"deduplicated": false,
"processed": { "applied": true, "operations": ["resize:300x200", "encode:webp@82"], … },
"expiresAt": null,
"privateUrl": "https://s5.example.com/p/Xk3f9QaLm2Pw",
"publicUrl": "https://s5.example.com/o/b554eae9-…/Xk3f9QaLm2Pw",
"createdAt": "2026-11-07T17:10:44+00:00",
"updatedAt": "2026-11-07T17:10:44+00:00"
}id— the short file id; it is also part of the delivery addresses.content.hash— SHA-256 of the stored content.deduplicated— only in an upload response:truewhen this content was already in the bucket and no disk space was spent. Alwaysfalsein other responses.processed— only in an upload response: what image processing did; without options it is{ "applied": false, "reason": "no options" }. Alwaysnullin other responses.publicUrl— present only on a public file.expiresAt— when the file is deleted by the folder’s retention;null— never.
POST /v1/files
Uploads a file in a single multipart/form-data request. For large files use the
chunked upload.
Form fields
| Field | Type | Description |
|---|---|---|
file |
file | Required. The content. |
folder |
string | Folder name. Without it — the bucket root. |
name |
string | File name. Without it — the name of the uploaded file. |
format |
ORIGINAL · WEBP · JPEG · PNG · AVIF |
Re-encode the image. |
quality |
1–100 | Encoding quality. |
maxWidth |
16–10000 | Shrink if wider. |
maxHeight |
16–10000 | Shrink if taller. |
curl -H "Authorization: Bearer <token>" \
-F file=@photo.png -F folder=avatars -F format=WEBP -F maxWidth=300 \
http://<host>:9090/v1/filesReturns 201 and the file.
The file name is unique within its folder (the bucket root is a namespace of its own): when it
is taken, a number is added — photo (1).png. The name is cleaned: /, \ and control
characters are replaced with -.
When re-encoding changes the format, the extension changes too: photo.png → photo.webp.
GET /v1/files
The files of the bucket, page by page.
| Parameter | Default | Description |
|---|---|---|
page, limit |
1, 25 |
Page and size (up to 100). |
search |
— | Search by name, case-insensitive. |
folder |
— | Folder name. An empty string — the root only. Without the parameter — all files. |
sort |
created |
created · name · type · size. |
dir |
desc |
asc · desc. |
GET /v1/files/{id}
Returns one file.
PUT /v1/files/{id}
Renames and/or moves the file.
{ "name": "avatar.webp", "folder": "users" }name is required and cleaned the same way as on upload: a/b.txt is saved as a-b.txt. The
extension is not adjusted on rename — it stays as given. When the name is taken in the target
folder — 409. folder is the name of the target folder; without it the file goes to the
root.
A moved file takes the visibility of the target folder and its retention too — the retention counts from the moment of the move.
The bucket root is always public
Moving a file to the root makes it public: it gets a publicUrl and opens at
/o/{bucketId}/{id} without a token. A private document moved there from a private folder
becomes available to anyone who has the address. Keep private files in private folders.
DELETE /v1/files/{id}
Deletes the file. Returns 204. Temporary links issued for the file stop working.
Deduplication
The same content is stored once per bucket (by SHA-256). A copy costs a database row, not disk space; deleting one copy does not touch the others.