Skip to main content

Files API

File management endpoints for TMA Cloud.

Note: All endpoints that accept ids arrays process multiple files in bulk operations. This includes move, copy, star, share, delete, restore, and download operations.

List Files

GET /api/files

List files and folders.

Query Parameters:

  • parentId - Parent folder ID (optional)
  • sortBy - Sort field: name, date, size, type (optional)
  • order - Sort order: asc, desc (optional)

Response:

An array of file and folder objects.

[
{
"id": "file_123",
"name": "document.pdf",
"type": "file",
"size": 1024,
"mimeType": "application/pdf",
"parentId": "folder_456",
"starred": false,
"modified": "2024-01-01T00:00:00Z"
}
]

File Statistics

GET /api/files/stats

Get file statistics (total files, total size).

Response:

{
"totalFiles": 100,
"totalFolders": 50,
"sharedCount": 10,
"starredCount": 25
}

Search Files

GET /api/files/search

Search files.

Query Parameters:

  • q or query - Search query (required)
  • limit - Result limit (optional)

Response:

An array of file and folder objects matching the search query.

[
{
"id": "file_123",
"name": "document.pdf",
"type": "file",
"size": 1024,
"mimeType": "application/pdf",
"parentId": "folder_456",
"starred": false,
"modified": "2024-01-01T00:00:00Z"
}
]

Create Folder

POST /api/files/folder

Create a new folder.

Request Body:

{
"name": "New Folder",
"parent_id": "parent_folder_id"
}

Validation:

  • name: Required. Must not be empty and must contain only valid file name characters (a-zA-Z0-9_.-). Max length 100.
  • parentId: Optional. Must be a string.

Response:

The created folder object.

{
"id": "folder_123",
"name": "New Folder",
"type": "folder",
"size": null,
"modified": "2024-01-01T00:00:00Z"
}

Check Upload Storage

POST /api/files/upload/check

Check if the user has enough storage space for an upload before sending the file.

Request Body:

{
"fileSize": 1024
}

Validation:

  • fileSize: Required. Must be a non-negative integer representing the file size in bytes.

Response (Success):

{
"message": "Storage space available"
}

Response (Error):

{
"message": "Storage limit exceeded. Required: 1 GB, available: 500 MB."
}

Upload File

POST /api/files/upload

Upload a file.

Form Data:

  • file - File to upload (required)
  • parent_id - Parent folder ID (optional)
  • path - Target path (optional)

MIME Type Validation:

  • The actual MIME type is detected from the file's content (magic bytes).
  • The stored MIME type will always match the actual file content, even if the file extension is different.

Duplicate names: If a file with the same name already exists in the parent folder, the server assigns a unique display name (e.g. document (1).pdf). The client can instead overwrite the existing file by calling POST /api/files/:id/replace with the existing file's ID.

Response:

The uploaded file object.

{
"id": "file_123",
"name": "uploaded_file.pdf",
"type": "file",
"size": 1024,
"mimeType": "application/pdf",
"parentId": null,
"modified": "2024-01-01T00:00:00Z"
}

Bulk Upload Files

POST /api/files/upload/bulk

Upload multiple files at once using multipart/form-data.

Form Data:

  • files - Files to upload (required)
  • parent_id - Parent folder ID (optional)
  • path - Target path (optional)
  • relativePaths - Optional. One value per file, same order as files. When present, the server uses these relative paths (e.g. "MyFolder/sub/file.txt") to recreate folder structure under parent_id.
  • clientIds - Optional. One value per file, same order as files. Echoed back in the response for easier client-side matching.

Duplicate names: For each file, if a file with the same name already exists in the parent folder, the server assigns a unique display name (e.g. document (1).pdf).

Response:

On success, returns a summary object. files contains created file records; failed contains per-file errors (if any).

{
"files": [
{
"id": "file_123",
"name": "file1.pdf",
"type": "file",
"size": 1024,
"mimeType": "application/pdf",
"parentId": null,
"modified": "2024-01-01T00:00:00Z",
"clientId": "entry-0"
},
{
"id": "file_456",
"name": "file2.jpg",
"type": "file",
"size": 2048,
"mimeType": "image/jpeg",
"parentId": null,
"modified": "2024-01-01T00:00:00Z",
"clientId": "entry-1"
}
],
"failed": [
{
"fileName": "bad-file.exe",
"error": "Invalid file type",
"clientId": "entry-2"
}
],
"total": 3,
"successful": 2,
"failedCount": 1
}

Move Files

POST /api/files/move

Move files and/or folders to a different location.

Request Body:

