最后更新时间:2026-05-11 已从PoxenStudio/Talebook更名为MyBooks
- 基础 URL:/api(除 OPDS/Podcast/静态资源等非 /api 路由)
- 认证方式:登录后 Cookie(user_id 等)
- 管理员接口:需登录且管理员权限
- 响应约定:大多数 JSON 接口都有 err 字段,err = "ok" 表示成功
成功响应:
{
"err": "ok",
"msg": "success",
"data": {}
}错误响应:
{
"err": "error.code",
"msg": "错误描述信息"
}系统设备分为两类:
- 用户设备:reader_id > 0,绑定具体用户(如用户 Kindle 推送目标)
- 全局设备:reader_id = 0 或空,系统级共享设备
客户端在展示设备列表时,应根据 reader_id 区分设备归属。
完整的图书对象包含以下字段:
{
"id": 123,
"title": "三体",
"rating": 5,
"timestamp": "2026-05-11",
"pubdate": "2024-01-01",
"author": "刘慈欣",
"authors": ["刘慈欣"],
"author_sort": "Liu Cixin",
"tag": "科幻 / 长篇",
"tags": ["科幻", "长篇"],
"publisher": "重庆出版社",
"comments": "暂无简介",
"series": "三体系列",
"series_index": 1,
"languages": ["zho"],
"isbn": "9787536692930",
"img": "https://your.cdn/get/cover/123.jpg",
"thumb": "https://your.cdn/get/thumb_240_320/123.jpg",
"collector": "admin",
"count_visit": 100,
"count_download": 50,
"sole": false,
"has_audio": 0,
"book_type": 0,
"book_count": 1,
"state": {
"favorite": 1,
"favorite_date": "2026-05-10T12:00:00",
"wants": 0,
"wants_date": null,
"read_state": 2,
"read_date": "2026-05-11T10:00:00",
"online_read": 1,
"download": 1
},
"category": "科幻",
"ext_link": "",
"files": [
{"format": "epub", "size": 123456}
],
"dynamic_cover": 0
}- 路径:
/api/welcome - 方法:GET
- 认证:无需认证
- 参数:无
- 响应示例:
{
"err": "ok",
"version": "v3.20.0"
}- 路径:
/api/user/sign_up - 方法:POST
- 认证:无需认证(需要开启注册功能)
- 参数:
username(string, 必填): 用户名,3-20位字符,仅字母数字下划线nickname(string, 必填): 昵称email(string, 必填): 邮箱地址password(string, 必填): 密码,6-20位
- 响应示例:
{
"err": "ok",
"msg": "注册成功,请查收激活邮件"
}- 路径:
/api/user/sign_in - 方法:POST
- 认证:无需认证
- 参数:
username(string, 必填): 用户名password(string, 必填): 密码
- 响应示例:
{
"err": "ok",
"msg": "ok"
}- 路径:
/api/user/sign_out - 方法:GET
- 认证:需要登录
- 参数:无
- 响应示例:
{
"err": "ok",
"msg": "你已成功退出登录。"
}- 路径:
/api/user/info - 方法:GET
- 认证:无需登录
- 参数:无
- 响应示例:
{
"err": "ok",
"sys": {
"title": "MyBooks",
"books": 10000,
"version": "v3.41.0",
"upgrable": ""
},
"user": {
"id": 1,
"username": "admin",
"name": "管理员",
"email": "admin@example.com",
"avatar": "reader.svg",
"is_admin": true
}
}未登录时返回基础系统信息,用户信息中is_login为false,登录时会返回完整用户信息。 sys中为基础系统信息,title为网站标题, books为在库书籍数量,version为当前系统版本。其中upgrable代表是否有升级版本,如果为有值且与version不同代表有可升级版本。
- 路径:
/api/user/update - 方法:POST
- 认证:需要登录
- 参数(JSON):
nickname(string, 可选): 新昵称password0(string, 可选): 当前密码(修改密码时必填)password1(string, 可选): 新密码password2(string, 可选): 确认新密码kindle_email(string, 可选): Kindle推送邮箱podcast_token(string, 可选): Podcast订阅Tokenallow_sending_mail(boolean, 可选): 是否允许发送邮件
- 响应示例:
{
"err": "ok"
}- 路径:
/api/user/reset - 方法:POST
- 认证:无需认证
- 参数:
username(string, 必填): 用户名email(string, 必填): 注册邮箱
- 响应示例:
{
"err": "ok",
"msg": "密码重置邮件已发送"
}- 路径:
/api/user/avatar - 方法:POST
- 认证:需要登录
- 参数:
avatar(file, 必填): 头像图片文件
- 响应示例:
{
"err": "ok",
"avatar": "/get/avatar/user_123.jpg"
}- 路径:
/api/user/active/send - 方法:GET/POST
- 认证:需要登录
- 参数:无
- 响应示例:
{
"err": "ok"
}- 路径:
/api/active/<username>/<code> - 方法:GET/POST
- 认证:无需认证
- 参数:
username(path, 必填): 用户名code(path, 必填): 激活码
- 响应:302重定向到激活成功页面
- 路径:
/api/user/new - 方法:POST
- 认证:需要管理员权限
- 参数:
username(string, 必填): 用户名nickname(string, 必填): 昵称email(string, 必填): 邮箱password(string, 必填): 密码
- 响应示例:
{
"err": "ok",
"msg": "用户添加成功"
}- 路径:
/api/done/ - 方法:GET
- 认证:无需认证(由OAuth流程调用)
- 参数:无
- 响应:302重定向到首页或指定页面
- 路径:
/api/user/messages - 方法:GET
- 认证:需要登录
- 参数:无
- 响应示例:
{
"err": "ok",
"messages": [
{
"id": 1,
"title": "系统通知",
"status": "unread",
"create_time": "2026-05-11 10:00:00",
"data": {}
}
]
}- 路径:
/api/user/messages - 方法:POST
- 认证:需要登录
- 参数(JSON):
id(int, 必填): 消息ID
- 响应示例:
{
"err": "ok"
}- 路径:
/api/user/messages/clear - 方法:POST
- 认证:需要登录
- 参数:无
- 响应示例:
{
"err": "ok"
}- 路径:
/api/user/pin - 方法:POST
- 认证:需要登录
- 参数(JSON):
item_type(int, 必填): 0=作者, 1=标签item(string, 必填): 作者名或标签名
- 响应示例:
{
"err": "ok"
}- 路径:
/api/user/unpin - 方法:POST
- 认证:需要登录
- 参数(JSON):
item_type(int, 必填): 0=作者, 1=标签item(string, 必填): 作者名或标签名
- 响应示例:
{
"err": "ok"
}- 路径:
/api/user/devices - 方法:GET/POST
- 认证:需要登录
- 说明:该接口是“全量替换”模型——没有单个设备的
id,GET 返回当前用户的全部设备列表,POST 时必须提交完整的设备列表(包含要保留的所有设备),服务端会先清空该用户的所有设备记录再写入。要删除某个设备,只需在 POST 时省略它;要清空所有设备,POST 一个空数组。
支持的设备类型(type 字段)共 8 种,按数据模型可分为三组:
| 分组 | type 取值 |
额外字段 |
|---|---|---|
| Kindle 邮箱推送 | kindle |
mailbox |
| WiFi 局域网传输(数据模型相同) | duokan(多看)、ireader(爱阅读)、hanwang(汉王)、boox(文石)、dangdang(当当)、purelibro |
ip、port、schema |
| FTP 传输 | ftp |
ip、port、ftp_username、ftp_password、ftp_path |
注:
type字段当前未做白名单校验(任意字符串都会被存储,省略时默认为duokan);类型校验仅在实际推送书籍的/api/book/<id>/send_to_device接口中执行。
- 参数:无
- 响应:
devices为数组,每个元素的字段取决于设备类型:- 所有类型通用:
name、type、ip、port、schema、mailbox - 仅
ftp类型额外返回:ftp_username、ftp_password、ftp_path(此时mailbox字段固定为空字符串)
- 所有类型通用:
Kindle 设备响应示例:
{
"err": "ok",
"devices": [
{
"name": "我的Kindle",
"type": "kindle",
"ip": "",
"port": 12121,
"schema": "http",
"mailbox": "user@kindle.com"
}
]
}WiFi 传输设备响应示例(duokan/ireader/hanwang/boox/dangdang/purelibro 共用此结构):
{
"err": "ok",
"devices": [
{
"name": "客厅的多看",
"type": "duokan",
"ip": "192.168.1.100",
"port": 8080,
"schema": "http",
"mailbox": ""
}
]
}FTP 设备响应示例:
{
"err": "ok",
"devices": [
{
"name": "NAS",
"type": "ftp",
"ip": "192.168.1.50",
"port": 21,
"schema": "http",
"mailbox": "",
"ftp_username": "admin",
"ftp_password": "123456",
"ftp_path": "/books"
}
]
}- 参数(JSON):
devices(array, 必填): 完整的设备列表,每个元素:type(string, 选填):kindle/duokan/ireader/hanwang/boox/dangdang/purelibro/ftp,默认duokanname(string, 选填): 设备名称,默认空字符串mailbox(string, 选填): 仅kindle类型使用,存放 Kindle 推送邮箱ip(string, 选填): 仅 WiFi 传输类、ftp类型使用,默认空字符串port(int, 选填): 仅 WiFi 传输类、ftp类型使用,默认12121schema(string, 选填): 仅 WiFi 传输类使用,http/https,默认httpftp_username(string, 选填): 仅ftp类型使用ftp_password(string, 选填): 仅ftp类型使用ftp_path(string, 选填): 仅ftp类型使用,序列化后的 FTP 配置总长度不可超过 2048 字符
请求示例(同时保留一个 Kindle、一个多看、一个 FTP 设备):
{
"devices": [
{ "type": "kindle", "name": "我的Kindle", "mailbox": "user@kindle.com" },
{ "type": "duokan", "name": "客厅的多看", "ip": "192.168.1.100", "port": 8080, "schema": "http" },
{ "type": "ftp", "name": "NAS", "ip": "192.168.1.50", "port": 21, "ftp_username": "admin", "ftp_password": "123456", "ftp_path": "/books" }
]
}- 响应示例(成功时不返回
devices,需重新 GET 获取最新列表):
{
"err": "ok",
"msg": "设备保存成功"
}- 错误响应:
- 请求体非合法 JSON 或
devices不是数组:{"err": "params.invalid", "msg": "参数无效"} - FTP 配置序列化后超过 2048 字符:
{"err": "params.invalid", "msg": "FTP配置信息过长"} - 数据库写入失败:
{"err": "db.error", "msg": "数据库操作异常,请重试"} - 未登录:
{"err": "user.need_login", "msg": "请先登录"}
- 请求体非合法 JSON 或
- 路径:
/api/user/expected - 方法:GET/POST
- 认证:需要登录
- 参数:
- GET: 无参数,获取期望列表
- POST: 添加/删除期望(JSON参数)
- 响应示例:
{
"err": "ok",
"items": [
{
"id": 1,
"title": "三体II",
"author": "刘慈欣"
}
]
}- 路径:
/api/user/history/clear - 方法:POST
- 认证:需要登录
- 参数:无
- 响应示例:
{
"err": "ok"
}- 路径:
/api/user/memo - 方法:GET/POST
- 认证:需要登录
- 参数:
- GET: 无参数,获取便签列表
- POST: 添加/更新/删除便签(JSON参数)
- 响应示例:
{
"err": "ok",
"memos": [
{
"id": 1,
"content": "便签内容",
"create_time": "2026-05-11 10:00:00"
}
]
}- 路径:
/api/friends/favicon/<filename> - 方法:GET
- 认证:无需认证
- 参数:
filename(path, 必填): 图标文件名
- 响应:返回图标文件(图片)
- 路径:
/api/index - 方法:GET
- 认证:无需认证
- 参数:
random(int, 可选): 随机书籍数量,默认12recent(int, 可选): 最新书籍数量,默认12
- 响应示例:
{
"err": "ok",
"random_books_count": 12,
"new_books_count": 12,
"random_books": [...],
"new_books": [...]
}- 路径:
/api/search - 方法:GET
- 认证:无需认证
- 参数:
query(string, 必填): 搜索关键词page(int, 可选): 页码,默认1num(int, 可选): 每页数量,默认20
- 响应示例:
{
"err": "ok",
"total": 100,
"books": [...]
}- 路径:
/api/recent - 方法:GET
- 认证:无需认证
- 参数:
page(int, 可选): 页码,默认1num(int, 可选): 每页数量,默认20
- 响应示例:
{
"err": "ok",
"total": 100,
"books": [...]
}- 路径:
/api/all - 方法:GET
- 认证:无需认证
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 1000,
"books": [...]
}- 路径:
/api/hot - 方法:GET
- 认证:无需认证
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 50,
"books": [...]
}- 路径:
/api/printbooks - 方法:GET
- 认证:无需认证
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 200,
"books": [...]
}- 路径:
/api/soledbooks - 方法:GET
- 认证:需要登录
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 20,
"books": [...]
}- 路径:
/api/book/nav - 方法:GET
- 认证:无需认证
- 参数:无
- 响应示例:
{
"err": "ok",
"nav": {
"categories": [...],
"tags": [...],
"authors": [...]
}
}- 路径:
/api/book/<id> - 方法:GET
- 认证:无需认证(但登录后可获取阅读状态)
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"kindle_sender": "sender@example.com",
"book": {...},
"audios": {...}
}- 路径:
/api/book/<id>/delete - 方法:POST
- 认证:需要管理员权限
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "删除成功"
}- 路径:
/api/book/<id>/delete_format - 方法:POST
- 认证:需要管理员权限
- 参数:
id(path, 必填): 图书IDformat(string, 必填): 格式名,如epub、pdf
- 响应示例:
{
"err": "ok",
"msg": "格式删除成功"
}- 路径:
/api/book/<id>/edit - 方法:POST
- 认证:需要管理员或书籍所有者权限
- 参数:
id(path, 必填): 图书ID- JSON数据:包含title、authors、tags、publisher等字段
- 响应示例:
{
"err": "ok",
"msg": "更新成功"
}- 路径:
/api/book/<id>.<ext> - 方法:GET
- 认证:需要登录
- 参数:
id(path, 必填): 图书IDext(path, 必填): 文件格式,如epub、pdf
- 响应:返回文件下载
- 路径:
/api/book/<id>/refer - 方法:GET
- 认证:无需认证
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"refer": {
"douban": "https://book.douban.com/...",
"amazon": "https://www.amazon.com/..."
}
}- 路径:
/api/book/<id>/send_to_device - 方法:POST
- 认证:需要登录(若管理员开启了"允许游客推送",则游客也可调用)
- 参数(JSON body):
id(path, 必填): 图书IDdevice_type(string, 必填): 设备类型,取值之一:duokan、ireader、hanwang、boox、dangdang、kindle、purelibro、ftpdevice_url(string): 设备地址(IP/URL)。除kindle外均必填;不允许填写指向本机的地址(127.开头)mailbox(string): 目标邮箱,仅device_type=kindle时必填ftp_path(string): FTP路径,仅device_type=ftp时必填ftp_username(string, 可选): FTP用户名,仅device_type=ftp时使用ftp_password(string, 可选): FTP密码,仅device_type=ftp时使用
- 响应示例:
{
"err": "ok",
"msg": "推送成功"
}- 路径:
/api/book/<id>/mailto - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书IDemail(string, 必填): 目标邮箱format(string, 可选): 格式
- 响应示例:
{
"err": "ok",
"msg": "发送成功"
}- 路径:
/read/<id> - 方法:GET
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应:返回在线阅读页面(HTML)
- 路径:
/api/read/txt - 方法:GET
- 认证:需要登录
- 参数:
book_id(int, 必填): 图书IDchapter(int, 可选): 章节号
- 响应示例:
{
"err": "ok",
"content": "章节内容...",
"chapter": 1,
"total_chapters": 10
}- 路径:
/api/book/txt/init - 方法:GET
- 认证:需要登录
- 参数:
book_id(int, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"chapters": [...],
"total": 10
}- 路径:
/api/book/<id>/convert - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书IDformat(string, 可选): 目标格式
- 响应示例:
{
"err": "ok",
"content": "转换成功,请稍后刷新页面查看"
}- 路径:
/api/book/<id>/topdf - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"content": "转换成功,请稍后刷新页面查看"
}- 路径:
/api/book/<id>/totxtz - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "转换成功"
}- 路径:
/api/book/<id>/setsole - 方法:POST
- 认证:需要管理员权限
- 参数:
id(path, 必填): 图书IDsole(boolean, 必填): 是否已售出
- 响应示例:
{
"err": "ok",
"msg": "设置成功"
}- 路径:
/api/book/<id>/cover - 方法:GET
- 认证:无需认证
- 参数:
id(path, 必填): 图书ID
- 响应:返回图片文件
- 路径:
/api/book/<id>/favorite - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书IDaction(string, 必填): "add" 或 "remove"
- 响应示例:
{
"err": "ok",
"msg": "收藏成功"
}- 路径:
/api/book/<id>/wants - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书IDaction(string, 必填): "add" 或 "remove"
- 响应示例:
{
"err": "ok",
"msg": "添加成功"
}- 路径:
/api/book/<id>/readstate - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书IDread_state(int, 必填): 阅读状态(0=未读,1=在读,2=已读)
- 响应示例:
{
"err": "ok",
"msg": "状态更新成功"
}- 路径:
/api/favorites - 方法:GET
- 认证:需要登录
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 50,
"books": [...]
}- 路径:
/api/wants - 方法:GET
- 认证:需要登录
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 30,
"books": [...]
}- 路径:
/api/reading - 方法:GET
- 认证:需要登录
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 10,
"books": [...]
}- 路径:
/api/read-done - 方法:GET
- 认证:需要登录
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 100,
"books": [...]
}- 路径:
/api/reading/stats - 方法:GET
- 认证:需要登录
- 参数:无
- 响应示例:
{
"err": "ok",
"stats": {
"favorites": 50,
"wants": 30,
"reading": 10,
"read_done": 100
}
}- 路径:
/api/book/<id>/tags - 方法:POST
- 认证:需要管理员或书籍所有者权限
- 参数:
id(path, 必填): 图书ID- JSON数据:包含tags数组
- 响应示例:
{
"err": "ok",
"msg": "标签更新成功"
}- 路径:
/api/book/<id>/aifill - 方法:POST
- 认证:需要管理员或书籍所有者权限
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "AI更新成功",
"category": "科幻",
"tags": ["硬科幻", "太空歌剧"]
}- 路径:
/api/book/update_tags - 方法:POST
- 认证:需要管理员权限
- 参数:
tag(string, 必填): 标签名
- 响应示例:
{
"err": "ok",
"msg": "已提交300本书籍的标签更新任务",
"count": 300
}- 路径:
/api/book/<id>/category - 方法:POST
- 认证:需要管理员或书籍所有者权限
- 参数:
id(path, 必填): 图书IDcategory(string, 必填): 分类名称
- 响应示例:
{
"err": "ok",
"msg": "分类更新成功"
}- 路径:
/api/book/category - 方法:POST
- 认证:需要管理员权限
- 参数:
category(string, 必填): 分类名称author(string, 可选): 作者名tag(string, 可选): 标签名
- 响应示例:
{
"err": "ok",
"msg": "成功更新100本书籍分类",
"count": 100
}- 路径:
/api/categories - 方法:GET
- 认证:无需认证
- 参数:无
- 响应示例:
{
"err": "ok",
"categories": [
{"name": "科幻", "count": 100},
{"name": "文学", "count": 200}
]
}- 路径:
/api/tags/search - 方法:GET
- 认证:无需认证
- 参数:
q(string, 必填): 搜索关键词limit(int, 可选): 返回数量,默认20
- 响应示例:
{
"err": "ok",
"tags": [
{"name": "科幻", "count": 100},
{"name": "硬科幻", "count": 50}
]
}- 路径:
/api/book/<id>/suggestion - 方法:GET
- 认证:无需认证
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"books": [...]
}- 路径:
/api/book/<id>/separate - 方法:POST
- 认证:需要管理员权限
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "拆分成功"
}- 路径:
/api/book/<id>/savemeta - 方法:POST
- 认证:需要管理员权限
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "元数据已保存"
}- 路径:
/api/book/<id>/addstamp - 方法:POST
- 认证:需要管理员权限
- 参数:
id(path, 必填): 图书IDstamp_id(int, 必填): 印章ID
- 响应示例:
{
"err": "ok",
"msg": "印章添加成功"
}- 路径:
/api/book/exchange_type - 方法:POST
- 认证:需要管理员权限
- 参数:
id1(int, 必填): 图书1的IDid2(int, 必填): 图书2的ID
- 响应示例:
{
"err": "ok",
"msg": "交换成功"
}- 路径:
/api/clear_rare_tags - 方法:POST
- 认证:需要管理员权限
- 参数:
threshold(int, 可选): 阈值,默认为1
- 响应示例:
{
"err": "ok",
"msg": "清理成功",
"count": 50
}- 路径:
/api/book/add - 方法:POST
- 认证:需要登录
- 参数:
- JSON数据:包含title、authors等信息
- 响应示例:
{
"err": "ok",
"book_id": 123
}- 路径:
/api/book/upload - 方法:POST
- 认证:需要登录
- 参数:
ebook(file, 必填): 图书文件,multipart/form-data 字段名须为ebook
- 响应示例:
{
"err": "ok",
"book_id": 123
}- 路径:
/api/book/upload/chunk - 方法:POST
- 认证:需要登录
- 参数:
chunk(file, 必填): 分块数据chunkIndex(int, 必填): 分块索引totalChunks(int, 必填): 总分块数filename(string, 必填): 文件名
- 响应示例:
{
"err": "ok",
"completed": false
}- 路径:
/api/<meta> - 方法:GET
- 认证:无需认证
- 参数:
meta(path, 必填): 类型,可选值:author、publisher、tag、rating、series、languageshow(string, 可选): "all" 显示全部
- 响应示例:
{
"err": "ok",
"meta": "author",
"title": "全部作者",
"items": [
{"name": "刘慈欣", "count": 10},
{"name": "金庸", "count": 20}
],
"total": 100,
"pins": [...]
}- 路径:
/api/<meta>/<name> - 方法:GET
- 认证:无需认证
- 参数:
meta(path, 必填): 类型name(path, 必填): 元数据名称page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 50,
"books": [...]
}- 路径:
/api/author/<name>/update - 方法:POST
- 认证:需要管理员权限
- 参数:
name(path, 必填): 作者名
- 响应:302重定向
- 路径:
/api/publisher/<name>/update - 方法:POST
- 认证:需要管理员权限
- 参数:
name(path, 必填): 出版社名
- 响应:302重定向
- 路径:
/api/audio/<id> - 方法:GET
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"audio_dir": "/data/books/audios/123",
"audios": [
{
"filename": "第1章",
"url": "/api/audio/123/chapter01.mp3",
"size": 1024000
}
],
"total_files": 10,
"is_paid": true
}- 路径:
/api/audio/<id>/conversion - 方法:GET/POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID- POST: 启动音频转换
- 响应示例:
{
"err": "ok",
"status": "converting",
"progress": 50
}- 路径:
/api/audio/<id>/cancel - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "转换已取消"
}- 路径:
/api/audio/<id>/delete - 方法:POST
- 认证:需要管理员权限
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "音频文件删除成功"
}- 路径:
/api/audio/<id>/purchase - 方法:POST
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "购买成功"
}- 路径:
/api/audiobooks - 方法:GET
- 认证:无需认证
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 50,
"books": [...]
}- 路径:
/api/audio/<id>/<filename> - 方法:GET
- 认证:需要登录
- 参数:
id(path, 必填): 图书IDfilename(path, 必填): 音频文件名
- 响应:返回音频文件
- 路径:
/api/audios/<id>/collection - 方法:GET
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"files": [...]
}- 路径:
/api/audios/<id>/collection/download - 方法:GET
- 认证:需要登录
- 参数:
id(path, 必填): 图书ID
- 响应:返回ZIP文件
- 路径:
/api/admin/ssl - 方法:GET/POST
- 认证:需要管理员权限
- 参数:
- GET: 获取SSL证书信息
- POST: 上传SSL证书(JSON)
- 响应示例:
{
"err": "ok",
"ssl": {
"enabled": true,
"expire_date": "2027-05-11"
}
}- 路径:
/api/admin/users - 方法:GET/POST
- 认证:需要管理员权限
- 参数:
- GET: 获取用户列表
page(int, 可选): 页码,默认1num(int, 可选): 每页数量,默认20sort(string, 可选): 排序字段desc(string, 可选): 是否降序
- POST: 更新用户信息(JSON)
- GET: 获取用户列表
- 响应示例:
{
"err": "ok",
"users": {
"items": [...],
"total": 100
},
"settings": {...}
}- 路径:
/api/admin/install - 方法:GET/POST
- 认证:无需认证(仅在未安装时可用)
- 参数:
- POST: 安装参数(JSON)
- 响应示例:
{
"err": "ok",
"msg": "安装成功"
}- 路径:
/api/admin/settings - 方法:GET/POST
- 认证:需要管理员权限
- 参数:
- GET: 获取系统设置
- POST: 更新系统设置(JSON)
- 响应示例:
{
"err": "ok",
"settings": {...}
}- 路径:
/api/admin/testmail - 方法:POST
- 认证:需要管理员权限
- 参数:
smtp_server(string, 必填): SMTP服务器smtp_username(string, 必填): SMTP用户名smtp_password(string, 必填): SMTP密码smtp_encryption(string, 必填): 加密方式
- 响应示例:
{
"err": "ok",
"msg": "发送成功"
}- 路径:
/api/admin/book/list - 方法:GET
- 认证:需要管理员权限
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量
- 响应示例:
{
"err": "ok",
"total": 1000,
"books": [...]
}- 路径:
/api/admin/book/fill - 方法:GET/POST
- 认证:需要管理员权限
- 参数:
book_id(int, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "填充成功"
}- 路径:
/api/admin/book/aifill - 方法:GET/POST
- 认证:需要管理员权限
- 参数:
book_id(int, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "AI填充成功"
}- 路径:
/api/admin/book/kindleconvert - 方法:GET/POST
- 认证:需要管理员权限
- 参数:
book_id(int, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "转换已启动"
}- 路径:
/api/admin/book/update_title_sort - 方法:GET/POST
- 认证:需要管理员权限
- 参数:无或book_id
- 响应示例:
{
"err": "ok",
"msg": "更新成功"
}- 路径:
/api/admin/bookbarn/token/apply - 方法:POST
- 认证:需要管理员权限
- 参数:
email(string, 必填): 邮箱
- 响应示例:
{
"err": "ok",
"msg": "申请成功"
}- 路径:
/api/admin/books/delete - 方法:POST
- 认证:需要管理员权限
- 参数:
book_ids(array, 必填): 图书ID数组
- 响应示例:
{
"err": "ok",
"msg": "删除成功",
"count": 10
}- 路径:
/api/admin/books/save_meta - 方法:POST
- 认证:需要管理员权限
- 参数:
book_ids(array, 必填): 图书ID数组
- 响应示例:
{
"err": "ok",
"msg": "保存成功"
}- 路径:
/api/admin/clear/invalid/items - 方法:POST
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"msg": "清理成功",
"count": 50
}- 路径:
/api/admin/audio/test - 方法:POST
- 认证:需要管理员权限
- 参数:
text(string, 必填): 测试文本
- 响应示例:
{
"err": "ok",
"audio_url": "/path/to/test.mp3"
}- 路径:
/api/admin/release/notes - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"notes": "版本更新说明..."
}- 路径:
/api/admin/token - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"token": "admin-token-here"
}- 路径:
/api/admin/tasks/running - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"tasks": [
{
"id": "task-123",
"type": "convert",
"status": "running",
"progress": 50
}
]
}- 路径:
/api/admin/trash/size - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"size": 1024000000
}- 路径:
/api/admin/trash/clear - 方法:POST
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"msg": "清空成功"
}- 路径:
/api/admin/stamp - 方法:GET/POST
- 认证:需要管理员权限
- 参数:
- GET: 获取印章列表
- POST: 添加/更新/删除印章
- 响应示例:
{
"err": "ok",
"stamps": [...]
}- 路径:
/api/library/stats - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"stats": {
"total_books": 1000,
"total_authors": 200,
"total_publishers": 100,
"total_users": 50
}
}- 路径:
/api/admin/syslog - 方法:GET
- 认证:需要管理员权限
- 参数:
lines(int, 可选): 显示行数,默认100
- 响应示例:
{
"err": "ok",
"log": "系统日志内容..."
}- 路径:
/api/admin/book/update_all_meta - 方法:POST
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"msg": "批量更新已启动"
}- 路径:
/api/admin/book/update_all_dynamic_cover - 方法:POST
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"msg": "批量更新已启动"
}- 路径:
/api/admin/book/reset_cover - 方法:POST
- 认证:需要管理员权限
- 参数:
book_id(int, 必填): 图书ID
- 响应示例:
{
"err": "ok",
"msg": "重置成功"
}- 路径:
/api/admin/syslog/download - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应:返回日志文件下载
- 路径:
/api/admin/barcode - 方法:POST
- 认证:需要登录
- 参数:
barcode_image(file, 必填): 条形码图片
- 响应示例:
{
"err": "ok",
"isbn": "9787536692930"
}- 路径:
/api/admin/import/list - 方法:GET
- 认证:需要管理员权限
- 参数:
page(int, 可选): 页码num(int, 可选): 每页数量sort(string, 可选): 排序字段desc(string, 可选): 是否降序filter(string, 可选): 过滤条件(all/todo/done)
- 响应示例:
{
"err": "ok",
"items": [...],
"total": 100,
"scanning": false,
"importing": false,
"summary": {
"total": 100,
"done": 50,
"todo": 50
},
"scan_dir": "/data/books/import"
}- 路径:
/api/admin/import/delete - 方法:POST
- 认证:需要管理员权限
- 参数:
hashlist(array/string, 必填): 文件hash列表或"all"
- 响应示例:
{
"err": "ok",
"msg": "删除成功",
"count": 10
}- 路径:
/api/admin/import/run - 方法:POST
- 认证:需要管理员权限
- 参数:
filelist(array/string, 必填): 文件列表或"all"skip_last_dirs(int, 可选): 跳过最后几级目录
- 响应示例:
{
"err": "ok",
"msg": "扫描成功"
}- 路径:
/api/admin/import/status - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"task": "task-id",
"status": {
"ready": 10,
"importing": 5,
"imported": 50,
"exist": 30,
"total": 100,
"processed": 85
},
"summary": {...},
"scanning": false,
"ignored_errors": [],
"importing": true
}- 路径:
/api/admin/batch_add/run - 方法:POST
- 认证:需要管理员权限
- 参数:
csv_file(file, 必填): CSV文件
- 响应示例:
{
"err": "ok",
"msg": "批量添加已启动"
}- 路径:
/api/admin/batch_add/status - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"status": "running",
"progress": 50,
"total": 100
}- 路径:
/api/admin/audio_import/run - 方法:POST
- 认证:需要管理员权限
- 参数:
audio_files(array, 必填): 音频文件列表
- 响应示例:
{
"err": "ok",
"msg": "音频导入已启动"
}- 路径:
/api/admin/audio_import/status - 方法:GET
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"status": "running",
"progress": 30
}- 路径:
/api/admin/import/cancel - 方法:POST
- 认证:需要管理员权限
- 参数:无
- 响应示例:
{
"err": "ok",
"msg": "导入已取消"
}OPDS(Open Publication Distribution System)接口用于提供标准化的图书目录服务,兼容各种OPDS客户端。
- 路径:
/opds/ - 方法:GET
- 认证:无需认证
- 参数:无
- 响应:返回OPDS Feed(XML)
- 路径:
/opds/nav/<which> - 方法:GET
- 认证:无需认证
- 参数:
which(path, 必填): 导航类型offset(int, 可选): 偏移量
- 响应:返回OPDS Feed(XML)
- 路径:
/opds/category/<category>/<which> - 方法:GET
- 认证:无需认证
- 参数:
category(path, 必填): 分类名which(path, 必填): 子分类offset(int, 可选): 偏移量
- 响应:返回OPDS Feed(XML)
- 路径:
/opds/categorygroup/<category>/<which> - 方法:GET
- 认证:无需认证
- 参数:
category(path, 必填): 分类组名which(path, 必填): 子分类
- 响应:返回OPDS Feed(XML)
- 路径:
/opds/search/<query> - 方法:GET
- 认证:无需认证
- 参数:
query(path, 必填): 搜索关键词offset(int, 可选): 偏移量
- 响应:返回OPDS Feed(XML)
- 路径:
/get/pcover - 方法:GET
- 认证:无需认证
- 参数:
url(string, 必填): 原始图片URL
- 响应:返回图片文件
- 路径:
/get/progress/<id> - 方法:GET
- 认证:无需认证
- 参数:
id(path, 必填): 任务ID
- 响应:返回进度文本
- 路径:
/get/extract/<book_id>/<path> - 方法:GET
- 认证:需要登录
- 参数:
book_id(path, 必填): 图书IDpath(path, 必填): 内部路径
- 响应:返回提取的文件内容
- 路径:
/get/<type>/<name> - 方法:GET
- 认证:无需认证
- 参数:
type(path, 必填): 资源类型(cover/thumb_*等)name(path, 必填): 资源名称
- 响应:返回资源文件
- 路径:
/<path> - 方法:GET
- 认证:无需认证
- 参数:
path(path, 必填): 文件路径
- 响应:返回静态文件
Podcast接口用于提供RSS订阅服务,支持播客客户端订阅有声书。
- 路径:
/podcast/ - 方法:GET
- 认证:无需认证(部分功能需要Token)
- 参数:无
- 响应:返回Podcast首页(HTML)
- 路径:
/podcast/all - 方法:GET
- 认证:无需认证
- 参数:
token(string, 可选): 用户Token
- 响应:返回RSS Feed(XML)
- 路径:
/podcast/book/<id> - 方法:GET
- 认证:无需认证
- 参数:
id(path, 必填): 图书IDtoken(string, 可选): 用户Token
- 响应:返回RSS Feed(XML)
- 路径:
/podcast/book/<id>/opml - 方法:GET
- 认证:无需认证
- 参数:
id(path, 必填): 图书ID
- 响应:返回OPML(XML)
- 路径:
/podcast/category/<name> - 方法:GET
- 认证:无需认证
- 参数:
name(path, 必填): 分类名token(string, 可选): 用户Token
- 响应:返回HTML页面列出该分类下的有声书
- 路径:
/podcast/tag/<name> - 方法:GET
- 认证:无需认证
- 参数:
name(path, 必填): 标签名token(string, 可选): 用户Token
- 响应:返回HTML页面列出该标签下的有声书
- 路径:
/podcast/author/<name> - 方法:GET
- 认证:无需认证
- 参数:
name(path, 必填): 作者名token(string, 可选): 用户Token
- 响应:返回HTML页面列出该作者的有声书
- 路径:
/podcast/<token>/book/<id> - 方法:GET
- 认证:通过Token认证
- 参数:
token(path, 必填): 用户Podcast Tokenid(path, 必填): 图书ID
- 响应:返回RSS Feed(XML)
- 路径:
/podcast/<token>/ - 方法:GET
- 认证:通过Token认证
- 参数:
token(path, 必填): 用户Podcast Token
- 响应:返回HTML页面列出个人订阅
- 路径:
/podcast/audio/<book_id>/<token>/<filename> - 方法:GET
- 认证:通过Token认证
- 参数:
book_id(path, 必填): 图书IDtoken(path, 必填): 访问Tokenfilename(path, 必填): 音频文件名
- 响应:返回音频文件
- 路径:
/api/assistant/ws - 方法:WebSocket
- 认证:需要登录
- 参数:
- WebSocket消息(JSON):
content(string, 必填): 用户输入内容
- WebSocket消息(JSON):
- 响应:
- 流式返回AI助手响应(JSON chunks)
- 消息类型:
{"type": "status", "content": "..."}{"type": "start"}{"type": "data", "content": "..."}{"type": "end"}{"type": "error", "content": "..."}
- 路径:
/api/mcp/stream - 方法:GET/POST
- 认证:可选(支持Token参数)
- 参数:
- GET: 获取MCP服务信息
- POST: 发送MCP请求(JSON-RPC格式)
token(query, 可选): 访问Token
- 响应示例:
GET响应:
{
"err": "ok",
"version": "v3.20.0",
"settings": {
"base_url": "https://your.site",
"mcp_version": "v3.20.0"
},
"timestamp": "2026-05-11T10:00:00"
}POST响应:
{
"err": "ok",
"jsonrpc": "2.0",
"result": {...}
}- 路径:
/api/mcp/health - 方法:GET
- 认证:无需认证
- 参数:无
- 响应示例:
{
"err": "ok",
"status": "healthy",
"server": "mybooks-mcp"
}常见错误代码:
ok: 请求成功params.invalid: 参数无效params.book.invalid: 图书不存在params.user.not_exist: 用户不存在permission.not_admin: 非管理员无权限permission.denied: 权限不足permission.inactive: 用户未激活user.no_permission: 无权限操作db.error: 数据库错误email.server_error: 邮件服务器错误internal: 内部错误
阅读状态字段(read_state):
0: 未读1: 在读2: 已读
收藏/待读状态:
favorite: 1=已收藏,0=未收藏wants: 1=想读,0=不想读
图书类型字段(book_type):
0: 电子书1: 实体书
大部分API使用Cookie进行认证,登录后会设置以下Cookie:
user_id: 用户ID(加密)admin_id: 管理员ID(管理员切换用户时使用)
部分API支持Token认证:
- Podcast订阅:使用
podcast_token参数 - MCP服务:使用
token查询参数 - 音频访问:使用Token进行权限验证