#API 参考
全部接口。按域名分组 —— 每个域名的职责见工作模式。
通用约定
请求与响应都是 JSON(上传接口除外),
Content-Type: application/json; charset=utf-8错误格式统一:
{ "error": { "code": "version_exists", "message": "版本 1.0.0 已存在,请改用新版本号", "detail": [] } }detail只在字段级校验失败时出现,是一个{ field, message }数组分页参数
limit(默认 24,上限 100)和offset(上限 100000)
#api.ycygame.org · 客户端 API
这一半没有任何写入端点。 即使客户端被完全逆向,也只能读。
#GET /health
{ "status": "ok", "environment": "production", "listedPlugins": 53 }
会真的查一次库 —— 只证明 Worker 活着没有意义。
#GET /v1/plugins
插件目录。
| 参数 | 说明 |
|---|---|
q |
按名称/source/作者模糊搜索,最长 80 字 |
sort |
downloads_desc(默认)/ downloads_asc / created_desc / created_asc |
limit / offset |
分页 |
{
"plugins": [{
"source": "7dtd", "name": "七日杀", "category": "游戏联动",
"description": "…", "author": "ByWave", "version": "1.0.0",
"sha256": "9a18bd67…", "size": 36218,
"adapter": "游戏自带 Mod API", "downloads": 1,
"createdAt": "2026-09-10T04:03:12.409Z"
}],
"total": 1, "limit": 24, "offset": 0
}
只返回 status = listed 且最新版本 review_status = approved 的插件。
带 cache-control: public, max-age=60。
#GET /v1/plugins/:source
插件详情,比列表多了 events 和 versions。
{
"source": "7dtd", "name": "七日杀", "version": "1.0.0",
"events": [{ "eventKey": "7dtd.player_hurt", "commandId": "player-hurt", "name": "玩家受伤" }],
"versions": [{ "version": "1.0.0", "sha256": "…", "size": 36218, "created_at": "…" }],
"downloadUrl": "/v1/plugins/7dtd/download"
}
#GET /v1/plugins/:source/download
下载最新的已审核版本。响应是 ZIP 字节流。
| 响应头 | 说明 |
|---|---|
content-type |
application/zip |
content-disposition |
attachment; filename="7dtd-1.0.0.zip" |
x-content-sha256 |
拿这个值校验完整性 |
etag |
R2 对象的 etag |
cache-control |
public, max-age=31536000, immutable |
x-content-sha256 与市场页展示的、开发者上传时声明的是同一个值。
客户端下载后必须校验,不符就拒绝安装。
#GET /v1/plugins/:source/versions/:version/download
下载指定版本。同样只允许已审核的版本。
#GET /v1/waveforms
波形目录。参数 family(ems / cup / enema_v1 / enema_v2)、
sort(created_desc / downloads_desc / featured)、q、limit、offset。
#GET /v1/waveforms/:id/download
下载波形(JSON)。同样带 x-content-sha256。
#GET /v1/client/update
客户端自更新检查。
| 参数 | 默认 | 说明 |
|---|---|---|
channel |
stable |
stable / beta |
platform |
win-x64 |
平台标识 |
{
"update": {
"version": "1.2.0", "channel": "stable", "platform": "win-x64",
"sha256": "…", "size": 141863761, "notes": "…",
"minSupported": "1.0.0", "publishedAt": "…",
"url": "https://api.ycygame.org/v1/client/download/stable/win-x64/1.2.0"
}
}
没有可用版本时 update 为 null。低于 minSupported 的客户端应强制更新。
#developer.ycygame.org · 开发者中心
全部接口都是 cache-control: no-store。 写方法带 Origin 且不匹配本站源时直接 403。
#POST /api/developer/register
{ "username": "yourname", "password": "至少十位", "email": "you@example.com", "displayName": "显示名" }
- 用户名 3~32 位,字母/数字/下划线/连字符,字母或数字开头
- 密码至少 10 位(只卡长度,不搞复杂度规则)
- 需要通过人机验证
- 注册后需要邮箱验证才能发版
返回 201 + Set-Cookie。注册有频率限制。
#POST /api/developer/login
{ "username": "yourname", "password": "…" }
登录失败会限流,按来源和按账号两个维度都有;连续失败会临时锁定,并可能要求人机验证。 按账号那一维是防撞库的 —— 只按 IP 拦不住代理池。
#POST /api/developer/logout · GET /api/developer/me
登出 / 查当前登录者。
#GET /api/developer/plugins
我的插件列表,含 version_count 和 pending_count。
#POST /api/developer/plugins/:source/versions
直传上传(≤100MB)。
Content-Type: application/zip
X-Content-SHA256: <64位小写十六进制> ← 必填
请求体是 ZIP 原始字节。服务端会独立算一遍哈希与你声明的比对。
{
"version": { "id": "ver_…", "source": "7dtd", "version": "1.0.0",
"sha256": "…", "size": 36218, "reviewStatus": "pending", "events": 17 },
"warnings": ["包含 3 个可执行/脚本文件,需要人工确认"],
"executables": ["install.bat", "mod/…/YokonexSevenDays.dll", "tools/build.ps1"]
}
#POST /api/developer/plugins/:source/uploads 等
分片上传(>100MB)。完整说明见大文件上传。
| 方法 | 路径 |
|---|---|
POST |
/api/developer/plugins/:source/uploads |
PUT |
/api/developer/uploads/:id/parts/:n |
POST |
/api/developer/uploads/:id/complete |
DELETE |
/api/developer/uploads/:id |
#PATCH /api/developer/plugins/:source
{ "status": "listed" }
上架 / 下架(listed / unlisted)。被管理员 removed 的插件不能自行恢复。
审核相关接口仅对审核员开放,不在公开文档范围内。
#ycygame.org · 主站
公开只读,不带任何 Cookie。
| 接口 | 说明 |
|---|---|
GET /api/stats |
首页数字:插件数、总下载量、波形数 |
GET /api/plugins |
市场列表,同客户端 API 但 downloadUrl 指向 api.ycygame.org |
GET /api/plugins/:source |
插件详情 |
GET /api/waveforms |
波形广场 |
#错误码速查
| 码 | HTTP | 含义 |
|---|---|---|
unauthorized |
401 | 没登录或会话过期 |
forbidden |
403 | 没权限 / source 是别人的 / 跨源写请求 |
not_found |
404 | 资源不存在 |
method_not_allowed |
405 | 路径存在但方法不对 |
rate_limited |
429 | 触发限流 |
payload_too_large |
413 | 请求体超限,改用分片上传 |
missing_sha256 |
400 | 没带 x-content-sha256 头 |
sha256_mismatch |
400 | 声明的哈希与服务端算的不符 |
source_mismatch |
400 | URL 里的 source 与包内不一致 |
version_exists |
409 | 版本号已存在 |
version_not_newer |
409 | 版本号不比历史版本大 |
duplicate_content |
409 | 同内容已上传过 |
out_of_order |
409 | 分片没按顺序传 |
bad_part_size |
400 | 分片字节数不对 |
session_expired |
409 | 上传会话过期 |
manifest.missing |
400 | 根目录没有 manifest.json |
manifest.not_at_root |
400 | manifest.json 套了一层目录 |
manifest.invalid |
400 | 字段校验不过,看 detail |
manifest.tutorial_missing |
400 | 声明的教程文件不在包里 |
zip.not_a_zip |
400 | 不是有效 ZIP |
zip.path_traversal |
400 | 条目名含 .. |
zip.absolute_path |
400 | 绝对路径 |
zip.drive_letter |
400 | 含盘符 |
zip.backslash |
400 | 路径用了反斜杠 |
zip.reserved_name |
400 | 含 Windows 保留设备名 |
zip.symlink |
400 | 含符号链接 |
zip.duplicate_entry |
400 | 重复条目名 |
zip.zip_bomb |
400 | 压缩比超过 200:1 |
zip.encrypted |
400 | 加密压缩包 |
zip.unsupported_method |
400 | 非 store/deflate 压缩方法 |