Kavita 0.9.1.4 REST API 使用详解
Kavita 0.9.1.4 REST API 实测手册:JWT/apiKey 双认证体系、无 Swagger 环境的端点探索方法、账户/书库/系列/阅读进度/OPDS/图片六大域核心端点 curl 实测回显与错误码速查(2026-10-31 实测)。
Kavita 0.9.1.4 REST API 使用详解
目标:以实测方式讲清 Kavita 0.9.1.4 的 REST API——认证体系、无 Swagger 环境下的端点探索方法,以及账户/书库/系列/阅读进度/OPDS/图片六大域的核心端点,全部请求附真实回显(2026-10-31)。Kavita 无独立 CLI,官方 Web UI 即构建在这套 API 之上;部署与配置见同专栏部署篇、配置篇。
一、环境信息
- 软件版本:Kavita v0.9.1.4(服务已就绪,
GET /api/health→Ok) - 服务地址:
http://127.0.0.1:8145 - 测试账号:
admin / q1w2e3r4(管理员) - 测试书库:Comics(2 个 CBZ 系列)、Books(1 个 PDF 系列),实测 3 个系列、5 个章节文件
- 客户端工具:curl(本文全部示例)+ 任意 JWT 解码工具(可选)
- 说明:所有响应中 JWT token、refreshToken、apiKey 均以
…(删节)截断展示
二、前置条件
2.1 端点与认证体系
| 凭据 | 形式 | 适用范围 |
|---|---|---|
JWT token | 登录/注册返回,请求头 Authorization: Bearer <token> | /api/* 全部业务端点 |
refreshToken | 随登录返回 | 换发新 token |
apiKey(opds) | 注册/用户设置返回 | /api/opds/<apiKey> 订阅源 |
apiKey(image-only) | 注册/用户设置返回 | /api/Image/* 图片直链 |
2.2 无 Swagger:端点探索方法(实测)
生产构建下 Swagger UI 已禁用,实测四个常见路径全部 404:
/swagger/index.html -> 404
/swagger/v1/swagger.json -> 404
/api/swagger.json -> 404
/api/swagger/v1/swagger.json -> 404
实测可行的探索路径有三条:
- 官方前端静态资源:前端脚本内含全部 API 路径与枚举字面量(本文枚举取值即从中提取)。
- ProblemDetails 校验回显:ASP.NET 对错误请求回显 DTO 类型与缺失字段名(见 5.2),可反推请求结构。
- 错误码区分路由:未注册路由 404,需认证的路由缺凭据 401,路由对但参数错 400——三者可精确定位端点是否存在。
三、API 总览
- 协议:HTTP REST,JSON 请求/响应(OPDS 域为 Atom XML);错误统一返回 RFC 9110 ProblemDetails(含
type/title/status/errors/traceId)。 - 认证:JWT Bearer(业务端点)+ apiKey(OPDS/图片直链),见 2.1。
- 版本形态:URL 无全局版本号;部分端点以
-v2后缀区分代际(如Series/all-v2)。 - 限流:官方未见公开限流约定;本文连续高频请求未触发限流。
- 分页:列表端点用
page+pageSize查询参数(从 1 起)。
核心端点速查(本文均实测):
| 域 | 方法与路径 | 用途 |
|---|---|---|
| 账户 | POST /api/Account/register | 注册(首个用户即管理员) |
| 账户 | POST /api/Account/login | 登录取 JWT |
| 书库 | GET /api/Library/libraries | 书库列表 |
| 书库 | POST /api/Library/create | 建库 |
| 书库 | POST /api/Library/update | 改库 |
| 书库 | DELETE /api/Library/delete?libraryId= | 删库 |
| 书库 | POST /api/Library/scan?libraryId=&force= | 触发扫描 |
| 系列 | POST /api/Series/all-v2?page=&pageSize= | 全库系列分页 |
| 系列 | GET /api/Series/{id} | 系列详情 |
| 系列 | GET /api/Series/volumes?seriesId= | 卷/章/文件树 |
| 阅读 | POST /api/Reader/progress | 保存阅读进度 |
| 阅读 | GET /api/Reader/continue-point?seriesId= | 续读点位 |
| 阅读 | POST /api/Reader/mark-read | 整系列标记已读 |
| OPDS | GET /api/opds/<apiKey>[…] | Atom 订阅源 |
| 图片 | GET /api/Image/series-cover?seriesId=&apiKey= | 封面直链 |
四、认证与首次调用
4.1 注册首个管理员
curl -s -X POST http://127.0.0.1:8145/api/Account/register \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4","email":"admin@quzuo.local"}'
实测回显(节选):
{"id":1,"username":"admin","roles":["Admin","Login"],
"token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW4i…(删节)",
"refreshToken":"CfDJ8OIUN+ecKIxLpieEI76ZROR…(删节)",
"apiKey":"tTyuDrTF…(删节)",
"authKeys":[{"name":"opds","key":"tTyuDrTF…(删节)"},
{"name":"image-only","key":"sMs3cdhv…(删节)"}],
"kavitaVersion":"0.9.1.4"}
JWT 载荷实测(base64 解码 payload 段):{"name":"admin","nameid":"1","role":["Admin","Login"],"nbf":1793419742,"exp":1793678942,"iat":1793419742}——有效期约 3 天,过期用 refreshToken 换发。
4.2 登录与携带凭据
TOKEN=$(curl -s -X POST http://127.0.0.1:8145/api/Account/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4"}' \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["token"])')
curl -s http://127.0.0.1:8145/api/Library/libraries -H "Authorization: Bearer $TOKEN"
# [] ← 新实例书库为空,HTTP 200
4.3 未携带凭据的行为(实测)
curl -s http://127.0.0.1:8145/api/Library/libraries -w '\ncode=%{http_code}\n'
# (空响应体)
# code=401
五、各 API 域详解
5.1 书库域(Library)
建库 POST /api/Library/create——DTO 必填完整,实测两次渐进补全:
curl -s -X POST http://127.0.0.1:8145/api/Library/create \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{}'
回显一(缺 name/folders):
{"status":400,"errors":{"$":["JSON deserialization for type 'Kavita.Models.DTOs.UpdateLibraryDto' was missing required properties including: 'name', 'folders'."],"dto":["The dto field is required."]}}
补上 name/type/folders 再试,回显二(暴露更多必填字段):
{"status":400,"errors":{"FileGroupTypes":["The FileGroupTypes field is required.","The field FileGroupTypes is invalid."],
"ExcludePatterns":["The ExcludePatterns field is required."],
"MetadataProvider":["The field MetadataProvider is invalid."]}}
枚举取值实测(结合前端资源字面量与试探回显):
| 字段 | 有效值 |
|---|---|
type(LibraryType) | 0=Manga,1=Comic,2=Book,3=Images,4=LightNovel |
fileGroupTypes(FileGroupType) | 1=Archive,2=Epub,3=Pdf,4=Images(0/7/15 均 400) |
metadataProvider | 有效 2/3/4;0、1 报 invalid |
完整请求(实测成功):
curl -s -X POST http://127.0.0.1:8145/api/Library/create \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Comics","type":1,"folders":["/media/Comics"],"fileGroupTypes":[1],"excludePatterns":[],"metadataProvider":2}'
# 返回 LibraryDto(含 id/name/type/folders/lastScanned 等),HTTP 200
改库 POST /api/Library/update(实测回显,节选):
curl -s -X POST http://127.0.0.1:8145/api/Library/update \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"id":1,"name":"Comics","type":1,"folders":["/media/Comics"],"fileGroupTypes":[1],"excludePatterns":[],"metadataProvider":2}'
{"lastScanned":"2026-10-31T04:24:10.7715862","coverImage":null,"folderWatching":false,
"includeInDashboard":false,"includeInRecommended":true,"manageCollections":false,
"manageReadingLists":false,"includeInSearch":false,"allowScrobbling":false,
"folders":["/media/Comics"],"collapseSeriesRelationships":false,…(节选)}
删库 DELETE /api/Library/delete?libraryId=N(实测):
curl -s -X DELETE "http://127.0.0.1:8145/api/Library/delete?libraryId=3" -H "Authorization: Bearer $TOKEN"
# true (HTTP 200;书库及其系列/进度级联删除)
⚠️ 注意:
DELETE /api/Library/3(REST 风格路径)实测 404——删除必须走delete动作路径 +libraryId查询参数。
触发扫描 POST /api/Library/scan(实测):
curl -s -X POST "http://127.0.0.1:8145/api/Library/scan?libraryId=2&force=true" \
-H "Authorization: Bearer $TOKEN" -w ' code=%{http_code}\n'
# code=200 (异步执行;日志出现 [ScannerService] Beginning file scan on Books)
⚠️ 注意:
force为布尔查询参数,实测force=1报 400:{"errors":{"force":["The value '1' is not valid."]}}。
5.2 系列域(Series)
全库系列分页 POST /api/Series/all-v2(注意是 POST,body 传过滤条件,空对象=不过滤):
curl -s -X POST "http://127.0.0.1:8145/api/Series/all-v2?page=1&pageSize=20" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{}'
实测回显(节选,3 个系列):
[{"id":5,"name":"Grace-field","originalName":"Grace-field","sortName":"Grace-field",
"pages":1,"coverImageLocked":false,"lastChapterAdded":"2026-10-31T04:27:59.2961459",
"lastChapterAddedUtc":"2026-10-31T04:27:59.296146","userRating":0,"hasUserRated":false,
"totalReads":0,"pagesRead":…(节选)},
{"id":2,"name":"Night Detective","pages":3,"format":1,…},
{"id":1,"name":"Planet Wanderer","pages":4,"format":1,…}]
系列详情 GET /api/Series/{id}(实测回显节选与 all-v2 单元素结构一致,HTTP 200)。
卷章树 GET /api/Series/volumes?seriesId=5(实测回显,节选):
[{"id":5,"minNumber":100000,"maxNumber":100000,"name":"100000","number":100000,"pages":1,
"pagesRead":0,"seriesId":5,
"chapters":[{"id":5,"range":"Field Notes","number":"-100000","pages":1,"isSpecial":true,
"title":"Field Notes",
"files":[{"id":5,"filePath":"/media/Books/Grace-field/Field Notes.pdf","pages":1,"bytes":604,…}]}]}]
层级即 库 → 系列 → 卷(volume)→ 章(chapter)→ 文件(files),后续进度/阅读 API 全部以 chapterId/volumeId 定位。
5.3 阅读进度域(Reader)
保存进度 POST /api/Reader/progress——先看 DTO 校验(实测传错字段名):
curl -s -X POST http://127.0.0.1:8145/api/Reader/progress \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"chapterId":5,"page":0,"bookScrollPos":"","seriesId":5,"libraryId":2}'
{"status":400,"errors":{"$":["JSON deserialization for type 'Kavita.Models.DTOs.Progress.ProgressDto' was missing required properties including: 'volumeId', 'pageNum'."]}}
改用正确字段(pageNum 而非 page,必含 volumeId):
curl -s -X POST http://127.0.0.1:8145/api/Reader/progress \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"volumeId":5,"chapterId":5,"pageNum":0,"bookScrollPos":"","seriesId":5,"libraryId":2}' \
-w 'code=%{http_code}\n'
# code=200
续读点位 GET /api/Reader/continue-point?seriesId=5(实测回显节选:直接返回应继续读的章 DTO):
{"id":5,"range":"Field Notes","number":"-100000","pages":1,"isSpecial":true,"title":"Field Notes",
"files":[{"id":5,"filePath":"/media/Books/Grace-field/Field Notes.pdf","pages":1,"bytes":604,…}]}
整系列已读 POST /api/Reader/mark-read(实测):
curl -s -X POST http://127.0.0.1:8145/api/Reader/mark-read \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"seriesId":2}' -w 'code=%{http_code}\n'
# code=200
5.4 OPDS 域(apiKey 认证,无需 JWT)
根目录 GET /api/opds/<apiKey>(实测回显,节选):
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2005/Atom">
<updated>2026-10-31T04:30:50</updated>
<id>root</id>
<title>Kavita</title>
<icon>/api/opds/<apiKey>/favicon</icon>
<author><name>Kavita</name><uri>https://www.kavitareader.com</uri></author>
<link rel="self" type="application/atom+xml;profile=opds-catalog;kind=navigation" href="/api/opds/" />
书库源 GET /api/opds/<apiKey>/libraries(实测回显节选):
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<updated>2026-10-31T04:46:55</updated>
<id>libraries</id>
<title>All Libraries</title>
5.5 图片域(image-only apiKey)
curl -s -o /dev/null -w 'code=%{http_code} type=%{content_type} size=%{size_download}\n' \
"http://127.0.0.1:8145/api/Image/series-cover?seriesId=2&apiKey=<image-only apiKey>"
# code=200 type=image/png size=3258
图片直链不要求 JWT,专为阅读客户端取封面/页图设计,凭据粒度比业务 JWT 低。
六、分页/过滤/排序通用约定
- 分页:
page(从 1 起)+pageSize(如 20/50),实测all-v2首页 3 条、pageSize=50 全量一致。 - 过滤:
all-v2类端点把过滤条件放 POST body(空对象{}= 全量),翻页参数放查询串。 - 排序:body 传
sortOptions(不传时按默认排序,实测返回按系列 id 倒序)。 - 字段命名:请求体一律 camelCase(
fileGroupTypes、pageNum),错误回显中的 PascalCase(FileGroupTypes)只是服务端字段标识。
七、常见问题
Q1:Swagger 打不开? 0.9.1.4 生产构建已移除 Swagger,四个常见路径实测均 404,属正常现象。端点探索见 2.2。
Q2:请求 400 missing required properties?
看 ProblemDetails 的 errors 字段:它直接列出 DTO 类型与缺失字段(如 ProgressDto 要求 volumeId、pageNum)。这是无 Swagger 环境下最可靠的请求结构来源。
Q3:force=1 这类短布尔为什么报错?
.NET 布尔查询参数只接受 true/false,实测 The value '1' is not valid.(400)。
Q4:扫描/删除后立刻查询没变化?
扫描是异步任务:scan 返回 200 只代表入队(日志 Enqueuing library scan for: N),数秒后生效;删除为同步级联,立即生效。
Q5:JWT 过期怎么办?
登录响应含 refreshToken,用其换发新 token;本文实测 JWT 有效期约 3 天(exp-iat)。
八、参考链接
- Kavita GitHub 仓库(API 控制器源码目录):https://github.com/Kareadita/Kavita (2026-10-31 查询)
- Kavita 官方 Wiki(第三方客户端与 OPDS):https://wiki.kavitareader.com/ (2026-10-31 查询)
- 站内部署篇(服务拉起与端口):《Kavita 0.9.1.4 Docker Compose 部署指南》
- 站内配置篇(两层参数体系):《Kavita 0.9.1.4 配置参数详解》
- 站内选型篇:《Kavita 0.9.1.4 介绍与选型指南》