# API_GOLDEN.md Dit document definieert stabiele API responses. Velden mogen niet wijzigen zonder golden tests te updaten. ## Browse ### `GET /api/browse` Response shape: ```json { "path": "storage1", "directories": [], "files": [] } ``` ## File Ops (direct) ### `POST /api/files/mkdir` Success: ```json { "path": "storage1/parent/new_dir" } ``` Conflict (`already_exists`): ```json { "error": { "code": "already_exists", "message": "Target path already exists", "details": { "path": "storage1/parent/new_dir" } } } ``` Invalid name (`invalid_request`): ```json { "error": { "code": "invalid_request", "message": "Invalid name", "details": { "name": "bad/name" } } } ``` ### `POST /api/files/rename` Success: ```json { "path": "storage1/parent/new_name.ext" } ``` Conflict (`already_exists`) + invalid name (`invalid_request`) gebruiken dezelfde error-shape als mkdir. ### `POST /api/files/delete` Success (202): ```json { "task_id": "", "status": "queued" } ``` Non-empty directory: ```json { "error": { "code": "directory_not_empty", "message": "Directory is not empty", "details": { "path": "storage1/parent/non_empty" } } } ``` ## Task-based create endpoints ### `POST /api/files/copy` ### `POST /api/files/move` ### `POST /api/files/delete` Success (202): ```json { "task_id": "", "status": "queued" } ``` Notes: - Batch move is supported as one task-based operation via `{ "sources": [...], "destination_base": "..." }`. - Cross-root batch move is supported for file-only selections. - Cross-root batch move with any directory in the selection remains unsupported in v1. - Batch delete is supported as one task-based operation via `{ "paths": [...], "recursive_paths": [...] }`. - Single delete remains supported via `{ "path": "...", "recursive": true|false }`. ## Tasks read endpoints ### `GET /api/tasks` Response shape: ```json { "items": [ { "id": "", "operation": "copy", "status": "running", "source": "storage1/a.txt", "destination": "storage2/a.txt", "created_at": "2026-03-10T10:00:00Z", "finished_at": null } ] } ``` ### `GET /api/tasks/{task_id}` Response shape: ```json { "id": "", "operation": "move", "status": "running", "source": "storage1/a.txt", "destination": "storage2/a.txt", "done_bytes": 1024, "total_bytes": 4096, "done_items": null, "total_items": null, "current_item": "storage1/a.txt", "failed_item": null, "error_code": null, "error_message": null, "created_at": "2026-03-10T10:00:00Z", "started_at": "2026-03-10T10:00:01Z", "finished_at": null } ``` Voor task-based file-actions `copy`, `move`, `duplicate` en `delete` betekenen progressvelden: - `done_items`: aantal volledig verwerkte bestanden - `total_items`: exact aantal te verwerken bestanden in de hele task - `current_item`: taakrelatief bestandspad als beschikbaar, anders bestandsnaam Voor `move` geldt een expliciete uitzondering: - file-gebaseerde move-paden rapporteren file-progress - same-root directory moves behouden directe rename-semantiek en rapporteren daarom grovere item-progress per directory-operatie Voor `delete` geldt: - recursive delete van directorytrees rapporteert file-progress per verwijderd bestand - lege mappen of directory-only deletes houden `done_items = 0`, `total_items = 0` en gebruiken geen kunstmatige file-teller ### `POST /api/tasks/{task_id}/cancel` Success for cancellable file-action task: ```json { "id": "", "operation": "copy", "status": "cancelling", "source": "2 items", "destination": "storage1/dest", "done_bytes": null, "total_bytes": null, "done_items": 0, "total_items": 2, "current_item": "storage1/a.txt", "failed_item": null, "error_code": null, "error_message": null, "created_at": "2026-03-10T10:00:00Z", "started_at": "2026-03-10T10:00:01Z", "finished_at": null } ``` Not cancellable: ```json { "error": { "code": "task_not_cancellable", "message": "Task cannot be cancelled", "details": { "task_id": "", "status": "completed" } } } ``` Task not found: ```json { "error": { "code": "task_not_found", "message": "Task was not found", "details": { "task_id": "task-missing" } } } ```