Storage API (Generated Files)¶
This API manages user-scoped generated files, storage quotas, trash/restore flows, and cleanup helpers.
Code anchors:
- Router: tldw_Server_API/app/api/v1/endpoints/storage.py:142
- Schemas: tldw_Server_API/app/api/v1/schemas/storage_schemas.py:165
- Quota service: tldw_Server_API/app/services/storage_quota_service.py:760
- Cleanup worker: tldw_Server_API/app/services/storage_cleanup_service.py:176
Base path: /api/v1/storage
Security and Path Handling¶
Downloads and cleanup operations validate resolved filesystem paths stay inside the correct per-user base directory:
- Download traversal guard: tldw_Server_API/app/api/v1/endpoints/storage.py:228
- Category-based base dir resolution (outputs vs voices): tldw_Server_API/app/api/v1/endpoints/storage.py:101
- Cleanup safe resolver: tldw_Server_API/app/services/storage_cleanup_service.py:32
Voice clones (file_category == voice_clone) are resolved under the voices directory; other files use the outputs directory.
Core File Endpoints¶
GET /files- List generated files for the current user with pagination and filters.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:142 GET /files/{file_id}- Returns metadata and updates
accessed_at. - Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:180 GET /files/{file_id}/download- Streams the file from disk after ownership and traversal checks.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:203 DELETE /files/{file_id}?hard_delete={bool}- Soft delete (default) subtracts usage and moves to trash.
- Hard delete removes the record; usage subtraction only occurs if the file was not already soft-deleted.
- Anchor:
tldw_Server_API/app/services/storage_quota_service.py:880 PATCH /files/{file_id}- Update metadata such as tags, folder tag, or retention fields.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:285
Bulk Operations¶
POST /files/bulk-delete- Deletes each file through the quota service to ensure usage counters are updated correctly.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:318 POST /files/bulk-move- Bulk folder-tag changes.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:352
Bulk delete examples (soft vs hard delete):
BASE_URL="http://127.0.0.1:8000"
API_KEY="${SINGLE_USER_API_KEY}"
# Soft delete (moves to trash, updates usage once)
curl -sS -X POST "$BASE_URL/api/v1/storage/files/bulk-delete" \
-H "X-API-KEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"file_ids":[101,102,103],"hard_delete":false}' | jq
# Hard delete (immediate removal; safe for already-trashed files)
curl -sS -X POST "$BASE_URL/api/v1/storage/files/bulk-delete" \
-H "X-API-KEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"file_ids":[201,202],"hard_delete":true}' | jq
Cleanup Suggestions¶
GET /files/least-accessed?limit=20- Returns least recently accessed files (oldest first), using
COALESCE(accessed_at, created_at). - Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:420 - Repo implementation:
tldw_Server_API/app/core/AuthNZ/repos/generated_files_repo.py:905
Least-accessed example:
curl -sS "$BASE_URL/api/v1/storage/files/least-accessed?limit=20" \
-H "X-API-KEY: $API_KEY" | jq
Usage and Quotas¶
GET /usage- Returns total usage, category breakdown, and quota warnings.
- Soft limit is 80% and hard limit is 100%.
- Anchors:
- Endpoint logic:
tldw_Server_API/app/api/v1/endpoints/storage.py:449 - Warning fields:
tldw_Server_API/app/api/v1/schemas/storage_schemas.py:165
- Endpoint logic:
GET /usage/breakdown- Returns folder and category breakdown plus quota numbers.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:500
Quick usage warning check:
curl -sS "$BASE_URL/api/v1/storage/usage" \
-H "X-API-KEY: $API_KEY" | jq '{
quota_mb,
quota_used_mb,
usage_percentage,
at_soft_limit,
at_hard_limit,
warning
}'
Example GET /usage response fields that are new/important:
{
"usage_percentage": 83.4,
"at_soft_limit": true,
"at_hard_limit": false,
"warning": "Approaching storage limit (80%+)"
}
Team/org quota checks now surface a soft-limit warning string when appropriate:
- tldw_Server_API/app/core/AuthNZ/repos/storage_quotas_repo.py:526
Trash and Restore¶
GET /trash- List trashed files.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:546 POST /trash/restore/{file_id}- Restores a soft-deleted file and re-adds its usage.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:570 DELETE /trash/{file_id}- Permanently deletes a file already in trash without re-subtracting usage.
- Anchor:
tldw_Server_API/app/api/v1/endpoints/storage.py:608
Trash lifecycle examples:
# 1) List trash
curl -sS "$BASE_URL/api/v1/storage/trash?offset=0&limit=50" \
-H "X-API-KEY: $API_KEY" | jq
# 2) Restore a trashed file (re-adds usage)
TRASHED_FILE_ID=101
curl -sS -X POST "$BASE_URL/api/v1/storage/trash/restore/$TRASHED_FILE_ID" \
-H "X-API-KEY: $API_KEY" | jq
# 3) Permanently delete a trashed file (no double subtraction)
curl -sS -X DELETE "$BASE_URL/api/v1/storage/trash/$TRASHED_FILE_ID" \
-H "X-API-KEY: $API_KEY" | jq
Admin Quota Endpoints¶
These endpoints require admin privileges and set or inspect quotas at different scopes:
- User quota set: PUT /admin/quotas/user/{user_id} (tldw_Server_API/app/api/v1/endpoints/storage.py:637)
- Team quota set: PUT /admin/quotas/team/{team_id} (tldw_Server_API/app/api/v1/endpoints/storage.py:670)
- Org quota set: PUT /admin/quotas/org/{org_id} (tldw_Server_API/app/api/v1/endpoints/storage.py:698)
- Team quota get: GET /admin/quotas/team/{team_id} (tldw_Server_API/app/api/v1/endpoints/storage.py:726)
- Org quota get: GET /admin/quotas/org/{org_id} (tldw_Server_API/app/api/v1/endpoints/storage.py:744)
Background Cleanup Worker¶
A background cleanup worker can be enabled to purge expired files, old trash, and temp directories:
- Cleanup cycle: tldw_Server_API/app/services/storage_cleanup_service.py:176
- Worker start: tldw_Server_API/app/main.py:2036
- Worker stop: tldw_Server_API/app/main.py:2906
Environment variables:
- STORAGE_CLEANUP_ENABLED (default: true)
- STORAGE_CLEANUP_INTERVAL_SEC (default: 3600)
- STORAGE_TRASH_RETENTION_DAYS (default: 30)
- STORAGE_CLEANUP_BATCH_SIZE (default: 100)
Note: trash purge uses hard delete directly against the repo (no usage subtraction), which is correct for already-soft-deleted files.
Related Integrations¶
- TTS download link headers:
tldw_Server_API/app/api/v1/endpoints/audio.py:1166 - Voice clone registration:
tldw_Server_API/app/core/TTS/voice_manager.py:640 - File artifacts export registration:
tldw_Server_API/app/core/File_Artifacts/file_artifacts_service.py:356
For developer-oriented flow details and integration patterns, see:
- Docs/Code_Documentation/Guides/Generated_Files_Storage_Code_Guide.md:1