Skip to content
Back

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:

ParameterTypeDescription
idstringFolio 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
  }
}
FieldDescription
idFolio ID
titleFolio title
descriptionFolio description
isPrivateWhether the folio requires an access key
allowCommentsWhether public comments are enabled
presentationModeOnlyWhether the folio shows in fullscreen mode only
hasAccessKeyWhether an access key is set (the key itself is never exposed)
statusdraft or published
draftConvenience boolean for status === 'draft'
latestVersionIdID of the most recent version
activeFileListArray of filenames in the latest version
commentsUnresolved comments on the latest version
reactionsEmoji reaction counts

Notes:

  • hasAccessKey indicates whether a password is required but never reveals the key itself
  • draft: true means 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:

FieldTypeRequiredDescription
accessKeystringYesThe 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 success field
  • For OSS, the key is stored in the folio's accessKey field 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": ""
}
FieldDescription
activeWhether a tunnel is currently running
urlThe active tunnel URL (null if not running)
customTunnelUrlA 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

StatusErrorDescription
400Invalid actionUnknown action value
403Tunnel API only available in OSS modeCalled in Cloud mode
500Error messageTunnel start/stop failure