Kavita 0.9.1.4 REST API 使用详解

Kavita 0.9.1.4 REST API 实测手册:JWT/apiKey 双认证体系、无 Swagger 环境的端点探索方法、账户/书库/系列/阅读进度/OPDS/图片六大域核心端点 curl 实测回显与错误码速查(2026-10-31 实测)。

KavitaKavita漫画电子书媒体服务器自托管.NET2026/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

实测可行的探索路径有三条:

  1. 官方前端静态资源:前端脚本内含全部 API 路径与枚举字面量(本文枚举取值即从中提取)。
  2. ProblemDetails 校验回显:ASP.NET 对错误请求回显 DTO 类型与缺失字段名(见 5.2),可反推请求结构。
  3. 错误码区分路由:未注册路由 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整系列标记已读
OPDSGET /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)。

八、参考链接

  1. Kavita GitHub 仓库(API 控制器源码目录):https://github.com/Kareadita/Kavita (2026-10-31 查询)
  2. Kavita 官方 Wiki(第三方客户端与 OPDS):https://wiki.kavitareader.com/ (2026-10-31 查询)
  3. 站内部署篇(服务拉起与端口):《Kavita 0.9.1.4 Docker Compose 部署指南》
  4. 站内配置篇(两层参数体系):《Kavita 0.9.1.4 配置参数详解》
  5. 站内选型篇:《Kavita 0.9.1.4 介绍与选型指南》