Uploading Files
Upload single files or batch upload images to a folio via the REST API.
Overview
LiveFolio provides two endpoints for uploading files into an existing folio's latest version. These are designed for programmatic asset uploads from CI/CD pipelines, design tools, or build scripts.
Use the PUT /api/files/ endpoint for full versioned updates. Use upload endpoints when you only need to add or overwrite individual files.
Single File Upload
POST /api/files/{id}/upload
Authorization: Bearer lf_live_xxxxxxxxxxxx
Content-Type: application/octet-stream
x-file-path: assets/logo.png
Uploads a single file as raw binary data. The file path is specified via the x-file-path header.
Headers:
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer API key |
Content-Type | Yes | Must be application/octet-stream |
x-file-path | Yes | Target path within the folio (e.g., assets/logo.png, images/hero.jpg) |
Body: Raw binary file content.
Limits:
- Maximum file size: 25 MB
- Supported image formats: PNG, JPEG, GIF, WebP, ICO, SVG, BMP
Example Request:
curl -X POST https://livefolio.cloud/api/files/a1b2c3d/upload \
-H "Authorization: Bearer lf_live_xxxxxxxxxxxx" \
-H "Content-Type: application/octet-stream" \
-H "x-file-path: assets/logo.png" \
--data-binary @logo.png
Response:
{
"success": true,
"path": "assets/logo.png"
}
Error Responses:
| Status | Error | Description |
|---|---|---|
| 400 | Missing x-file-path header | No file path specified |
| 404 | Not found | Folio does not exist |
| 413 | FILE_TOO_LARGE | File exceeds 25 MB limit |
Batch Upload (Multipart)
POST /api/files/{id}/upload-batch
Authorization: Bearer lf_live_xxxxxxxxxxxx
Content-Type: multipart/form-data
Uploads multiple files in a single request using multipart/form-data. All files are applied to the folio's latest version in one transaction.
This endpoint bypasses Next.js body size limits because multipart data is streamed, not buffered. It also avoids the 33% size overhead of base64 encoding.
Request Body: Standard multipart/form-data with each part being a file. The part's filename field is used as the folio file path.
Limits:
- No hard file count limit (bounded by request timeout)
- Supported formats: same as single upload
Example Request:
curl -X POST https://livefolio.cloud/api/files/a1b2c3d/upload-batch \
-H "Authorization: Bearer lf_live_xxxxxxxxxxxx" \
-F "assets/logo.png=@logo.png" \
-F "assets/hero.jpg=@hero.jpg" \
-F "assets/icon.svg=@icon.svg"
Response:
{
"success": true,
"count": 3
}
Error Responses:
| Status | Error | Description |
|---|---|---|
| 400 | No image files in form data | No valid files in the request |
| 404 | Not found | Folio does not exist |
How It Works
Both endpoints write files into the current latest version of the folio. They do not create a new version — the files are merged into the existing file map of the most recent version.
For versioned updates (creating a new version with a commit message), use PUT /api/files/{id} with the files and commitMessage fields.
In Cloud mode, uploaded images are automatically processed: base64-encoded images are extracted and stored in the asset store, with the folio version receiving lightweight asset:// pointers instead of inline base64 data. This keeps the database lean and improves read/write performance.