The following paths are relative to /api/v1 and require authentication.
| Method | Path | Description |
|---|---|---|
POST |
/batch/delete |
Batch-delete files and folders |
POST |
/batch/move |
Batch-move files and folders |
POST |
/batch/copy |
Batch-copy files and folders |
POST |
/batch/archive-compress |
Create an archive-compress background task |
POST |
/batch/archive-download |
Create a batch ZIP download ticket |
GET |
/batch/archive-download/{token} |
Stream a ZIP by ticket |
Selection-style request bodies use mixed resource selection:
{
"file_ids": [1, 2],
"folder_ids": [10, 11]
}file_idsandfolder_idscan both be present- the total item count per request is capped at 1000
- each item is processed independently; one failure does not roll back the rest
POST /batch/deletePOST /batch/movePOST /batch/copy
return a BatchResult structure with:
succeededfailederrors
The frontend uses this to drive batch progress and grouped toast messages.
POST /batch/archive-compressreturnsTaskInfoPOST /batch/archive-downloadreturnsStreamTicketInfo
Behavior:
- files and folders use the same soft-delete logic as the single-item endpoints
- results are counted per item
- one failure does not stop the rest of the batch
Request body also includes the target folder:
{
"file_ids": [1, 2],
"folder_ids": [10],
"target_folder_id": 99
}Behavior:
- files and folders can be moved together to the same destination
target_folder_id = nullmeans move to root- drag-move and batch-move reuse the same capability
Request body:
{
"file_ids": [1],
"folder_ids": [10],
"target_folder_id": 99
}Behavior:
- file copy does not physically duplicate the blob; it only increments the reference count
- folder copy recursively copies the subtree
- name conflicts at the destination are resolved automatically, just like single-item copy
Creates an archive_compress background task that packages the selected files / folders into a ZIP and writes the result back into the current workspace.
Request body:
{
"file_ids": [1, 2],
"folder_ids": [10],
"archive_name": "workspace-export",
"target_folder_id": 99
}Semantics:
- if
target_folder_id = null, the server first checks whether the selected items all come from the same parent directory; if they do, the ZIP is written back there, otherwise it goes to the root - the endpoint returns
TaskInfo, not a file stream - the result later appears in the background-task API
- the team-space variant is mounted under
/teams/{team_id}/batch/archive-compress
Request body:
{
"file_ids": [1, 2],
"folder_ids": [10],
"archive_name": "workspace-export"
}Success returns a short-lived stream ticket:
{
"code": "success",
"msg": "",
"data": {
"token": "st_xxxxx",
"download_path": "/api/v1/batch/archive-download/st_xxxxx",
"expires_at": "2026-04-12T12:00:00Z"
}
}Key points:
archive_nameis optional; the final file always ends in.zip- the ticket expires after 5 minutes by default
download_pathmay be relative or absolute depending onpublic_site_url- the ticket is bound to the current user and workspace, so it cannot be reused elsewhere
- this path is a short-lived ticket plus direct streaming ZIP download, not a background-task record
The download_path from the previous call returns the raw application/zip stream.
Implementation notes:
- empty folders are preserved
- multiple selected folders are packed according to the current tree shape
- duplicate top-level names inside the ZIP are automatically disambiguated
- only active items that are visible to the current workspace are included