LubeLogger 1.7.4 REST API 使用详解

LubeLogger 1.7.4 REST API 实战:接口文档页 /api 与 74 个端点分域速查、Basic 认证与 API Key 双认证、车辆/保养/加油记录增删改查全实测、PUT 方法约束与区域格式开关排障。

LubeLoggerLubeLoggerAPIREST API2026/10/30

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、.../deleteService 记录
维修记录/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、.../deleteTaxes 记录
物料/api/vehicle/supplyrecords(五件套)Supplies 台账
提醒/api/vehicle/reminders(五件套)+ .../sendReminders,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)。

八、参考链接