{
"ids": ["file_123", "file_456"],
"parentId": "target_folder_id"
}

Validation:

  • ids: Required. Must be a non-empty array of strings.
  • parentId: Optional. Must be a string.

Response:

{
"message": "Files moved successfully."
}

Copy Files

POST /api/files/copy

Copy files and/or folders to a different location.

Request Body:

{
"ids": ["file_123", "file_456"],
"parentId": "target_folder_id"
}

Validation:

  • ids: Required. Must be a non-empty array of strings.
  • parentId: Optional. Must be a string.

Response:

{
"message": "Files copied successfully."
}

Rename File

POST /api/files/rename

Rename a file or folder.

Request Body:

{
"id": "file_123",
"name": "New Name"
}

Validation:

  • id: Required. Must be a string.
  • name: Required. Must not be empty and must contain only valid file name characters (a-zA-Z0-9_.-). Max length 100.

Response:

The updated file or folder object.

{
"id": "file_123",
"name": "New Name",
"type": "file",
"modified": "2024-01-01T00:00:00Z"
}

Star Files

POST /api/files/star

Star or unstar one or more files/folders.

Request Body:

{
"ids": ["file_123", "file_456"],
"starred": true
}

Validation:

  • ids: Required. Must be a non-empty array of strings.
  • starred: Required. Must be a boolean.

Response:

{
"message": "File starred status updated."
}

Get Starred Files

GET /api/files/starred

List all starred files and folders.

Query Parameters:

  • sortBy - Sort field (optional)
  • order - Sort order (optional)

Response:

An array of file and folder objects.

[
{
"id": "file_123",
"name": "document.pdf",
"type": "file",
"size": 1024,
"mimeType": "application/pdf",
"parentId": "folder_456",
"starred": true,
"modified": "2024-01-01T00:00:00Z"
}
]

Share Files

POST /api/files/share

Share or unshare files. Creates share links if they don't exist, or removes sharing if shared: false.

Request Body:

{
"ids": ["file_123", "file_456"],
"shared": true,
"expiry": "7d"
}

Validation:

  • ids: Required. Must be a non-empty array of strings.
  • shared: Required. Must be a boolean.
  • expiry: Optional. One of "7d", "30d", or "never".

Response (when sharing):

{
"links": {
"file_123": "http://example.com/s/token123",
"file_456": "http://example.com/s/token456"
}
}

Response (when unsharing):

{
"message": "Files unshared successfully."
}

POST /api/files/share/links

Get existing share links for multiple files without creating new ones.

Request Body:

{
"ids": ["file_123", "file_456"]
}

Validation:

  • ids: Required. Must be a non-empty array of strings.

Response:

{
"links": {
"file_123": "http://example.com/s/token123"
}
}

POST /api/files/link-parent-share

Link files to their parent folder's share link. If the parent folder is shared, the files will be added to that share.

Request Body:

{
"ids": ["file_123", "file_456"]
}

Validation:

  • ids: Required. Must be a non-empty array of strings.

Response:

{
"links": {
"file_123": "http://example.com/s/parent_token"
}
}

Get Shared Files

GET /api/files/shared

List files and folders shared by the current user. Includes share link expiry information.

Query Parameters:

  • sortBy - Sort field (optional)
  • order - Sort order (optional)

Response:

An array of shared file and folder objects. Each object includes expiresAt from the associated share link (null if the link has no expiration).

[
{
"id": "file_123",
"name": "document.pdf",
"type": "file",
"size": 1024,
"mimeType": "application/pdf",
"starred": false,
"shared": true,
"modified": "2024-01-01T00:00:00Z",
"expiresAt": "2024-01-08T00:00:00Z"
}
]

Delete Files

POST /api/files/delete

Move one or more files/folders to the trash.

Request Body:

{
"ids": ["file_123", "file_456"]
}

Validation:

  • ids: Required. Must be a non-empty array of strings.

Response:

{
"message": "Files moved to trash."
}

Get Trash

GET /api/files/trash

List all files and folders currently in the trash.

Query Parameters:

  • sortBy - Sort field (optional)
  • order - Sort order (optional)

Response:

An array of trashed file and folder objects.

[
{
"id": "file_123",
"name": "document.pdf",
"type": "file",
"size": 1024,
"mimeType": "application/pdf",
"parentId": "folder_456",
"starred": false,
"modified": "2024-01-01T00:00:00Z"
}
]

Restore Files

POST /api/files/trash/restore

Restore one or more files/folders from the trash.

Request Body:

{
"ids": ["file_123", "file_456"]
}

Validation:

  • ids: Required. Must be a non-empty array of strings.

Response:

