Library files
Verified request, response and authorization contracts.
Library files are workspace resources. File access also follows the owning Area’s access policy. {workspaceId} is the workspace UUID. The protected root folders and Area folders cannot be arbitrarily renamed/deleted. File content editing uses an optional version precondition to reject stale writes.
Examples use the environment variables from Overview. UUID placeholders must be replaced with your own IDs.
GET /api/workspaces/{workspaceId}/files
Auth: Workspace member with access to this resource.
Request: Optional query parent_id:UUID; omit to list root.
Response: {files:workspaceFileRow[]}.
Status: 200. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"GET /api/workspaces/{workspaceId}/files/search
Auth: Workspace member with access to this resource.
Request: Query q:string required; limit?:integer defaults 20, capped at 50.
Response: {files:workspaceFileRow[],total:integer} (returned count).
Status: 200; 400 missing query. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/search?q=report" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"POST /api/workspaces/{workspaceId}/files
Auth: Workspace member with access to this resource.
Request: Multipart form: file:binary required; optional parent_id:UUID.
Response: workspaceFileRow.
Status: 201; 400 invalid upload; 409 name conflict; 503 storage unavailable. Authentication and resource-access errors follow Overview.
Use multipart instead of the JSON examples: curl -sS "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files" -H "Authorization: Bearer $MELSO_TOKEN" -F "file=@report.pdf".
curl -sS -X POST "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID" -F "file=@report.pdf"POST /api/workspaces/{workspaceId}/files/folders
Auth: Workspace member with access to this resource.
Request: name:string, parent_id?:UUID|null.
Response: workspaceFileRow.
Status: 201; 400 invalid parent/name; 409 duplicate/reserved name. Authentication and resource-access errors follow Overview.
curl -sS -X POST "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/folders" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID" \
-H "Content-Type: application/json" -d '{"name":"Reports"}'POST /api/workspaces/{workspaceId}/files/markdown
Auth: Workspace member with access to this resource.
Request: name:string, content:string, parent_id?:UUID|null.
Response: workspaceFileRow.
Status: 201; 400 invalid parent; 409 name conflict; 503 storage unavailable. Authentication and resource-access errors follow Overview.
curl -sS -X POST "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/markdown" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID" \
-H "Content-Type: application/json" -d '{"name":"notes.md","content":"Research notes"}'GET /api/workspaces/{workspaceId}/files/{fileId}
Auth: Workspace member with access to this resource.
Request: Path: file UUID.
Response: workspaceFileRow.
Status: 200. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/$FILE_ID" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"GET /api/workspaces/{workspaceId}/files/{fileId}/content
Auth: Workspace member with access to this resource.
Request: Path: file UUID.
Response: Text: {binary:false,content:string,truncated:boolean,content_version:integer,content_type:string|null}. Binary: {binary:true,content_version:integer,content_type:string|null,url:string|null}. Text preview caps at 2 MiB.
Status: 200; 400 folder; 404 content unavailable. Authentication and resource-access errors follow Overview.
curl -sS -X GET "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/$FILE_ID/content" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"PUT /api/workspaces/{workspaceId}/files/{fileId}/content
Auth: Workspace member with access to this resource.
Request: content:string (up to 2 MiB), content_version?:integer from the last read.
Response: Updated workspaceFileRow.
Status: 200; 400 folder; 409 stale_version; 413 oversized content; 503 storage unavailable. Authentication and resource-access errors follow Overview.
curl -sS -X PUT "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/$FILE_ID/content" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID" \
-H "Content-Type: application/json" -d '{"content":"Updated notes","content_version":1}'PATCH /api/workspaces/{workspaceId}/files/{fileId}
Auth: Workspace member with access to this resource.
Request: name:string.
Response: Updated workspaceFileRow.
Status: 200; 400 invalid name; 409 duplicate/protected name. Authentication and resource-access errors follow Overview.
curl -sS -X PATCH "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/$FILE_ID" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID" \
-H "Content-Type: application/json" -d '{"name":"final-notes.md"}'DELETE /api/workspaces/{workspaceId}/files/{fileId}
Auth: Workspace member with access to this resource.
Request: Optional query recursive:boolean for folders; defaults false.
Response: Empty.
Status: 204; 409 folder_not_empty or protected file. Authentication and resource-access errors follow Overview.
curl -sS -X DELETE "$MELSO_URL/api/workspaces/$WORKSPACE_ID/files/$FILE_ID?recursive=false" \
-H "Authorization: Bearer $MELSO_TOKEN" -H "X-Workspace-ID: $WORKSPACE_ID"workspaceFileRow
Source: server/internal/handler/workspace_files.go (workspaceFileRow). Referenced nested objects retain their handler-defined fields; clients should tolerate additional fields.
| Field | JSON type |
|---|---|
id | string |
workspace_id | string |
parent_id | string or null |
kind | string |
name | string |
url | string or null |
content_type | string or null |
size_bytes | integer or null |
content_version | integer |
created_by_type | string |
created_by_id | string |
created_at | timestamp string |
updated_at | timestamp string |
deleted_at | timestamp string or null (may be omitted) |
area_id | string or null |