跳转到文档内容
文档ATHubAPI 参考数据导入
API REFERENCEATHub

批量上传小说

一次创建小说并导入卷与章节,或为已有小说分批续传。

POST/api/v2/uploadREST
{ }Bodyapplication/json
示例代码
{
  "novel": {
    "platformId": 1,
    "authorId": 2,
    "title": "示例小说",
    "summary": "小说简介",
    "coverUrl": null,
    "status": "ONGOING"
  },
  "volumes": [
    { "order": 1, "title": "第一卷 启程" },
    { "order": 2, "title": "第二卷 远方" }
  ],
  "chapters": [
    {
      "order": 1,
      "volumeOrder": null,
      "title": "序章",
      "content": "未分卷的序章正文。"
    },
    {
      "order": 2,
      "volumeOrder": 1,
      "title": "第一章 出发",
      "content": "第一段。\n\n第二段。"
    },
    {
      "order": 3,
      "volumeOrder": 2,
      "title": "第二章 远行",
      "content": "第二卷中的章节正文。"
    }
  ]
}

Request Body

application/json

这是推荐的小说导入接口。上传前先取得平台 ID,可选取得作者 ID。 每次请求只能选择以下一种模式:

  1. 新建小说:提供 novel 对象,不提供 novelId。成功返回 201。
  2. 已有小说续传:提供 novelId,不提供 novel。成功返回 200。

不带查询参数。新建模式允许只建元信息;续传模式至少包含一个卷或一个章节。

8.1 新建小说并上传卷、章节

示例代码
{
  "novel": {
    "platformId": 1,
    "authorId": 2,
    "title": "示例小说",
    "summary": "小说简介",
    "coverUrl": null,
    "status": "ONGOING"
  },
  "volumes": [
    { "order": 1, "title": "第一卷 启程" },
    { "order": 2, "title": "第二卷 远方" }
  ],
  "chapters": [
    {
      "order": 1,
      "volumeOrder": null,
      "title": "序章",
      "content": "未分卷的序章正文。"
    },
    {
      "order": 2,
      "volumeOrder": 1,
      "title": "第一章 出发",
      "content": "第一段。\n\n第二段。"
    },
    {
      "order": 3,
      "volumeOrder": 2,
      "title": "第二章 远行",
      "content": "第二卷中的章节正文。"
    }
  ]
}

8.2 给已有小说分批续传

示例代码
{
  "novelId": 10,
  "volumes": [
    { "order": 3, "title": "第三卷 归途" }
  ],
  "chapters": [
    {
      "order": 4,
      "volumeOrder": 3,
      "title": "第三章 归来",
      "content": "新章节正文。"
    },
    {
      "order": 5,
      "volumeOrder": 1,
      "title": "第一卷补记",
      "content": "引用此前已经存在的第一卷。"
    }
  ]
}

续传只修改本批次列出的卷、章节,不清空其他数据,不修改小说元信息。 要修改小说元信息,另行使用 PUT /api/v2/novelinfo?id=10。

8.3 顶层字段

请求键类型必填说明
novelobject / null新建模式必填第 5.4 节定义的小说写入对象;与非空 novelId 互斥。
novelIdinteger / null续传模式必填已存在的小说 ID;不存在返回 404。与非空 novel 互斥。
volumesarray / null否本批次要新增/覆盖的卷,最多 200 项;省略/null/空数组均表示本批不写入卷。
chaptersarray / null否本批次要新增/覆盖的章节,最多 1000 项;省略/null/空数组均表示本批不写入章节。

8.4 volumes 数组每项的所有键

请求键类型必填说明
orderinteger是小说内卷序号;同一批次不能重复,不要求数组按序排列。
titlestring是卷名,去除首尾空白后不能为空。

这里不提交 novelId、id 或时间字段;小说由顶层确定。 卷按 (novelId, order) 新增或覆盖,已有卷保留 ID、创建时间和章节关联。

8.5 chapters 数组每项的所有键

