DailyTxT 2.6.4 API 使用详解
DailyTxT 2.6.4 REST API 全表面逐端点实测:JWT Cookie 会话、日记/标签/模板/附件/地图/统计各域、免登录备份端点 backupUser、HTML 导出与导入闭环、管理 API 与错误码行为
DailyTxT 2.6.4 API 使用详解
目标:逐端点实测 DailyTxT 2.6.4 的 REST API 全表面——认证链(注册/登录/Cookie 会话)、日记读写、标签、模板、附件、地图标记、备份/导入/HTML 导出与管理端点,覆盖参数格式、成功回显与错误码行为。已在 Ubuntu 26.04.1 LTS(x86_64,Docker 29.9.2,
phitux/dailytxt:2.6.4,端口 8137)实测通过。
一、环境信息
- 实例:容器
dailytxt-264-web(compose 项目dailytxt-264-stack),宿主http://127.0.0.1:8137→ nginx 80 → Go 后端 8000 - 部署与数据卷配置见 《DailyTxT 2.6.4 Docker Compose 部署指南》;环境变量语义见 《DailyTxT 2.6.4 配置参数详解》
- 演示账号:
admin/q1w2e3r4;管理面板密码q1w2e3r4(ADMIN_PASSWORD) - 客户端工具:
curl(cookie jar 维持会话)+python3(生成 uuid / URL 编码) - 路由挂载:所有端点在
/api/前缀下(Gohttp.StripPrefix("/api")),无版本号;前端 SPA 与 API 同源
二、前置条件
- DailyTxT 容器运行中,
curl http://127.0.0.1:8137/api/version有响应; - 已注册账号(或
ALLOW_REGISTRATION=true可现场注册,见 4.1); - 下文所有请求以 shell 变量约定:
B=http://localhost:8137,登录态经curl -b cookies.txt携带。
⚠️ 实操坑:cookie jar 与域名绑定。用
127.0.0.1登录写入的 cookie,请求localhost时 curl 不会带出,表现为莫名 401。全程统一主机名。
三、API 总览
| 约定 | 内容 |
|---|---|
| 协议 | REST,请求/响应 JSON(文件与导出为 multipart / zip 流) |
| 认证 | 登录签发 token Cookie(JWT HS256,HttpOnly; SameSite=Lax),后续请求自动携带;无 Bearer/API Key 机制 |
| 超时 | 普通端点 15 秒 TimeoutHandler;长任务端点(login、statistics、uploadFile、downloadFile、allGPXFiles、exportData、importData、backup、backupUser)不设超时(源码 main.go 实测清单) |
| 反向代理 | nginx client_max_body_size 0(附件上传不限体积,应用层单文件限 500MB)、proxy_read_timeout 6000s |
| 错误格式 | 纯文本 http.Error(如 Unauthorized、Missing translations parameter),非 JSON |
端点域一览(路由表源码实查 + 本篇逐个实测):
| 域 | 前缀 | 鉴权 |
|---|---|---|
| 版本 | /api/version | 公开 |
| 用户 | /api/users/* | login/register/logout/migrationProgress/isRegistrationAllowed 公开,其余需会话 |
| 日记/标签/模板/附件/地图/备份 | /api/logs/* | 会话(backupUser 例外,见 5.7) |
| 管理 | /api/admin/* | 会话 + admin_password 双重校验 |
四、认证与首次调用
4.1 注册与登录
curl -s -X POST $B/api/users/register -H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4"}'
{"success":true}
注册被禁时(ALLOW_REGISTRATION=false 默认值):
Registration is not allowed
http=403
重复注册实测返回 Internal Server Error: username already exists(HTTP 500,非 409,见 FAQ 7.7)。
登录:
curl -s -c cookies.txt -X POST $B/api/users/login -H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4"}'
{"available_backup_codes":-1,"migration_started":false,"username":"admin"}
响应同时下发会话 Cookie(实测头):
Set-Cookie: token=<JWT>; Path=/; Expires=Fri, 11 Dec 2026 11:42:18 GMT; HttpOnly; SameSite=Lax
Expires 即 LOGOUT_AFTER_DAYS(本实例设 40)。available_backup_codes:-1 表示尚未生成备份码。
4.2 会话校验与登出
curl -s -b cookies.txt $B/api/users/check
{"user_id":1,"username":"admin"}
无 cookie 访问受保护端点:Unauthorized(401)。登出:
curl -s -b cookies.txt $B/api/users/logout
{"success":true}
⚠️ 实测:
logout仅清服务端下发 cookie 的意图,旧 JWT 在有效期内仍可继续调 API(登出后带旧 cookiecheck仍返回 200)。服务端全局吊销的唯一手段是轮换SECRET_TOKEN(配置篇 5.1 实测 401)。
4.3 版本检查
curl -s $B/api/version
{"current_version":"2.6.4","latest_overall_version":"2.6.4","latest_stable_version":"2.6.4"}
该端点后端实时访问 Docker Hub,容器出网受限时返回 Request timeout(15s),修复方法(HTTPS_PROXY)见部署篇 FAQ 11.1。
五、各 API 域详解
5.1 日记域(/api/logs/)
写日记 saveLog(POST JSON,day/month/year 定位,text 支持 Markdown):
curl -s -b cookies.txt -X POST $B/api/logs/saveLog -H 'Content-Type: application/json' \
-d '{"day":1,"month":11,"year":2026,"text":"# DailyTxT 实测\n端到端加密日记第一篇。","date_written":"2026-11-01"}'
{"history_available":true,"success":true}
读日记 getLog(query 三参数):
curl -s -b cookies.txt "$B/api/logs/getLog?year=2026&month=11&day=1"
{"date_written":"2026-11-01","files":[],"history_available":true,"pins":[],"tags":[],"text":"# DailyTxT 实测\n端到端加密日记第一篇。"}
修改留痕 getHistory(同一篇多次 saveLog 后实测):
[{"date_written":"2026-11-01","text":"# DailyTxT 实测\n端到端加密日记第一篇。"}]
阅读模式 loadMonthForReading(整月,含标签/标记解析):
[{"date_written":"2026-11-01","day":1,"pins":[{"id":1,"lat":31.2304,"lon":121.4737,"text":"上海"}],"tags":[1],"text":"# DailyTxT 实测\n端到端加密日记第一篇。"}]
删除一天 deleteDay(先写 2 日再删,实测序列):
{"history_available":false,"success":true}
{"success":true}
{"date_written":"","files":[],"pins":[],"tags":[],"text":""}
书签 bookmarkDay 与标记日查询:
{"bookmarked":true,"success":true}
getMarkedDays 必须带 year 且带 month(缺参实测分别返回 Invalid year parameter / Invalid month parameter)。getALookBack 需 month+year+day 三参数(缺一报对应 Invalid ... parameter)。
5.2 标签域
创建→列表→挂到日记→搜索的完整实测链:
curl -s -b cookies.txt -X POST $B/api/logs/saveNewTag -H 'Content-Type: application/json' \
-d '{"name":"写作","color":"#e91e63","icon":"✍️"}'
{"success":true}
[{"color":"#e91e63","icon":"✍️","id":1,"name":"写作"}]
addTagToLog({"tag":1,"day":1,"month":11,"year":2026})返回 {"success":true};removeTagFromLog、editTag、deleteTag 同构。
全文搜索(服务端解密后检索,这正是它不做客户端 E2E 的原因):
curl -s -b cookies.txt "$B/api/logs/searchString?searchString=加密"
[{"day":1,"month":"11","text":"DailyTxT 实测 端到端<b>加密</b>日记第一篇。","year":"2026"}]
命中词用 <b> 包裹。searchTag 按标签名检索返回整篇原文。
5.3 模板域
saveTemplates 提交数组全量覆盖,getTemplates 回读(实测):
{"success":true}
[{"is_default":true,"name":"晨间模板","text":"## 今日三件事\n- "}]
5.4 附件域
上传 uploadFile:multipart 表单,file 字段 + query 参数 uuid&day&month&year(uuid 客户端自生成;缺 uuid 实测报 Missing uuid parameter):
U=$(python3 -c "import uuid; print(uuid.uuid4())")
curl -s -b cookies.txt -X POST "$B/api/logs/uploadFile?uuid=$U&day=1&month=11&year=2026" \
-F "file=@sample.txt"
{"success":true}
上传后 getLog 的 files 数组(实测:filename 明文、enc_filename 密文并存,落盘文件本体加密):
{"files":[{"enc_filename":"YgOZVhbIb1JHacfJqYFLxdrIYGOzc5jpuAdeEfig2H8wcTF63w4=","filename":"sample.txt","size":38,"uuid_filename":"902adb87-0ff4-43f0-900e-b8d02d5f6776"}]}
下载 downloadFile(?uuid=$U)实测 http=200 bytes=38,内容与上传原文一致。renameFile、reorderFiles、deleteFile 均返回 {"success":true};GPX 轨迹文件用 allGPXFiles 聚合查询。
5.5 地图标记域
addPin(日记页挂坐标点,实测上海外滩):
{"pin":{"id":1,"lat":31.2304,"lon":121.4737,"text":"上海"},"success":true}
allPins 按天聚合:
[{"day":1,"month":11,"pins":[{"id":1,"lat":31.2304,"lon":121.4737,"text":"上海"}],"year":2026}]
updatePinText / movePin / deletePin 实测均 {"success":true};修改后 getLog 回读可见新值("pins":[{"id":1,"lat":31.24,"lon":121.49,"text":"上海·外滩"}])。
5.6 用户设置与统计域
getUserSettings 返回全量偏好 JSON(节选,实测):
{"aLookBackYears":[1,5,10],"background":"gradient","checkForUpdates":true,"defaultMap":"osm","firstDayOfWeek":"monday","language":"en","timezone":"UTC","useMap":true,"writeDateFormat":"2-digit"}
saveUserSettings 全量提交修改(实测把 language 改为 zh 后回读生效)。statistics 返回逐日统计(字数/文件/标签/书签,供 GitHub 式分布图):
[{"year":2026,"month":11,"day":1,"wordCount":13,"fileCount":0,"fileSizeBytes":0,"pinCount":0,"tags":[1],"isBookmarked":false}]
validatePassword(改密前置校验):
{"available_backup_codes":-1,"valid":true}
createBackupCodes(带当前密码)实测生成 6 个一次性备份码(仅展示一次):
{"available_backup_codes":-1,"backup_codes":["$3jv{mJyM%","9C]#XMWRo#","V[06~4Ae1~","W9{aIb!hu4","TVLD3$(W39","8h=#c2R9GP"],"success":true}
不带密码直接调用返回 {"message":"Error checking password","success":false}。changePassword、changeUsername、deleteAccount、checkChangelog(实测 {"changelog":null})同域。
5.7 备份、导出与导入域
backup(POST,登录态,加密与否可选):
curl -s -b cookies.txt -X POST $B/api/logs/backup -H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4","encrypted":false,"includeFiles":true,"includeTemplates":true,"includeTags":true,"includePins":true,"includeBookmarks":true}' \
-o backup_plain.zip -w 'http=%{http_code} bytes=%{size_download}\n'
http=200 bytes=806
Archive: backup_plain.zip
Length Date Time Name
--------- ---------- ----- ----
156 1980-00-00 00:00 tags.json
162 1980-00-00 00:00 templates.json
484 1980-00-00 00:00 2026/11.json
--------- -------
802 3 files
encrypted:true 时 zip 额外含 user.json(密钥材料,4 文件 3581B 解包,实测 http=200 bytes=2566)。
backupUser(POST /api/logs/backupUser,免登录——专为 cron 自动备份设计,凭据即鉴权):同上参数直接调用,实测 http=200 bytes=806 与登录态备份字节一致。密码错误实测:
Error getting encryption key: error creating cipher: chacha20poly1305: bad key length
http=500
exportData(GET,HTML 导出):参数 period=periodAll|periodVariable(+startDate/endDate)、split=month|year|aio、translations(必填,完整 JSON)、imagesInHTML/tagsInHTML/pinsInHTML/extendedFormatting 布尔开关。缺 translations 实测 400 Missing translations parameter;完整调用实测返回 zip:
http=200 bytes=3558 type=application/zip
Archive: DailyTxT_export.html (14016 B)
periodVariable&split=month 按区间出月包(实测 200,DailyTxT_2026-11.html 13423B)。⚠️ translations 必须含 7 元素 weekdays 数组,否则后端越界 panic(见 FAQ 7.5)。
importData(POST multipart):file=@备份.zip + encrypted + password。实测把 5.7 的 backup_plain.zip 导入第二个用户后,getLog 完整还原日记、标签与地图标记:
{"success":true}
{"date_written":"2026-11-01","files":[],"history_available":false,"pins":[{"id":1,"lat":31.2304,"lon":121.4737,"text":"上海"}],"tags":[1],"text":"# DailyTxT 实测\n端到端加密日记第一篇。"}
5.8 管理域(/api/admin/)
全部需登录态 + 请求体带 admin_password:
curl -s -b cookies.txt -X POST $B/api/admin/validate-password \
-H 'Content-Type: application/json' -d '{"password":"q1w2e3r4"}'
{"valid":true}
错误密码返回 {"valid":false};无登录态则直接 401。get-data 返回运行时配置与每用户磁盘占用(配置篇 3.2 实测回显)。open-registration 临时开放注册(实测 60 秒档):
{"duration":60,"success":true,"until":"2026-11-01T11:22:01Z"}
delete-user(实测删除第二用户 {"success":true})、delete-old-data(无 v1 遗留数据时返回 Old directory does not exist)。
六、分页/过滤/排序通用约定
DailyTxT 的 API 没有分页与排序参数:日记天然按 year/month/day 定位(getLog 单日、loadMonthForReading 整月、statistics 全量逐日数组),列表端点(allPins、getTags、getTemplates、searchString)一次全量返回。过滤靠路径语义:搜索词(searchString/searchTag)、时间区间(exportData 的 startDate/endDate)。多用户隔离实测:第二个用户登录后 getLog 同一天返回全空 {"date_written":"","files":[],"pins":[],"tags":[],"text":""},无任何跨用户读取通道。
七、常见问题
7.1 一切正常却 401? 先查 cookie jar 域名匹配(第二节警告);再查 SECRET_TOKEN 是否变过(容器重建/变量未导出,配置篇 5.1)。
7.2 uploadFile 报 Missing uuid parameter? uuid 是 query 参数且由客户端生成(python3 -c "import uuid; print(uuid.uuid4())"),不在 multipart 表单里。
7.3 exportData 400 Invalid period parameter? period 只接受 periodAll / periodVariable(不是 all),且 split 与 translations 必填。
7.4 backupUser 免登录安全吗? 它用用户名+口令现派生密钥再打包,口令错误即失败(5.7 实测 500)。适合 cron,但意味着备份脚本里存有明文口令,建议配合文件权限 600 与目标机隔离。
7.5 exportData 返回 502 Bad Gateway? 实测 translations JSON 缺 weekdays(或不足 7 元素)触发后端 translations.Weekdays[weekday] 越界 panic;Go net/http 恢复 panic 后断开连接,nginx 报 502,进程不受影响(随后请求正常)。传入完整 weekdays 数组即恢复 200。
7.6 logout 后旧 cookie 还能用? 是(4.2 实测)。JWT 无状态,有效期 = LOGOUT_AFTER_DAYS。全局吊销请轮换 SECRET_TOKEN。
7.7 重复注册返回 500 而不是 409? 实测回显 Internal Server Error: username already exists(HTTP 500)。脚本化注册先调 isRegistrationAllowed 并容忍 500 视为已存在。
7.8 GET /api/version 超时? 后端实时访问 Docker Hub(15s 超时策略),出网受限环境注入 HTTPS_PROXY 或关闭用户设置 checkForUpdates(部署篇 FAQ 11.1 实测修复)。
八、参考链接
- 路由表源码(backend/main.go,查询日期 2026-11-01):https://github.com/PhiTux/DailyTxT/blob/main/backend/main.go
- 官方 README(功能与备份 API 说明):https://github.com/PhiTux/DailyTxT
- 站内姊妹篇:《DailyTxT 2.6.4 Docker Compose 部署指南》、《DailyTxT 2.6.4 配置参数详解》