Sharing & Access
Public folio access, access key verification, and OSS tunnel management.
Overview
LiveFolio provides endpoints for controlling public access to folios and managing sharing infrastructure. This section covers:
- Public metadata — retrieve folio info for share pages
- Access key verification — validate passwords for private folios
- Tunnel management — Cloudflare tunnel control (OSS only)
Get Public Folio Metadata
GET /api/files/{id}/public
Returns public-facing metadata for a folio. No authentication required. This is the endpoint used by the share page (/share/{id}) to display folio information before loading the full content.
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
id | string | Folio ID |
Example Request:
curl https://livefolio.cloud/api/files/a1b2c3d/public
Response:
{
"id": "a1b2c3d",
"title": "Q3 Investor Deck",
"description": "Quarterly earnings presentation",
"isPrivate": true,
"allowComments": true,
"presentationModeOnly": false,
"hasAccessKey": true,
"status": "published",
"draft": false,
"latestVersionId": "v3",
"activeFileList": ["index.html", "styles.css", "assets/logo.png"],
"comments": [
{
"id": "c_1718400000000",
"author": "Jane Reviewer",
"text": "Header needs more contrast",
"versionId": "v3",
"filename": "index.html",
"resolved": false
}
],
"reactions": {
"👍": 12,
"❤️": 7
}
}
| Field | Description |
|---|---|
id | Folio ID |
title | Folio title |
description | Folio description |
isPrivate | Whether the folio requires an access key |
allowComments | Whether public comments are enabled |
presentationModeOnly | Whether the folio shows in fullscreen mode only |
hasAccessKey | Whether an access key is set (the key itself is never exposed) |
status | draft or published |
draft | Convenience boolean for status === 'draft' |
latestVersionId | ID of the most recent version |
activeFileList | Array of filenames in the latest version |
comments | Unresolved comments on the latest version |
reactions | Emoji reaction counts |
Notes:
hasAccessKeyindicates whether a password is required but never reveals the key itselfdraft: truemeans the folio is only visible to the owner- The access key is never included in the response — use the POST method to verify it
Verify Access Key
POST /api/files/{id}/public
Content-Type: application/json
Verifies an access key for a private folio. Used by the share page to gate access.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
accessKey | string | Yes | The access key to verify |
Example Request:
curl -X POST https://livefolio.cloud/api/files/a1b2c3d/public \
-H "Content-Type: application/json" \
-d '{"accessKey": "my-secret-password"}'
Response:
{
"success": true
}
If the key is incorrect:
{
"success": false
}
Security Notes:
- Access keys are compared using exact string matching (case-sensitive, trimmed)
- There is no rate limit differentiation between correct and incorrect attempts — the response is always 200 with a boolean
successfield - For OSS, the key is stored in the folio's
accessKeyfield in the flat-file database
Tunnel Management (OSS Only)
GET /api/tunnel
POST /api/tunnel
Manage Cloudflare Quick Tunnels for public folio sharing in OSS (self-hosted) mode. Tunnels expose your local LiveFolio instance to the internet without port forwarding or a public IP.
Availability: OSS mode only. Returns 403 in Cloud mode.
Get Tunnel Status
GET /api/tunnel
Returns the current tunnel status.
curl http://localhost:3000/api/tunnel
Response:
{
"active": true,
"url": "https://random-name.trycloudflare.com",
"customTunnelUrl": ""
}
| Field | Description |
|---|---|
active | Whether a tunnel is currently running |
url | The active tunnel URL (null if not running) |
customTunnelUrl | A custom URL saved in settings (for display purposes) |
Start Tunnel
POST /api/tunnel
Content-Type: application/json
Starts a new Cloudflare Quick Tunnel.
curl -X POST http://localhost:3000/api/tunnel \
-H "Content-Type: application/json" \
-d '{"action": "start"}'
Response:
{
"success": true,
"url": "https://random-name.trycloudflare.com"
}
If a tunnel is already running:
{
"success": true,
"url": "https://random-name.trycloudflare.com",
"message": "Tunnel already running"
}
Stop Tunnel
POST /api/tunnel
Content-Type: application/json
Stops the active tunnel.
curl -X POST http://localhost:3000/api/tunnel \
-H "Content-Type: application/json" \
-d '{"action": "stop"}'
Response:
{
"success": true
}
Save Custom Tunnel URL
POST /api/tunnel
Content-Type: application/json
Saves a custom tunnel URL to settings.json for display in the UI. This does not start a tunnel — it only stores the URL for reference.
curl -X POST http://localhost:3000/api/tunnel \
-H "Content-Type: application/json" \
-d '{
"action": "save_custom",
"customTunnelUrl": "https://my-folio.example.com"
}'
Response:
{
"success": true,
"customTunnelUrl": "https://my-folio.example.com"
}
Error Responses
| Status | Error | Description |
|---|---|---|
| 400 | Invalid action | Unknown action value |
| 403 | Tunnel API only available in OSS mode | Called in Cloud mode |
| 500 | Error message | Tunnel start/stop failure |