LeafPage API
Publish a self-contained HTML report and receive a permanent URL. Reports are immutable snapshots, served from a cookieless content host.
The API lives on the application host https://leafpage.cc; published reports are served from https://leafpage.link. All requests and responses are JSON. The machine-readable spec is at /openapi.json.
For AI agents
There's a ready-to-install Agent Skill for this API — point your AI coding agent at it and it learns to publish reports, read them back, and later update itself. Machine-readable manifest: /.well-known/skills/index.json.
Create a personal access token first, in the portal (https://leafpage.cc) under the account menu → API Tokens. Already have the skill installed? Just tell your agent “update the LeafPage skill” — it checks the fixed manifest URL, verifies file integrity, and asks for your OK before installing anything.
Authentication
Requests authenticate with an Authorization: Bearer lp_… header. Personal access tokens are created in the portal under the account menu → API Tokens; the plaintext value is shown once at creation.
Scopes: reports:read (list, and read your own reports' content), reports:write (upload/modify, implies read), reports:delete. A token lacking the required scope returns 403.
Reading reports
Owners can also fetch a report's raw HTML back with a token, without a browser session: resolve the version's code via /api/config (content host base URL) and /api/group (current_code, or an entry from versions), then request {content}/{code}/ with the same Authorization: Bearer header — page assets fetch the same way. The live links /{name}/ and /@owner/{name}/ serve a platform shell, not the report itself, so always resolve to a pinned /{code}/ first. Full flow and edge cases: llms.txt.
Errors
Errors return { "error": "…" } with the status below. A target owned by another account is reported as 404, indistinguishable from one that does not exist.
| Status | Meaning |
|---|---|
400 | Malformed request — invalid JSON, missing index.html, bad name/encoding, or invalid field. |
401 | Authentication required or not recognized. |
403 | The token lacks the required scope. |
404 | The target does not exist or is owned by another account. |
409 | Name owned by another account, or rename collision. |
413 | A file exceeds the per-file size limit. |
429 | Rate limited — see the Retry-After header. |
507 | A storage quota is full. |