Export a folder and all its files (including nested folders) as a ZIP archive. The folder structure is preserved in the archive.
Endpoint
GET /api/user/folders/:id/export
Authentication
Requires authentication via API token in the Authorization header.
Path Parameters
The ID of the folder to export
Response
Returns a ZIP file containing all files in the folder and its subfolders. The folder structure is preserved within the archive.
Content-Type: application/zip
Content-Disposition: attachment; filename="{folder_name}.zip"
Behavior
- The export includes all files in the folder recursively
- Subfolder structure is preserved in the ZIP archive
- Files maintain their original names
- If a folder contains no files, the export will be aborted
- Only files that can be read from the datasource are included
- You must own the folder to export it
Example Request
curl -X GET "https://your-zipline-instance.com/api/user/folders/clx123/export" \
-H "Authorization: your-api-token" \
-o folder_export.zip
Download with original folder name
curl -X GET "https://your-zipline-instance.com/api/user/folders/clx123/export" \
-H "Authorization: your-api-token" \
-O -J
async function exportFolder(folderId: string) {
const response = await fetch(
`https://your-zipline-instance.com/api/user/folders/${folderId}/export`,
{
headers: {
'Authorization': 'your-api-token',
},
}
);
if (!response.ok) {
throw new Error('Export failed');
}
// Get filename from Content-Disposition header
const disposition = response.headers.get('content-disposition');
const filename = disposition?.match(/filename="(.+)"/)?.[1] || 'folder.zip';
// Download the file
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
}
import requests
def export_folder(folder_id):
url = f'https://your-zipline-instance.com/api/user/folders/{folder_id}/export'
headers = {'Authorization': 'your-api-token'}
response = requests.get(url, headers=headers, stream=True)
response.raise_for_status()
# Extract filename from Content-Disposition header
disposition = response.headers.get('content-disposition', '')
filename = disposition.split('filename="')[1].split('"')[0] if 'filename=' in disposition else 'folder.zip'
with open(filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return filename
ZIP Structure Example
For a folder structure like:
Screenshots/
├── 2024/
│ ├── January/
│ │ ├── screenshot1.png
│ │ └── screenshot2.png
│ └── February/
│ └── screenshot3.png
└── logo.png
The exported ZIP will contain:
Screenshots.zip
├── logo.png
├── 2024/
│ ├── January/
│ │ ├── screenshot1.png
│ │ └── screenshot2.png
│ └── February/
│ └── screenshot3.png
Error Responses
{
"error": "Forbidden",
"message": "You do not own this folder",
"statusCode": 403
}
{
"error": "Not Found",
"message": "Folder not found",
"statusCode": 404
}
Notes
- Large folders may take time to export
- The ZIP is created with maximum compression (level 9)
- Files that cannot be read from storage are skipped with a warning in the server logs
- Empty folders (containing no files) will abort the export
- You must own the folder to export it - admins cannot export other users’ folders
- The export endpoint uses response hijacking to stream the ZIP directly, so standard JSON error responses may not apply once streaming begins