LeafWiki REST API 实测
LeafWiki v0.14.2 REST API 全链路 curl 实测:73 端点全景、Cookie+CSRF 双持认证、页面 CRUD 与乐观锁(PUT 全字段/DELETE 带 version)、树与检索标签、viewer/editor/admin 三角色权限边界、resync/快照/修订运维端点与 ZIP 导入。
LeafWiki REST API 实测
基于 v0.14.2 实测(2026-11-01),目标实例为部署篇 Compose 栈(宿主端口 8141),示例账号
admin/q1w2e3r4。全部请求与响应为服务器上一手回显逐行照抄。官方标注「开发中」的 API Keys 不在本文范围(见《LeafWiki 配置参数详解》第五章)。
一、API 全景
LeafWiki 前后端同体,界面即本套 REST API 的消费者。从发布包内嵌前端产物枚举出全部端点(73 个),按域分组:
| 域 | 端点 |
|---|---|
| 认证 | /api/auth/login、/login/totp、/logout、/me、/refresh-token、/password/forgot、/password/reset、/invite/accept |
| 用户管理 | /api/users(GET/POST)、/api/users/{id}、/users/invite、/users/{id}/invite/resend、/users/me/password、/users/me/totp/* |
| 页面 | /api/pages、/api/pages/{id}(GET/PUT/DELETE)、/move、/copy/{id}、/convert/{id}、/pin、/sort、/favorite、/links、/assets*、`/refactor/preview |
| 定位 | /api/tree、/api/pages/by-path、/api/pages/lookup、/api/pages/ensure、/api/pages/slug-suggestion、/api/pages/permalink/{id} |
| 检索与标签 | /api/search、/api/tags、/api/favorites、/api/links/broken |
| 管理运维 | /api/admin/resync、`/api/admin/settings/public-access |
| 导入 | /api/import/plan、/api/import/execute |
| 杂项 | /api/config、/api/branding*、/api/user-settings、/api/user/avatar |
二、认证模型:Cookie + CSRF 双持
登录(identifier 字段接受用户名或邮箱):
$ curl -s -c cookies.txt -X POST http://127.0.0.1:8141/api/auth/login \
-H 'Content-Type: application/json' -d '{"identifier":"admin","password":"q1w2e3r4"}'
{"accessTokenExpiresAt":1793542984,"message":"Login successful","user":{"id":"H_sIThqDR","username":"admin","email":"admin@localhost","role":"admin","totpEnabled":false,"mustSetPassword":false}}
令牌经 HttpOnly Cookie 下发(access 默认 15m,refresh 168h,见 C1 篇),响应体只给过期时间戳;同时下发可读的 leafwiki_csrf Cookie。所有写操作必须回带 X-CSRF-Token 头(值取该 Cookie),实测缺失时:
{"error":"Invalid CSRF token"}
错误口令实测:
{"error":{"code":"auth_invalid_credentials","message":"Invalid credentials","template":"invalid credentials"}}
续期 POST /api/auth/refresh-token 实测 200;GET /api/auth/me 返回当前身份:
{"email":"admin@localhost","id":"H_sIThqDR","role":"admin","totpEnabled":false,"username":"admin"}
未认证访问业务端点实测 401:
$ curl -s http://127.0.0.1:8141/api/pages/RRpOT2qvR
{"error":"Missing or invalid access token"}
脚本化调用要点:curl -c/-b cookies.txt 维持会话,写操作前 CSRF=$(grep leafwiki_csrf cookies.txt | awk '{print $7}') 取令牌。
三、页面生命周期实测
3.1 建页
POST /api/pages,payload {title, slug, parentId, kind}(kind 取 page/section,parentId 用 root 或节点 ID):
$ curl -s -b cookies.txt -H "X-CSRF-Token: $CSRF" -H 'Content-Type: application/json' \
-X POST http://127.0.0.1:8141/api/pages \
-d '{"title":"Deploy Verify","slug":"deploy-verify","parentId":"root","kind":"page"}'
{"id":"RRpOT2qvR","title":"Deploy Verify","slug":"deploy-verify","version":"2026-11-01T14:08:51.712198164Z","position":1,"kind":"page","children":null,"metadata":{...},"content":"# Deploy Verify\n","path":"deploy-verify","tags":[],"properties":{}}
新页自动获得初始内容 # <title>,响应携带乐观锁 version。
3.2 编辑(全字段 PUT)
PUT /api/pages/{id} 要求全字段 {version,title,slug,content,tags,properties}——只传 {content,version} 实测被拒 page_invalid_request(排障实录见部署篇第六章)。成功响应返回新 version:
{"id":"RRpOT2qvR",...,"version":"2026-11-01T14:10:50.045641994Z",...}
tags 数组直接落盘为 Markdown 前置元数据(实测 data/root/deploy-verify.md 头部 tags: [s9, verify])。
乐观锁:携带过期 version 重试实测:
{"error":{"code":"page_version_conflict","message":"Page was changed by another request","template":"page was changed by another request"}}
正确姿势:先 GET /api/pages/{id} 取最新 version 再 PUT。
3.3 删除
DELETE /api/pages/{id} 必须带 version(查询参数),实测不带时:
{"error":{"code":"page_version_required","message":"Page version is required","template":"page version is required"}}
带 version 成功:
$ curl -s -b cookies.txt -H "X-CSRF-Token: $CSRF" -X DELETE 'http://127.0.0.1:8141/api/pages/vobRAh3vg?version=2026-11-01T14:20:58.217723517Z'
{"message":"Page deleted"}
删除后 GET /api/tree 复核该节点消失。
3.4 树与定位
GET /api/tree 返回全树(嵌套 children,节点含 id/title/slug/path/version/position/kind/metadata):
{"id":"root","title":"root","slug":"root","path":"","version":"...","kind":"section","children":[{"id":"89sSohqvR","title":"Welcome to LeafWiki","slug":"welcome-to-leafwiki",...}]}
按路径取页 GET /api/pages/by-path?path=deploy-verify 实测返回整页对象;/api/pages/lookup、/ensure、/slug-suggestion 为辅助端点;/api/pages/permalink/{id} 面向短链分享(实测以 slug 直访返回 404,正确用法为按页面 permalink ID 访问)。移动/排序/置顶分别走 /move、/sort({orderedIDs:[...]})、/pin({version,pinned})。
四、检索与标签
$ curl -s -b cookies.txt 'http://127.0.0.1:8141/api/search?q=callout'
{"limit":20,"offset":0,"count":1,"items":[{"page_id":"RRpOT2qvR","title":"Deploy Verify","path":"deploy-verify","kind":"page","rank":1,"excerpt":"Deploy Verify S9 实测页面:编辑功能验证。 [x] 建页 [x] 编辑 info LeafWiki <b>callout</b> 实测","tags":["s9","verify"]}],"tag_facets":[]}
要点(均实测):命中词 <b> 高亮内嵌于 title/excerpt;分页 limit/offset;tag_facets 支持标签分面过滤(配合 q 与标签参数);索引随编辑即时更新(编辑后立即可检索到新词)。GET /api/tags 返回全站标签计数:
[{"tag":"s9","count":1},{"tag":"verify","count":1}]
链接审计:GET /api/links/broken 实测 {"links":[]}(无断链)。
五、用户与角色权限实测
POST /api/users 建用户({username,email,password,role},role ∈ admin/editor/viewer):
{"id":"ClOhT23vR","username":"viewer01","email":"viewer01@localhost","role":"viewer","totpEnabled":false,"mustSetPassword":false}
{"id":"GtxR02qvR","username":"editor01","email":"editor01@localhost","role":"editor","totpEnabled":false,"mustSetPassword":false}
三角色边界实测:
| 操作 | viewer01 | editor01 | admin |
|---|---|---|---|
GET /api/pages/{id} 读页 | ✓ 200 | ✓ | ✓ |
POST /api/pages 建页 | 403 {"error":"Editor or Admin role required"} | ✓ 成功建 editor-page | ✓ |
| 用户管理/运维端点 | — | — | ✓ |
GET /api/users(仅 admin)返回用户清单;/users/invite 走 SMTP 邀请(未配邮件时不可用);--editor-limit 可在服务层限制 admin+editor 总数。
六、运维端点实测
POST /api/admin/resync:外部修改磁盘 Markdown 后触发重同步,实测{"ok":true},随后 API 读到外部追加段落;GET /api/pages/{id}/revisions(需--enable-revision):返回修订列表,含id/type(content_update)/authorId/createdAt/contentHash/assetManifestHash与nextCursor分页游标;配套/revisions/latest、/revisions/compare?base=&target=、/revisions/{rid}/restore(POST);GET /api/admin/snapshot与/snapshot/status:快照清单/状态,/snapshot/{name}/download下载 ZIP;/api/admin/restore在线恢复(写入 503 门禁,见 C1 篇第七章);PUT /api/admin/settings/public-access:运行时切换匿名只读模式;GET /api/config:运行态配置全量回显(见 C1 篇第十三章实测快照)。
七、批量导入 API
ZIP 导入两步式:POST /api/import/plan(上传计划,返回目标树与链接改写预览)→ POST /api/import/execute。编辑器/管理员角色可用,支持 Obsidian 风格 [[wiki 链接]] 改写;官方口径「适合结构较干净的目录,不是全格式自动转换器」。
八、小结
LeafWiki 的 REST API 完整覆盖页面 CRUD、树操作、检索、标签、用户角色、修订、快照与运维动作,认证采用 HttpOnly Cookie + X-CSRF-Token 双持,写操作全线乐观锁(version 必带,PUT 需全字段、DELETE 需 version 查询参数)。作为集成面:会话令牌 15m 默认时长适合脚本短任务,长周期自动化建议等待官方 API Keys 就绪或经反代认证头接入。三处实测坑位(PUT 全字段、DELETE 带 version、permalink 语义)已在正文标注,均为一手回显。
延伸阅读:《LeafWiki 二进制与 Compose 部署实战》(环境搭建与排障)、《LeafWiki 介绍与选型指南》(定位与对比)。