请求键类型必填默认/约束
orderinteger是全书章节序号;同一批次不能重复,跨卷不重置,不要求连续或数组排序。
volumeOrderinteger / null否卷序号,不是卷 ID;引用本批次创建的卷,或同一本小说此前已经存在的卷。省略/null 会将章节设为未分卷。
titlestring是章节标题,去除首尾空白后不能为空。
contentstring是非全空白的纯文本正文,原始换行和空白保留。

批量上传不接受单章接口的 volumeId,用 volumeOrder 避免新卷尚无数据库 ID 的问题。 卷先写入,章节后写入;数组顺序不影响关联。卷引用找不到返回 400,整个事务回滚。 同一小说允许未分卷章节与分卷章节混用,卷可以暂时没有章节。

8.6 成功响应的所有键

新建返回 201,同时带 Location: /api/v2/novelinfo?id=10;续传返回 200。

示例代码
{
  "novel": {
    "id": 10,
    "platformId": 1,
    "authorId": 2,
    "title": "示例小说",
    "summary": "小说简介",
    "coverUrl": null,
    "status": "ONGOING",
    "createdAt": "2026-10-29T04:00:00Z",
    "updatedAt": "2026-10-29T04:00:00Z"
  },
  "volumes": [
    {
      "id": 20,
      "novelId": 10,
      "order": 1,
      "title": "第一卷 启程",
      "createdAt": "2026-10-29T04:00:00Z",
      "updatedAt": "2026-10-29T04:00:00Z"
    }
  ],
  "chapters": [
    {
      "id": 30,
      "order": 2,
      "volumeId": 20,
      "updatedAt": "2026-10-29T04:00:00Z"
    }
  ],
  "chapterCount": 1
}

以上用一卷一章展示响应结构,并非 8.1 完整请求的逐项响应。

响应键类型说明
novelobject完整小说元信息,所有键见第 5 节。
volumesarray本批次显式写入的卷,结构见第 6 节,按请求数组顺序返回;未写卷时为 []。仅被章节引用的旧卷不会额外出现在这里。
chaptersarray本批次章节回执,按请求数组顺序返回;未写章节时为 []。不重复返回正文,完整章节用 GET /api/v2/content 获取。
chapters[].idinteger章节数据库 ID。
chapters[].orderinteger全书章节序号。
chapters[].volumeIdinteger / null解析后的数据库卷 ID,未分卷为 null。
chapters[].updatedAtstring本次写入的服务端更新时间。
chapterCountinteger本批次成功写入的章节条数,不是全书章节总数。新增和覆盖都计数。

8.7 事务、覆盖与重试规则

  • 每批次一个数据库事务,任何关联或数据库错误都会撤销本批新小说、卷和章节的全部修改,不会部分成功。
  • 卷按 (novelId, order)、章节按 (novelId, order) 覆盖。既有章节保留 ID,替换标题、正文与卷关联。
  • 卷序号和章节序号是两套独立编号。序号是定位键,提交新序号不会移动/重编号旧记录,而是创建另一条。
  • 同一批内部的重复卷序号或重复章节序号直接返回 400,避免隐式“最后一条覆盖”。
  • 首次创建不按标题去重,也没有幂等键。重复发送带 novel 的请求会创建多部小说。
  • 成功取得 novel.id 后,后续请求统一改用 novelId。相同续传数据可以重试,记录 ID 保持不变,更新时间会更新。
  • 如首次请求超时或连接中断,提交结果可能不明;先查询并核对,不要盲目再次用 novel 新建。
  • 上传卷/章节不刷新小说的 updatedAt,该字段仅反映小说元信息写入时间。
  • 多批之间不是同一个事务:某批失败不会撤销此前成功的批次。8 MiB/1000 章以内按需拆分,分批进度由客户端记录。
正文与 JSON 示例读取自 docs/content/athub/API.md,与项目文档保持同源。
发现文档有问题?在 GitHub 提出建议 ↗