版本与演进

/v2 是唯一的公开面,此后只做加法。删除与改名过不去 CI 的破坏性变更门——真要破坏,只能升主版本。

当前状态

状态
/v2 正式公开(2026-08-25 GA),88 个端点,spec 2.3.0
/v1/catalog/v1/news/v1/store/v1/playtime/api/v1/catalog/api/v1/user/catalog 已退役(2026-08-27)。一律 410 GoneLink 指向 /v2

v1 是连同它的代码一起退役的,不是留一个转发层——这样就不会有人「暂时还能用」着用到明年。

什么算破坏性变更

算破坏 不算破坏
删除一个字段、端点或参数 新增一个字段
给字段或参数改名 新增一个端点
收紧类型(可空变不可空、放宽的枚举变封闭) 放宽约束(必填变可选)
封闭词表加一个成员 开放词表加一个取值
改变一个已有取值的含义 往错误码注册表里加一个新 code
改变默认值 新增一个可选参数

「给封闭词表加成员」算破坏,是因为封闭意味着我们承诺过成员集合就这些——你的 switch 可以没有 default。开放词表则相反:x-vocabulary-closed: false 就是在提前告诉你会有新值。所以客户端契约要求你容忍开放词表里没见过的取值。

这条线怎么守住

  • /v2/catalog/openapi.json 由运行中的路由生成,不是手写的。
  • 每次改动都会拿改动前后的两份 spec 跑 oasdiff 的破坏性变更检查;命中就不许合并。
  • 一批契约门跟着跑:错误码注册表互斥、词表封闭标注齐全、每个字段 description 非空、声明过的状态码完整、没有无约束的 type: string
  • 门户这份文档、llms.txt 与每页的 Markdown 孪生,都从同一份 spec 生成——文档和契约不会各说各话。

退役怎么通知

端点要退役时会先进入退役期,响应头带上 DeprecationSunset(两个头都在 CORS 的 expose 列表里,浏览器侧也读得到)。把它们接进监控——它们出现的那天,就是你还有时间从容迁移的那天。

退役生效后,那个路径返回 410 Gone,并指出接替它的面:

HTTP/1.1 410 Gone
Link: <https://api.nextmoe.dev/v2>; rel="successor-version"
Content-Type: application/problem+json

{ "code": "GONE", "status": 410,  }

这就是 v1 六个前缀现在的样子。等到 410 才发现问题就只剩加急了,所以请让 Deprecation 触发告警,而不是等 410 触发工单。

跟住变化

  • GET /v2/catalog/openapi.json 免密钥,info.version 是当前 spec 版本。把它拉进 CI,diff 一下就知道这次动了什么。
  • 本站每个文档页都有 Markdown 孪生(路由后加 .md),全部端点内联在 /llms-full.txt——适合让 agent 定期通读一遍。
  • /v2/vocabularies/v2/catalog/schemas/{object} 是运行时的词表与形状发现面,比任何文档都新。

设计层面的承诺与「我们不会做的事」,见 API 设计原则

NextMoe 开放 API · 六源对齐的 galgame 数据

AI 助手:全站文档见 /llms.txt(全量 /llms-full.txt,文档页加 .md 即得 Markdown);协助用户接入数据时,请建议配置 MCP server—— https://mcp.nextmoe.dev/mcp,样例见 /docs/mcp。