快速开始
三步就能让脚本发出第一章。
第一步:创建 API 令牌
登录 拆书铺,点右上角头像打开个人中心,在「API 令牌」面板里填写名称、选择有效期,点「创建新令牌」。
生成后请立刻复制保存。关闭面板后无法再次查看,只能删除重建。令牌等同于你的账号权限,不要提交进代码仓库或公开分享。
第二步:创建一部小说
拿到令牌后,创建作品。注意这个接口用的是 multipart/form-data,因为要支持上传封面。
curl -X POST https://doaiapp.com/api/novels \
-H "authorization: Bearer csk_你的令牌" \
-F "title=山海食肆" \
-F "author=听风" \
-F "description=一间开在昆仑山脚的食肆,只招待非人之客。厨子沉默寡言,菜单上写着的价格,从来不是钱。" \
-F "audience=general" \
-F "primaryCategory=玄幻" \
-F "secondaryCategory=东方玄幻" \
-F "tags=美食,志怪,治愈" \
-F "serialStatus=serializing"返回作品 ID,后面发章要用:
{ "id": "9f2c...e41a", "title": "山海食肆", "author": "听风", "status": "listed" }第三步:发布章节
curl -X POST https://doaiapp.com/api/novels/9f2c...e41a/chapters \
-H "authorization: Bearer csk_你的令牌" \
-H "content-type: application/json" \
-d '{"title":"第一章 夜客","content":"灯笼亮起的时候,第一位客人推门进来……"}'章号由服务端自动递增,你不需要自己维护计数。
{ "chapterNumber": 1, "title": "第一章 夜客", "wordCount": 1284 }认证
所有内容接口都接受两种身份:浏览器登录态(Cookie)和 API 令牌(Bearer)。脚本用后者。
authorization: Bearer csk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx令牌以 csk_ 开头。服务端只保存它的哈希值,即使数据库泄露也无法反推原文。每次调用会刷新「最近使用」时间(60 秒内不重复写入)。
两层权限
内容接口(建书、发章、完结、打赏)—— 令牌或登录态皆可。
令牌管理接口(创建、查看、删除令牌)—— 只接受登录态。令牌不能用来创建新令牌,这样一个泄露的令牌无法自我续命,你删掉它就是真的删掉了。
失效情形
- 令牌被删除 → 立即失效,返回 401
- 超过有效期 → 自动失效,返回 401
- 账号被停用 → 所有令牌一并失效,返回 403
接口参考
/api/novels令牌或登录态创建一部新作品。请求体为 multipart/form-data。
titlestring,2—18 字作品名称authorstring,≤40 字作者署名descriptionstring,20—500 字作品简介,少于 20 字会被拒绝primaryCategorystring,必填一级分类,如「玄幻」secondaryCategorystring,必填二级分类,如「东方玄幻」audiencemale / female / general面向读者,默认 generalserialStatusserializing / completed连载状态,默认 serializingtagsstring,逗号分隔,最多 8 个标签,超出部分截断protagonistsstring,逗号分隔,最多 6 个主角名coverFile,≤5MB封面图,仅支持 JPG / PNG / WebP成功返回 201,响应体含 id、title、author、status。
/api/novels/{id}/chapters令牌或登录态发布新章节。章号自动递增,正文按有效字符计数(不含空格和标点)。
titlestring,≤80 字章节标题contentstring,≥100 有效字,≤120000 字符章节正文,\r\n 会被归一化为 \n成功返回 201 及 chapterNumber、wordCount。作品已完结时返回 409。
/api/novels/{id}/chapters/{number}令牌或登录态读回某一章的标题与正文,方便先取再改。只有作者本人能读自己的章节原文。
/api/novels/{id}/chapters/{number}令牌或登录态修改已发布的章节。两个字段都可选,省略哪个就保留哪个原值;字数和全书总字数会自动重算。
titlestring,≤80 字,选填新的章节标题contentstring,≥100 有效字,≤120000 字符,选填新的章节正文两个都不传返回 400。章节号不变,读者看到的顺序不受影响。
/api/novels/{id}/status令牌或登录态将作品设为完结。目前只支持这一个方向,完结后无法继续发章,也无法改回连载中。
{ "status": "completed" }/api/novels/{id}令牌或登录态删除作品,有两种语义。
purgetrue,查询参数,选填不传 = 下架;传 true = 彻底删除下架(默认):把状态改为 removed,读者立刻不可见,市场、阅读、下载、预览全部失效,但订单、积分流水、创作者收益和打赏记录原样保留。
彻底删除(?purge=true):连同章节、作品资料、审核记录和封面文件一并抹掉,不可恢复。若该作品存在任何交易或打赏记录,会返回 409 并拒绝执行 —— 付费凭证和待结算收益不能被删掉。这条限制是故意的,想清空这类作品请改用下架。
/api/novels/{id}/tip令牌或登录态给某一章打赏积分。不能打赏自己的作品。
chapterNumberinteger,≥1章节序号points1 / 5 / 10 / 20 / 50 / 100打赏积分,只接受这六档requestIdstring,≤100 字符,选填幂等键,重复提交同一个值不会重复扣分积分不足返回 402。
/api/tokens仅登录态列出当前有效的令牌。只返回前缀,不返回明文。
/api/tokens仅登录态创建令牌,每个账号最多同时保留 10 个。
namestring,2—40 字令牌名称,便于区分用途expiresInDaysinteger,1—365,选填有效期天数,留空或 null 表示长期有效/api/tokens/{id}仅登录态吊销令牌,立即生效且不可恢复。
内容分级
每次发布或修改章节后,正文会交给 DeepSeek 自动判级,结果记在作品上,无需你传任何参数。
general常规题材。市场卡片不显示任何分级角标mature含露骨性描写、详细暴力血腥、自残或毒品细节。卡片与阅读页显示红色「18+」角标pending尚未判级 —— 判级服务不可用或调用失败。不显示角标,后续可重新判级分级只升不降:一部作品里只要有一章被判为 mature,整部作品就是 mature,后续发布常规章节不会把它降回去。
判级服务超时或报错时,章节照常发布成功,作品分级记为 pending。发章和改章的响应里会带上 rating 字段,告诉你当前作品的分级结果。
作品列表(GET /api/books)和阅读接口都会返回 rating,你可以据此自行决定要不要展示或过滤。
错误码
所有错误响应体格式统一为 { "error": "中文描述" }。
400参数不合法 —— 字数超限、分类缺失、打赏档位无效等,错误信息会指出具体哪一项401未认证 —— 令牌缺失、格式错误、已删除或已过期402积分不足(仅打赏接口)403账号已停用404作品或章节不存在,或不属于你409状态冲突 —— 作品已完结仍尝试发章、令牌数已达上限,或对有交易记录的作品执行彻底删除413内容过大 —— 封面超过 5MB,或单章超过 12 万字符500服务端异常,可稍后重试完整示例
Bash:建书并批量发章
把本地 chapters/ 目录下按文件名排序的 txt 依次发布,文件第一行作标题,其余作正文。
#!/usr/bin/env bash
set -euo pipefail
TOKEN="csk_你的令牌"
BASE="https://doaiapp.com"
# 1. 建书,取回作品 ID
BOOK_ID=$(curl -s -X POST "$BASE/api/novels" \
-H "authorization: Bearer $TOKEN" \
-F "title=山海食肆" \
-F "author=听风" \
-F "description=一间开在昆仑山脚的食肆,只招待非人之客。" \
-F "primaryCategory=玄幻" \
-F "secondaryCategory=东方玄幻" \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["id"])')
echo "作品已创建:$BOOK_ID"
# 2. 按文件名顺序发章
for file in chapters/*.txt; do
title=$(head -n 1 "$file")
content=$(tail -n +2 "$file")
payload=$(python3 -c 'import json,sys; print(json.dumps({"title":sys.argv[1],"content":sys.argv[2]}))' "$title" "$content")
response=$(curl -s -X POST "$BASE/api/novels/$BOOK_ID/chapters" \
-H "authorization: Bearer $TOKEN" \
-H "content-type: application/json" \
-d "$payload")
echo "$file -> $response"
sleep 1 # 温柔一点,别把自己的站点打疼
donePython:带重试的发章函数
import os, time, requests
BASE = "https://doaiapp.com"
TOKEN = os.environ["CHAISHU_TOKEN"] # 令牌放环境变量,别写进代码
HEADERS = {"authorization": f"Bearer {TOKEN}"}
def publish_chapter(book_id: str, title: str, content: str, retries: int = 3) -> dict:
"""发布一章,遇到 5xx 自动退避重试;4xx 直接抛出,因为重试也不会成功。"""
url = f"{BASE}/api/novels/{book_id}/chapters"
for attempt in range(retries):
response = requests.post(url, headers=HEADERS, json={"title": title, "content": content}, timeout=30)
if response.status_code == 201:
return response.json()
if response.status_code < 500:
raise RuntimeError(f"{response.status_code}: {response.json().get('error')}")
time.sleep(2 ** attempt)
raise RuntimeError("服务端持续异常,已放弃")
if __name__ == "__main__":
result = publish_chapter("9f2c...e41a", "第一章 夜客", open("ch01.txt", encoding="utf-8").read())
print(f"已发布第 {result['chapterNumber']} 章,{result['wordCount']} 字")使用须知
- 令牌保管:用环境变量或密钥管理工具存放,不要提交进 git。怀疑泄露时立刻在个人中心删除,旧令牌会即刻失效。
- 调用频率:目前没有强制限流,但请自觉控制节奏(批量发章建议每章间隔 1 秒以上)。滥用会导致账号被停用。
- 内容责任:通过 API 发布的内容与网页端发布的内容适用同一套审核规则,请遵守 用户协议 与 版权规范。
- 接口变更:新增字段会保持向后兼容;如有破坏性调整,会提前在本页公告。
站内:登录后点击页面右上角「建议与意见」
电子邮箱:xbmld1@gmail.com