Dateiverwaltung
Ordner
{ "id": 4, "parent_id": null, "name": "Produktbilder" }
| Endpunkt | Zugriff | Beschreibung |
|---|---|---|
GET /folders |
🔑 | Alle Ordner (flach, über parent_id verschachtelt) |
POST /folders |
✏️ | Body { "name": "…", "parent_id": null } → 201 |
PUT /folders/{id} |
✏️ | Umbenennen { "name": "…" } und/oder Verschieben { "move": true, "parent_id": 4 } (null = Hauptordner; 400 folder.cycle bei Verschieben in sich selbst oder einen Unterordner, 404 bei unbekanntem Ordner) → 204 |
DELETE /folders/{id} |
✏️ | Löscht Ordner und Unterordner; enthaltene Dateien wandern in den Hauptordner (folder_id: null) → 204 |
Dateien
Datei-Objekt
{
"id": 7,
"folder_id": 4,
"name": "sneaker.jpg",
"path": "2026/10/sneaker-1a2b3c4d.jpg",
"mime": "image/jpeg",
"size": 482113,
"width": 2400,
"height": 1600,
"alt": "Weißer Sneaker auf Holzboden",
"variants": [
{ "width": 320, "height": 213, "path": "2026/10/sneaker-1a2b3c4d-320w.jpg" },
{ "width": 640, "height": 426, "path": "2026/10/sneaker-1a2b3c4d-640w.jpg" },
{ "width": 960, "height": 640, "path": "2026/10/sneaker-1a2b3c4d-960w.jpg" },
{ "width": 1280, "height": 853, "path": "2026/10/sneaker-1a2b3c4d-1280w.jpg" },
{ "width": 1920, "height": 1280, "path": "2026/10/sneaker-1a2b3c4d-1920w.jpg" }
],
"created_at": 1791191677,
"private": false,
"url": "/media/2026/10/sneaker-1a2b3c4d.jpg",
"srcset": "/media/2026/10/sneaker-1a2b3c4d-320w.jpg 320w, …, /media/2026/10/sneaker-1a2b3c4d.jpg 2400w",
"tag": "<img src=\"/media/…\" srcset=\"…\" sizes=\"100vw\" width=\"2400\" height=\"1600\" alt=\"…\" loading=\"lazy\" decoding=\"async\">"
}
| Feld | Beschreibung |
|---|---|
name |
Anzeigename (Original-Dateiname, änderbar) |
path |
Speicherpfad unter /media/ (nicht änderbar) |
width, height |
Pixelmaße bei Rastergrafiken (JPEG, PNG, GIF, WebP), sonst 0 |
variants |
Automatisch erzeugte verkleinerte Fassungen für srcset – nur für JPEG und PNG, nur für Breiten kleiner als das Original (320, 640, 960, 1280, 1920 px) |
url |
Öffentliche URL des Originals |
srcset |
Fertiges srcset-Attribut (Varianten + Original); leer ohne Varianten |
tag |
Fertiges responsives <img>-Element (nur bei Bildern) |
private |
Private Datei: /media/… liefert sie (samt Varianten und WebP-Fassungen) nur angemeldet oder mit signiertem Link, sonst 404 – siehe Handbuch |
GET /files 🔑
| Query | Beschreibung |
|---|---|
folder |
Ordner-ID oder root (Standard: Hauptordner) |
all=1 |
Dateien aus allen Ordnern |
q |
Suche in Name und Alt-Text |
type |
MIME-Hauptklasse, z. B. image, video, application |
Sortierung: neueste zuerst.
curl -H "Authorization: Bearer $TOKEN" "https://example.com/api/v1/files?all=1&type=image&q=sneaker"
GET /files/{id} 🔑
Einzelne Datei.
POST /files ✏️
Upload als multipart/form-data. Beliebig viele Felder file, optional ein Feld folder_id und ein Feld private (1/true = als private Datei anlegen) – beide müssen vor den Dateien stehen.
curl -H "Authorization: Bearer $TOKEN" \
-F folder_id=4 \
-F file=@sneaker.jpg \
-F file=@datenblatt.pdf \
https://example.com/api/v1/files
Antwort 201: Array der angelegten Datei-Objekte.
Limits: 64 MB pro Datei, 256 MB pro Request. Dateinamen werden bereinigt (Kleinbuchstaben, nur a-z0-9._-) und mit einem Zufallssuffix versehen; Uploads landen in media/JJJJ/MM/.
PUT /files/{id} ✏️
{ "name": "sneaker-weiss.jpg", "alt": "Weißer Sneaker", "move": true, "folder_id": null }
| Feld | Beschreibung |
|---|---|
name |
Neuer Anzeigename (leer = unverändert) |
alt |
Alt-Text |
move + folder_id |
Nur wenn move: true, wird folder_id übernommen (null = Hauptordner) |
private |
true/false schaltet die Datei privat bzw. öffentlich – wirkt sofort auf /media/…. Ohne Feld unverändert |
POST /files/{id}/signed-url 🔑
Erzeugt einen signierten Link auf die Datei – für private Dateien gedacht, für öffentliche harmlos. Body optional:
{ "ttl": 604800 }
ttl = Gültigkeit in Sekunden, Standard 86400 (1 Tag), erlaubt 60 bis 2592000 (30 Tage), sonst 400 (file.ttlInvalid). Antwort:
{ "url": "/media/2026/10/angebot-1a2b3c4d.pdf?exp=1791796477&sig=Q2x…", "expires_at": 1791796477 }
url ist relativ zur Instanz. Die Signatur (HMAC-SHA256 über Pfad und Ablaufzeit, Geheimnis je Instanz, nicht im Bundle) gilt für das Original samt Varianten und WebP-Fassungen, auch mit ?w=/?format= dahinter, und lässt sich weder verlängern noch auf andere Dateien übertragen. Einzelne Links lassen sich nicht widerrufen. Leert den Seiten-Cache nicht.
DELETE /files/{id} ✏️
Löscht Datenbankeintrag, Original und alle Varianten. 204. Mit ?if_unused=1 nur, wenn die Datei nirgends verwendet wird (Prüfung unmittelbar vor dem Löschen, siehe POST /files/usage); sonst 409 file.inUse mit refs und more.
POST /files/{id}/replace ✏️
Ersetzt den Inhalt einer Datei an Ort und Stelle: ID, Pfad und damit alle Verwendungen bleiben, Typ, Größe, Maße und Bildvarianten (auch die WebP-Fassungen) werden neu berechnet, die alten Varianten entfallen. multipart/form-data mit einem Feld file (bis 64 MB). Die Dateiendung muss gleich bleiben (400 file.replaceTypeMismatch, params.ext). Antwort 200 mit dem Datei-Objekt. Löst das Ereignis content.changed (file/updated) aus.
POST /files/usage 🔑
Wo werden Dateien verwendet? Body { "ids": [31, 32] } (höchstens 200, sonst 400 file.tooManyIDs). Antwort { "usage": { "31": { "used": true, "refs": [{ "kind": "page", "id": 1, "title": "Start", "path": "/" }], "more": 0 }, "32": { "used": false, "refs": [], "more": 0 } } }. Unbekannte IDs fehlen im Ergebnis.
used ist maßgeblich und folgt derselben vorsichtigen Prüfung wie das Aufräumen (im Zweifel verwendet). refs sind die gefundenen Stellen (höchstens 10, weitere zählt more): kind = page, item (mit collection = Slug), global, snippet, collection, redirect, source, workflow, pen. Das sind Auskünfte für Menschen – bei Verweisen, die sich keiner Stelle zuordnen lassen, kann refs trotz used: true leer sein. Lesend (leert den Seiten-Cache nicht).
GET /cleanup ✏️ · POST /cleanup ✏️
Aufräumen: GET listet ungenutzte Dateien und CSS/JS-Assets (Kriterien im Handbuch).
{
"files": [{ "id": 31, "name": "altes-foto.png", "path": "2026/10/altes-foto-1a2b.png", "url": "/media/2026/10/altes-foto-1a2b.png", "mime": "image/png", "size": 3512, "width": 1200, "height": 630, "folder_id": null, "imported": false }],
"files_bytes": 3512,
"assets": [{ "id": 7, "name": "webflow-alt", "kind": "css", "size": 13, "imported": true }]
}
POST mit { "files": [31], "assets": [7] } löscht die angegebenen – aber nur, was bei einer erneuten Prüfung immer noch ungenutzt ist. Antwort { "files": 1, "assets": 1, "bytes": 3512, "skipped": 0 } (skipped: inzwischen verwendet oder nicht gefunden).