LubeLogger 1.7.4 REST API 使用详解
LubeLogger 1.7.4 REST API 实战:接口文档页 /api 与 74 个端点分域速查、Basic 认证与 API Key 双认证、车辆/保养/加油记录增删改查全实测、PUT 方法约束与区域格式开关排障。
LubeLogger 1.7.4 REST API 使用详解
目标:把 LubeLogger 1.7.4 的 REST API 用起来——接口文档页在哪、两种认证(Basic 认证 / API Key)怎么用、车辆与各类记录的增删改查逐条实测、区域格式开关与常见坑。全部请求与响应回显均在 Ubuntu 22.04 实机(v1.7.4,端口 8131)上用 curl 实测,示例凭据为 Root 用户
admin/q1w2e3r4。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64)
- LubeLogger:v1.7.4(自带 Kestrel Web 服务器,服务端口 8080,本机映射为 8131)
- 实例状态:认证已启用(Root 用户 admin),已录入 1 辆车(2019 Nissan Altima,id=1)
- 接口文档页:
http://127.0.0.1:8131/api(实例自带交互式文档,74 个端点) - 客户端工具:curl(8.x)+ 登录会话 Cookie(生成 API Key 用)
二、前置条件
2.1 端点与文档页
- 服务根地址:
http://<实例IP>:8080(或你的反代地址),本文以http://127.0.0.1:8131书写; - 接口文档页固定在
/api。浏览器打开即是全部端点的交互式文档(方法、参数、JSON 请求样例、Execute 按钮)。实测/swagger与/swagger/index.html均返回 404——LubeLogger 没有部署 Swagger UI,网上把它叫"swagger 页"实为/api自带文档页; - 认证启用后文档页本身也受保护:未带凭据访问
/api实测返回401,浏览器访问会跳登录页。
2.2 认证方式总览
v1.7.4 支持两种 API 认证(认证未启用时两者都不需要):
| 方式 | 凭据形态 | 请求形态 | 适用范围 |
|---|---|---|---|
| Basic 认证 | 用户名:密码(RFC2617,Base64) | Authorization: Basic <b64> 或 https://user:pass@host/api/...(行内 URL 授权) | 全部端点 |
| API Key | 用户级长期密钥 | 请求头 x-api-key: <key> 或查询参数 ?apiKey=<key> | 仅 /api、/kiosk、/images、/documents、/temp 路径前缀 |
两条硬约束(官方文档 + 源码核对):
- Basic 认证凭据按
用户名:密码拼接后 Base64,用户名与密码都不能含冒号:; - API Key 仅在
/api等前缀路径被接受,用它访问普通页面(如/Home/Index)实测被拒(302 跳登录)。
2.3 客户端工具
任意 HTTP 客户端均可;官方文档还提供 Postman Collection。本文全部用 curl。
三、API 总览
3.1 协议与编码约定
- 协议:HTTP/1.1 REST;GET 查询、POST 新增、PUT 更新、DELETE 删除(方法用错时行为见第 7.3 节实测排障);
- 请求体支持三种编码(1.4.2+):
application/json、x-www-form-urlencoded、form-data;官方建议传 JSON——表单编码会把一切转成字符串,无法传数值类型; - 响应格式默认区域敏感(数字/日期均为字符串),加
culture-invariant请求头或实例级LUBELOGGER_INVARIANT_API=true后类型保真(详见第六章); - 限流:官方未设明确限流约定,
/api下的读写与页面同进程同库,脚本化调用注意节流; - 实时通道:WebSocket Hub 在
/api/ws(SignalR,提醒推送等场景用,REST 场景不涉及)。
3.2 端点全景(74 个,按域分组)
| 域 | 端点(通用模式) | 说明 |
|---|---|---|
| 车辆 | /api/vehicles(GET 列表)、/api/vehicles/add、/api/vehicles/update、/api/vehicles/delete、/api/vehicle/info、/api/vehicle/adjustedodometer | 车辆 CRUD 与里程修正 |
| 保养记录 | /api/vehicle/servicerecords、.../all、.../add、.../update、.../delete | Service 记录 |
| 维修记录 | /api/vehicle/repairrecords(同上五件套) | Repair 记录 |
| 改装记录 | /api/vehicle/upgraderecords(同上五件套) | Upgrade 记录 |
| 加油记录 | /api/vehicle/gasrecords(同上五件套) | Fuel 记录(含电动车 SOC 字段) |
| 里程记录 | /api/vehicle/odometerrecords、.../all、.../add、.../update、.../delete、.../latest、.../recalculate | 里程流水 |
| 计划 | /api/vehicle/planrecords(五件套) | Planner 待办 |
| 税费 | /api/vehicle/taxrecords、.../all、.../add、.../update、.../check、.../delete | Taxes 记录 |
| 物料 | /api/vehicle/supplyrecords(五件套) | Supplies 台账 |
| 提醒 | /api/vehicle/reminders(五件套)+ .../send | Reminders,send 触发提醒推送 |
| 装备 | /api/vehicle/equipmentrecords(五件套) | Equipment |
| 笔记 | /api/vehicle/notes(五件套) | 自由笔记 |
| 日历 | /api/calendar | 全部提醒的 iCalendar 流 |
| 系统与运维 | /api/whoami、/api/version、/api/info、/api/makebackup、/api/cleanup、/api/tempfiles | 身份/版本/备份/清理 |
| 其他 | /api/documents/upload、/api/extrafields | 附件上传、扩展字段定义 |
("五件套"= 单车查询 GET ...?vehicleId= + 全量 GET .../all + 新增 POST .../add + 更新 PUT .../update + 删除 DELETE .../delete,各域参数同构。)
四、认证与首次调用
4.1 未认证探测(401 实录)
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8131/api/vehicles
实测回显:
401
4.2 Basic 认证首次调用
curl -s -u admin:q1w2e3r4 http://127.0.0.1:8131/api/version
curl -s -u admin:q1w2e3r4 http://127.0.0.1:8131/api/whoami
实测回显:
{"currentVersion":"1.7.4","latestVersion":"1.7.4"}
{"username":"admin","emailAddress":"","isAdmin":"True","isRoot":"True"}
/api/whoami 是最省事的认证自检端点:返回当前凭据对应的身份与角色。行内 URL 授权形态(等价写法,日历订阅场景常用):
curl -s http://admin:q1w2e3r4@127.0.0.1:8131/api/version
4.3 API Key 生成与使用(实测)
API Key 是每个用户的长期密钥,适合脚本/集成场景,免去在命令行与 URL 中落密码。生成入口在 Web 界面:登录后右上角用户菜单 → Account Information → API Keys → Create,填写名称与角色(viewer/editor/manager,对应只读/可编辑/可删除权限)。
本机以登录会话调用其内部创建端点实测(keyName=demo-key,权限 Edit+Delete):
POST /Home/CreateAPIKeyForUser → HTTP 200
{"success":true,"message":"API Key Created",
"additionalData":{"apiKey":"f1590531850d455c96465fe9cf72c74e"}}
(明文 Key 只在创建回显中出现一次,服务端只存 SHA256 哈希,务必当场保存。)
三种使用形态实测:
# 形态 1:x-api-key 请求头
curl -s -H 'x-api-key: f1590531850d455c96465fe9cf72c74e' \
-H 'culture-invariant: true' http://127.0.0.1:8131/api/vehicles
# 形态 2:apiKey 查询参数
curl -s 'http://127.0.0.1:8131/api/whoami?apiKey=f1590531850d455c96465fe9cf72c74e'
实测回显(形态 1 节选 / 形态 2 全文):
[{"id":1,"imageLocation":"/defaults/noimage.png","mapLocation":null,"year":2019,
"make":"Nissan","model":"Altima", ...}]
{"username":"demo-key","emailAddress":"","isAdmin":true,"isRoot":true}
边界实测:
# 无效 Key → 401
curl -s -o /dev/null -w '%{http_code}\n' -H 'x-api-key: invalid000' \
http://127.0.0.1:8131/api/vehicles
# 401
# Key 访问非 /api 路径 → 不接受 Key(302 跳登录)
curl -s -o /dev/null -w '%{http_code}\n' \
-H 'x-api-key: f1590531850d455c96465fe9cf72c74e' http://127.0.0.1:8131/Home/Index
# 302
五、各 API 域详解
5.1 车辆域(/api/vehicles)
GET /api/vehicles — 当前用户车库内全部车辆(无需参数):
curl -s -u admin:q1w2e3r4 -H 'culture-invariant: true' http://127.0.0.1:8131/api/vehicles
实测回显(车库为空时是 [];录入一辆后):
[{"id":1,"imageLocation":"/defaults/noimage.png","mapLocation":null,"year":2019,
"make":"Nissan","model":"Altima","licensePlate":"沪A12345","purchaseDate":null,
"soldDate":null,"purchasePrice":0,"soldPrice":0,"isElectric":false,"isDiesel":false,
"useHours":false,"odometerOptional":false,"extraFields":[],"tags":["sedan","test"],
"hasOdometerAdjustment":false,"odometerMultiplier":1,"odometerDifference":0,
"dashboardMetrics":[],"vehicleIdentifier":"LicensePlate"}]
POST /api/vehicles/add — 新增车辆(请求体 JSON,车辆文档页 Body Sample 实测照跑):
curl -s -u admin:q1w2e3r4 -H 'Content-Type: application/json' \
-X POST http://127.0.0.1:8131/api/vehicles/add \
--data '{"year":2019,"make":"Nissan","model":"Altima","identifier":"LicensePlate",
"licensePlate":"沪A12345","fuelType":"Gasoline","tags":"sedan test"}'
实测回显:
{"success":true,"message":"Vehicle Added","additionalData":{"vehicleId":1}}
关键参数:identifier 取 LicensePlate 或 VIN(决定列表以何字段标识车辆);fuelType 常见 Gasoline/Diesel;extraFields 数组可挂自定义字段(如 VIN 号)。成功响应的 additionalData.vehicleId 是后续所有记录端点的关联键。
PUT /api/vehicles/update — 更新车辆(请求体需含完整对象与 id);DELETE /api/vehicles/delete — 删除车辆(?id= 指定)。两者方法约束与记录域一致(POST 更新无效,见 7.3)。
5.2 保养记录域(/api/vehicle/servicerecords)
POST /api/vehicle/servicerecords/add — vehicleId 为必填查询参数,其余在请求体:
curl -s -u admin:q1w2e3r4 -H 'Content-Type: application/json' \
-X POST 'http://127.0.0.1:8131/api/vehicle/servicerecords/add' \
--data '{"vehicleId":1,"date":"2026-10-20","odometer":15200,
"description":"更换机油机滤","cost":386.5,"notes":"4S店保养","tags":"保养 机油"}'
实测回显:
{"success":true,"message":"Service Record Added","additionalData":{"recordId":1}}
GET /api/vehicle/servicerecords/all — 全车库保养记录(可选过滤参数 id/startDate/endDate/tags):
curl -s -u admin:q1w2e3r4 -H 'culture-invariant: true' \
http://127.0.0.1:8131/api/vehicle/servicerecords/all
实测回显:
[{"vehicleId":1,"id":1,"date":"2026-10-20","odometer":15200,
"description":"更换机油机滤","notes":"4S店保养","cost":386.5,
"tags":"保养 机油","extraFields":[],"files":[]}]
GET /api/vehicle/servicerecords?vehicleId=1 — 单车记录(同构端点在各记录域同形,如 /api/vehicle/gasrecords?vehicleId=1,实测见 5.3)。
PUT /api/vehicle/servicerecords/update — 更新(请求体为完整记录对象,id 必填):
curl -s -u admin:q1w2e3r4 -H 'Content-Type: application/json' \
-X PUT 'http://127.0.0.1:8131/api/vehicle/servicerecords/update' \
--data '{"id":1,"vehicleId":1,"date":"2026-10-21","odometer":15300,
"description":"更换机油机滤(含空调滤芯)","cost":456.0,
"notes":"4S店保养","tags":"保养","extraFields":[],"files":[]}'
实测回显:
{"success":true,"message":"Service Record Updated"}
随后复查单车记录,date/odometer/description/cost/tags 均已变为更新值(实测回显见配套排障 7.3)。
DELETE /api/vehicle/servicerecords/delete?id=1 — 按 id 删除:
curl -s -u admin:q1w2e3r4 -X DELETE \
'http://127.0.0.1:8131/api/vehicle/servicerecords/delete?id=1'
实测回显:
{"success":true,"message":"Service Record Deleted"}
再次 GET ?vehicleId=1 实测返回 [](已删空)。
5.3 加油记录域(/api/vehicle/gasrecords)
POST /api/vehicle/gasrecords/add — 必填字段比保养记录多:isFillToFull 与 missedFuelUp 不可缺。缺字段的真实报错实测(排障实录):
$ curl -s -u admin:q1w2e3r4 -H 'Content-Type: application/json' \
-X POST 'http://127.0.0.1:8131/api/vehicle/gasrecords/add' \
--data '{"vehicleId":1,"date":"2026-10-25","odometer":15500,
"fuelConsumed":42.5,"cost":312.25,"isFillToFull":true,"notes":"中石化 95号"}'
{"success":false,
"message":"Input object invalid, Date, Odometer, FuelConsumed, IsFillToFull, MissedFuelUp, and Cost cannot be empty."}
补上 missedFuelUp:false 后实测成功:
{"success":true,"message":"Gas Record Added","additionalData":{"recordId":1}}
表单编码同样被接受(x-www-form-urlencoded,字段全为字符串形态):
curl -s -u admin:q1w2e3r4 -X POST \
'http://127.0.0.1:8131/api/vehicle/gasrecords/add' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'vehicleId=1&date=2026-10-28&odometer=15800&fuelConsumed=38.2&cost=280.6&isFillToFull=true&missedFuelUp=false'
实测回显:
{"success":true,"message":"Gas Record Added","additionalData":{"recordId":2}}
GET /api/vehicle/gasrecords?vehicleId=1 — 单车加油记录,同时是格式开关的对照实验(不带 invariant 全字符串 + 区域日期;带 invariant 类型保真 + ISO 日期,两份真实回显全文见第六章)。
其余字段:fuelEconomy(由系统按配置口径 MPG / UK MPG / L/100KM / KM/L 计算)、startingSoc/endingSoc(电动车充电起止电量)。维修/改装/税费/物料/计划/里程/装备/笔记各域的请求体字段在 /api 文档页对应端点的 Body Sample 中逐一给出,方法与参数形态与本章同构。
5.4 日历、备份与系统域
GET /api/calendar — 全车库提醒的 iCalendar 流(日历应用直接订阅,支持行内 URL 授权):
curl -s -u admin:q1w2e3r4 http://127.0.0.1:8131/api/calendar
实测回显(尚无提醒记录时):
BEGIN:VCALENDAR
VERSION:2.0
PRODID:lubelogger.com
CALSCALE:GREGORIAN
METHOD:PUBLISH
END:VCALENDAR
GET /api/makebackup — 触发全量备份:
curl -s -u admin:q1w2e3r4 http://127.0.0.1:8131/api/makebackup
实测回显:
"/temp/db_backup_2026-10-30-14-36-22.zip"
备份 zip 落在数据目录 temp/ 下(实测包内含 config/userConfig.json 与 data/cartracker.db),配合定时脚本即可自动化备份(官方 FAQ 推荐做法)。
系统域其余端点:/api/info(实例信息)、/api/cleanup(清理临时文件)、/api/tempfiles(临时文件列表)、/api/documents/upload(附件上传)、/api/extrafields(扩展字段定义管理)、/api/vehicle/reminders/send(手动触发提醒推送,提醒邮件地址取 Root 用户 DefaultReminderEmail 配置)。
六、分页/过滤/排序通用约定
- 过滤:列表端点两级形态——
GET .../all(全车库,可带id/startDate/endDate/tags过滤参数)与GET ...?vehicleId=<id>(单车);tags过滤为关键字匹配; - 分页:没有分页参数,列表端点一次返回全量;记录量大时按
vehicleId拆分请求,或用日期区间参数收缩结果; - 排序:无排序参数,响应按记录时间组织,界面侧排序由用户列偏好(
UserColumnPreferences)控制,与 API 无关; - 格式:响应默认区域敏感(日期
10/25/2026、数字字符串化)。两种 invariant 开关实测对照(同一实例同一条记录):
# 默认格式(无 invariant)
[{"vehicleId":"1","id":"1","date":"10/25/2026","odometer":"15500",
"fuelConsumed":"42.5","cost":"312.25","fuelEconomy":"0",
"isFillToFull":"True","missedFuelUp":"False","startingSoc":"0",
"endingSoc":"0","notes":"中石化 95号","tags":"","extraFields":[],"files":[]}]
# 携带 culture-invariant 请求头(或实例配 LUBELOGGER_INVARIANT_API=true)
[{"vehicleId":1,"id":1,"date":"2026-10-25","odometer":15500,
"fuelConsumed":42.5,"cost":312.25,"fuelEconomy":0,
"isFillToFull":true,"missedFuelUp":false,"startingSoc":0,
"endingSoc":0,"notes":"中石化 95号","tags":"","extraFields":[],"files":[]}]
程序化消费建议固定使用 invariant 形态,避免实例区域调整后解析脚本集体破裂。格式开关的配置细节见《LubeLogger 1.7.4 配置参数详解》。
七、常见问题(FAQ)
Q1:全部接口都 401?
三种核对:① 实例是否启用了认证(启用后 /api 与页面一样受保护);② Basic 凭据是否正确(用户名或密码含冒号 : 会直接破坏 Basic 编码——官方明示的限制);③ API Key 是否用在了允许路径(仅 /api、/kiosk、/images、/documents、/temp 前缀,实测用于普通页面被拒)。
Q2:/swagger 打不开(404)?
LubeLogger 的接口文档页固定在 /api,没有 /swagger 路径(实测 404)。/api 页面提供全部 74 个端点的方法、参数与 JSON 样例。
Q3:更新接口返回空响应、数据也没变?
更新必须用 PUT、删除必须用 DELETE。实测把更新请求用 POST 发出:连接正常建立但响应体为空、数据未变(无错误码提示,极易误判为"接口坏了");改用 PUT 后同一请求体立即返回 {"success":true,"message":"Service Record Updated"}。
Q4:新增记录报 Input object invalid?
错误消息会逐一点名缺失字段(加油记录实测:Date/Odometer/FuelConsumed/IsFillToFull/MissedFuelUp/Cost 均不可空)。按消息补齐字段即可;建议一律传 JSON 并显式给全布尔字段(isFillToFull/missedFuelUp),避免表单编码的类型陷阱。
Q5:响应里的数字全是字符串、日期格式很怪?
默认区域敏感输出所致。带 culture-invariant 请求头(单请求)或配置 LUBELOGGER_INVARIANT_API=true(实例级)即可得到类型保真 + ISO 日期,实测对照见第六章。
Q6:如何备份全部数据?
GET /api/makebackup(实测返回 zip 路径),zip 在数据目录 temp/ 下,含 LiteDB 数据库文件与用户配置;官方建议用 cron 定时调用实现自动备份,恢复走 Settings → Restore Backup(仅 Root)。
八、参考链接
- 官方 API 文档:https://docs.lubelogger.com/Advanced/API (认证方式、编码约定与用例,查询日期 2026-10-30)
- 实例自带接口文档页:
http://<你的实例地址>/api(74 个端点交互式文档,本篇全部实测基于 v1.7.4 该页) - 官方 Postman Collection:见 API 文档页「Testing」节
- 相关文档:《LubeLogger 介绍与选型指南》《LubeLogger 1.7.4 Docker Compose 部署指南》《LubeLogger 1.7.4 配置参数详解》