{
"message": "Restored 2 file(s) from trash"
}

Permanent Delete

POST /api/files/trash/delete

Permanently delete one or more files/folders from the trash. This action is irreversible.

Request Body:

{
"ids": ["file_123", "file_456"]
}

Validation:

  • ids: Required. Must be a non-empty array of strings.

Response:

{
"message": "Files permanently deleted."
}

Empty Trash

POST /api/files/trash/empty

Permanently delete all files and folders in the trash.

Response:

{
"message": "Deleted 5 file(s) from trash"
}

Note: If trash is already empty, returns: {"message": "Trash is already empty"}

Download File

GET /api/files/:id/download

Download a single file or a folder (folders are returned as a ZIP archive).

Validation:

  • id: Required. Must be a string.

Response: The raw file content or a ZIP archive.

Get File or Folder Info

GET /api/files/:id/info

Get basic metadata for a single file or folder.

Path Parameters:

  • id - File or folder ID (required)

Response (file):

{
"id": "file_123",
"name": "document.pdf",
"type": "file",
"size": 1024,
"modified": "2024-01-01T00:00:00Z",
"parentId": "folder_456"
}

Response (folder):

{
"id": "folder_123",
"name": "Reports",
"type": "folder",
"size": null,
"parentId": null,
"folderInfo": {
"totalSize": 1048576,
"fileCount": 25,
"folderCount": 3
}
}
  • size and folderInfo.totalSize are in bytes.
  • For folders, size may be null; use folderInfo.totalSize for the recursive size.

Errors:

  • 404 - File or folder not found or not owned by the user

Replace File Contents

POST /api/files/:id/replace

Replace the contents of an existing file. The file ID and name stay the same; size and modified time are updated. Used when the user chooses "Replace the File" for a duplicate-name upload, and by the Windows desktop app when syncing edits from Word, Excel, PowerPoint, or other desktop editors.

Path Parameters:

  • id - File ID (required)

Form Data:

  • file - New file content (required). Single file in multipart/form-data.

Validation:

  • The file must exist and belong to the authenticated user.
  • MIME type is detected from file content. Stored MIME type is updated to match.

Response:

The updated file object.

{
"id": "file_123",
"name": "document.docx",
"type": "file",
"size": 2048,
"mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"parentId": "folder_456",
"starred": false,
"modified": "2024-01-01T12:00:00Z"
}

Errors:

  • 404 - File not found or not owned by the user
  • 400 - No file in request or invalid file type

Upload Derived File (e.g. Exported Document/PDF)

POST /api/files/:id/derived

Upload a new file that is derived from an existing one while keeping the original file unchanged. This is used by the Windows desktop app when a user opens a document via Open on desktop and then uses Save As or Export (for example, exporting a Word document to PDF or saving a copy as .docx, .xlsx, or .pptx).

The new file is created as a separate entry in the same folder as the original file.

Path Parameters:

  • id - Source file ID (required). The new file is created as a sibling of this file.

Form Data (local / non-S3 deployments):

  • file - Derived file content (required). Single file in multipart/form-data.

S3-backed deployments:

  • When STORAGE_DRIVER=s3, uploads are streamed and streamUploadToS3 sets req.streamedUpload. The desktop client sends the same multipart/form-data request; the server handles streaming and metadata creation.

Validation:

  • The source file must exist and belong to the authenticated user.
  • The derived file name must be a valid file name.
  • MIME type is detected from file content and stored accordingly.
  • Storage quota and max upload size checks apply in the same way as for normal uploads.

Response:

The created file object for the derived file. Common use cases include exported PDFs and alternate Office document formats saved from Word, Excel, or PowerPoint.

{
"id": "file_derived_123",
"name": "document.pdf",
"type": "file",
"size": 4096,
"mimeType": "application/pdf",
"parentId": "folder_456",
"starred": false,
"modified": "2024-01-01T12:05:00Z"
}

Errors:

  • 404 - Source file not found or not owned by the user
  • 400 - No file in request or invalid file type
  • 413 - Storage limit exceeded

Bulk Download Files

POST /api/files/download/bulk

Download multiple files and/or folders as a single ZIP archive.

Request Body:

{
"ids": ["file_123", "file_456", "folder_789"]
}

Validation:

  • ids: Required. Must be a non-empty array of strings.

Response: A ZIP archive containing all selected files and folders.

Note: For single file downloads, use the GET endpoint. This endpoint is optimized for downloading multiple items at once.

File Events

GET /api/files/events

Establish a real-time event stream (Server-Sent Events) for file system changes. Requires Redis to be configured.

Response: A Server-Sent Events stream.