Skip to content
Back

Files

CRUD operations for folios — list, create, read, update, and delete.

Overview

Folios are the core resource in LiveFolio. Each folio contains HTML files, versions, comments, reactions, and metadata. All file endpoints require authentication.

List Folios

GET /api/files
Authorization: Bearer lf_live_xxxxxxxxxxxx

Returns all folios in the authenticated workspace, ordered by most recently updated.

Response: Array of folio objects:

[
  {
    "id": "a1b2c3d",
    "title": "Q3 Investor Deck",
    "description": "Quarterly earnings presentation",
    "createdAt": "2025-01-15T10:30:00.000Z",
    "updatedAt": "2025-06-20T14:22:00.000Z",
    "isPrivate": false,
    "allowComments": true,
    "presentationModeOnly": false,
    "status": "published",
    "projectMode": "deck",
    "versions": [...],
    "comments": [...],
    "reactions": { "👍": 5, "❤️": 3 },
    "_storageBytes": 245760
  }
]

Cache: Responses include Cache-Control: public, max-age=5, stale-while-revalidate=60.

Create a Folio

POST /api/files
Authorization: Bearer lf_live_xxxxxxxxxxxx
Content-Type: application/json

Request Body:

FieldTypeRequiredDescription
titlestringYesFolio title (trimmed, non-empty)
initialHtmlstringNo*Full HTML document for index.html
defaultFilesobjectNo*Map of filename to content (e.g. {"index.html": "...", "styles.css": "..."})
descriptionstringNoOne-line description (defaults to "Custom HTML Multipages")
projectModestringNoOne of: deck, document, spreadsheet, dashboard, infography (default: deck)
isPrivatebooleanNoRequire access key to view (OSS: always false)
accessKeystringNoPassword for private folios
allowCommentsbooleanNoEnable public comments (default: true)
presentationModeOnlybooleanNoFullscreen presentation mode only (default: false)
statusstringNodraft or published (default: draft)
designPreferencesobjectNoTheme, typography, palette, libraries, customColors, customGuidelines
referenceFilesarrayNoReference documents for AI context
collaboratorsarrayNoEmail addresses of collaborators (Cloud only)

*At least one of initialHtml or defaultFiles must be provided.

Example Request:

curl -X POST https://livefolio.cloud/api/files \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer lf_live_xxxxxxxxxxxx" \
  -d '{
    "title": "Product Launch Page",
    "initialHtml": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><script src=\"https://cdn.tailwindcss.com\"></script></head><body class=\"bg-white\"><h1 class=\"text-4xl font-bold\">Coming Soon</h1></body></html>",
    "projectMode": "deck",
    "description": "Landing page for our new product",
    "status": "draft"
  }'

Response (201):

{
  "success": true,
  "project": {
    "id": "a1b2c3d",
    "title": "Product Launch Page",
    "description": "Landing page for our new product",
    "createdAt": "2025-06-20T14:22:00.000Z",
    "updatedAt": "2025-06-20T14:22:00.000Z",
    "isPrivate": false,
    "allowComments": true,
    "status": "draft",
    "projectMode": "deck",
    "versions": [
      {
        "versionId": "v1",
        "commitMessage": "Genesis Initial Draft Commit",
        "createdAt": "2025-06-20T14:22:00.000Z",
        "author": "Workspace Founder",
        "files": {
          "index.html": "<!DOCTYPE html>..."
        }
      }
    ],
    "comments": [],
    "collaborators": []
  }
}

Error Responses:

StatusErrorDescription
400Title is requiredMissing or empty title
401UnauthorizedNo valid auth context
402STORAGE_EXCEEDEDOver storage quota (Cloud mode)

Get a Folio

GET /api/files/{id}
Authorization: Bearer lf_live_xxxxxxxxxxxx

Returns the full folio object including all versions, files, comments, and metadata.

Path Parameters:

ParameterTypeDescription
idstringFolio ID (e.g., a1b2c3d or UUID in Cloud mode)

Example Request:

curl https://livefolio.cloud/api/files/a1b2c3d \
  -H "Authorization: Bearer lf_live_xxxxxxxxxxxx"

Response: Full folio object (same shape as the project field in create response).

Error Responses:

StatusErrorDescription
401UnauthorizedNo valid auth context (Cloud mode)
404Project not found.Folio does not exist

Update a Folio

PUT /api/files/{id}
Authorization: Bearer lf_live_xxxxxxxxxxxx
Content-Type: application/json

Updates a folio's files, metadata, or both. Supports gzip-compressed payloads for large folios.

Path Parameters:

ParameterTypeDescription
idstringFolio ID

Request Body:

FieldTypeDescription
filesobjectMap of filename to content (alias: updated_files)
commitMessagestringVersion commit message (alias: change_message)
titlestringUpdated title
descriptionstringUpdated description
isPrivatebooleanToggle private mode
accessKeystringSet/change access key
allowCommentsbooleanToggle comments
presentationModeOnlybooleanToggle presentation mode
projectModestringChange project mode
designPreferencesobjectUpdate design system settings
statusstringdraft or published
collaboratorsarrayUpdate collaborator list
restoreVersionIdstringRestore to a specific version (creates a new version)
reactionsobjectSet reaction counts
publicTunnelEnabledbooleanEnable/disable public tunnel (OSS)
referenceFilesarrayUpdate AI reference files
_gzbooleanSignal that _d field contains gzip-compressed JSON
_dstringBase64-encoded gzip-compressed payload

Providing files creates a new version. Omitting files updates only metadata.

Example — Update metadata only:

curl -X PUT https://livefolio.cloud/api/files/a1b2c3d \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer lf_live_xxxxxxxxxxxx" \
  -d '{
    "title": "Q3 Investor Deck (Revised)",
    "status": "published"
  }'

Example — Add a new version:

curl -X PUT https://livefolio.cloud/api/files/a1b2c3d \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer lf_live_xxxxxxxxxxxx" \
  -d '{
    "files": {
      "index.html": "<!DOCTYPE html>...updated...",
      "styles.css": "body { margin: 0; }"
    },
    "commitMessage": "Updated hero section with new branding"
  }'

Response:

{
  "success": true,
  "project": { ... }
}

Gzip Compression: For folios larger than ~1 MB, compress the payload:

const payload = { files: { "index.html": htmlContent }, commitMessage: "Update" };
const compressed = pako.gzip(JSON.stringify(payload));
const body = {
  _gz: true,
  _d: btoa(String.fromCharCode(...compressed))
};

Error Responses:

StatusErrorDescription
400INVALID_JSONMalformed request body
400INVALID_BODYFailed to decompress gzip payload
401UnauthorizedNo valid auth context
404Project not foundFolio does not exist
413FOLIO_TOO_LARGERequest body exceeds 20 MB

Delete a Folio

DELETE /api/files/{id}
Authorization: Bearer lf_live_xxxxxxxxxxxx

Permanently deletes a folio and all associated assets (storage files, versions, comments).

Path Parameters:

ParameterTypeDescription
idstringFolio ID

Example Request:

curl -X DELETE https://livefolio.cloud/api/files/a1b2c3d \
  -H "Authorization: Bearer lf_live_xxxxxxxxxxxx"

Response:

{
  "success": true
}

Error Responses:

StatusErrorDescription
401UnauthorizedNo valid auth context (Cloud mode)
500Error messageDeletion failed

Get Design Brief

GET /api/files/{id}/brief
Authorization: Bearer lf_live_xxxxxxxxxxxx

Returns a structured markdown design brief compiled from unresolved feedback pins and current file structure. Useful for feeding to AI agents for targeted revisions.

Example Request:

curl https://livefolio.cloud/api/files/a1b2c3d/brief \
  -H "Authorization: Bearer lf_live_xxxxxxxxxxxx"

Response:

{
  "title": "Product Launch Page",
  "description": "Landing page for our new product",
  "brief": "# LiveFolio Design Brief: Product Launch Page\n\n**Description**: Landing page...\n\n## 🎨 Current Open Feedback & Visual Annotations\n...",
  "openComments": [...]
}