403 lines
13 KiB
Markdown
403 lines
13 KiB
Markdown
# Modrinth 获取版本信息 API 使用文档
|
||
|
||
本文档描述如何通过 Modrinth API 获取项目的版本列表以及每个版本的详细信息,包括版本名(`name`)、版本号(`version_number`)、文件名(`filename`)、下载地址等。
|
||
|
||
---
|
||
|
||
## 基本信息
|
||
|
||
所有版本读取接口均为 **公开接口,无需认证**。但如果项目包含 `draft`(草稿)状态的版本,获取它们可能需要认证。
|
||
|
||
| 项目 | 内容 |
|
||
|------|------|
|
||
| **生产环境** | `https://api.modrinth.com/v2` |
|
||
| **测试环境** | `https://staging-api.modrinth.com/v2` |
|
||
| **认证** | 公开接口无需认证;获取草稿版本需要 PAT |
|
||
| **Rate Limit** | 每 IP 每分钟 300 请求 |
|
||
|
||
---
|
||
|
||
## 接口一:列出项目的所有版本
|
||
|
||
获取指定项目下的全部版本列表。这是获取版本信息最常用的入口。
|
||
|
||
| 项目 | 内容 |
|
||
|------|------|
|
||
| **端点** | `GET /project/{id\|slug}/version` |
|
||
| **认证** | 否(公开) |
|
||
| **成功响应码** | `200` |
|
||
| **响应体** | `Version[]` — Version 对象数组 |
|
||
|
||
### 路径参数
|
||
|
||
| 参数 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `id\|slug` | 项目的 8 位 base62 ID 或 slug(别名) | `AABBCCDD` 或 `my-mod` |
|
||
|
||
### 查询参数(可选,用于过滤)
|
||
|
||
| 参数 | 类型 | 说明 | 示例 |
|
||
|------|------|------|------|
|
||
| `loaders` | `string` | 按加载器过滤,JSON 数组字符串 | `'["fabric"]'` |
|
||
| `game_versions` | `string` | 按 Minecraft 版本过滤,JSON 数组字符串 | `'["1.20.4"]'` |
|
||
| `featured` | `boolean` | 按是否精选过滤 | `true` |
|
||
| `include_changelog` | `boolean` | 是否在响应中包含 `changelog` 字段。**强烈建议设为 `false`** 以减小响应体,除非确实需要更新日志内容 | `false` |
|
||
|
||
### 请求示例
|
||
|
||
**获取某项目的全部版本(不含 changelog):**
|
||
|
||
```bash
|
||
curl "https://api.modrinth.com/v2/project/AABBCCDD/version?include_changelog=false"
|
||
```
|
||
|
||
**按加载器和游戏版本过滤:**
|
||
|
||
```bash
|
||
curl "https://api.modrinth.com/v2/project/AABBCCDD/version?loaders=%5B%22fabric%22%5D&game_versions=%5B%221.20.4%22%5D"
|
||
```
|
||
|
||
> 注意:`loaders` 和 `game_versions` 的值需要是 JSON 数组字符串(如 `["fabric"]`),在 URL 中需要做 URL 编码。`[...]` 编码后为 `%5B...%5D`。
|
||
|
||
**Node.js (fetch) 示例:**
|
||
|
||
```js
|
||
const projectId = "AABBCCDD";
|
||
|
||
const url = new URL(`https://api.modrinth.com/v2/project/${projectId}/version`);
|
||
url.searchParams.set("include_changelog", "false");
|
||
|
||
const response = await fetch(url);
|
||
const versions = await response.json();
|
||
|
||
for (const v of versions) {
|
||
console.log(`版本名: ${v.name}`);
|
||
console.log(`版本号: ${v.version_number}`);
|
||
for (const f of v.files) {
|
||
console.log(` 文件: ${f.filename} (${f.size} bytes) ${f.primary ? "[主文件]" : ""}`);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 接口二:获取单个版本
|
||
|
||
根据版本 ID 获取某个版本的完整信息。
|
||
|
||
| 项目 | 内容 |
|
||
|------|------|
|
||
| **端点** | `GET /version/{id}` |
|
||
| **认证** | 否(公开) |
|
||
| **成功响应码** | `200` |
|
||
| **响应体** | `Version` 对象 |
|
||
|
||
### 路径参数
|
||
|
||
| 参数 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `id` | 版本 ID(8 位 base62 字符串) | `IIJJKKLL` |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl "https://api.modrinth.com/v2/version/IIJJKKLL"
|
||
```
|
||
|
||
```js
|
||
const versionId = "IIJJKKLL";
|
||
const response = await fetch(`https://api.modrinth.com/v2/version/${versionId}`);
|
||
const version = await response.json();
|
||
console.log(version.name, version.version_number);
|
||
```
|
||
|
||
---
|
||
|
||
## 接口三:通过项目 + 版本号获取版本
|
||
|
||
如果你知道项目 ID 和版本号(而非版本 ID),可以用此接口直接获取。
|
||
|
||
| 项目 | 内容 |
|
||
|------|------|
|
||
| **端点** | `GET /project/{id\|slug}/version/{id\|number}` |
|
||
| **认证** | 否(公开) |
|
||
| **成功响应码** | `200` |
|
||
| **响应体** | `Version` 对象 |
|
||
|
||
### 路径参数
|
||
|
||
| 参数 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `id\|slug` | 项目 ID 或 slug | `AABBCCDD` |
|
||
| `id\|number` | 版本 ID 或版本号字符串 | `1.0.0` 或 `IIJJKKLL` |
|
||
|
||
> **注意:** 如果版本号匹配到多个版本,只会返回 **最旧的** 那个。建议使用版本 ID 获得精确结果。
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl "https://api.modrinth.com/v2/project/AABBCCDD/version/1.0.0"
|
||
```
|
||
|
||
---
|
||
|
||
## 接口四:批量获取多个版本
|
||
|
||
一次请求获取多个指定版本的信息。
|
||
|
||
| 项目 | 内容 |
|
||
|------|------|
|
||
| **端点** | `GET /versions` |
|
||
| **认证** | 否(公开) |
|
||
| **成功响应码** | `200` |
|
||
| **响应体** | `Version[]` — Version 对象数组 |
|
||
|
||
### 查询参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 | 示例 |
|
||
|------|------|------|------|------|
|
||
| `ids` | `string` | ✅ | JSON 数组字符串,包含版本 ID 列表 | `'["IIJJKKLL", "MMNNOOPP"]'` |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl "https://api.modrinth.com/v2/versions?ids=%5B%22IIJJKKLL%22%2C%22MMNNOOPP%22%5D"
|
||
```
|
||
|
||
```js
|
||
const versionIds = ["IIJJKKLL", "MMNNOOPP"];
|
||
const url = new URL("https://api.modrinth.com/v2/versions");
|
||
url.searchParams.set("ids", JSON.stringify(versionIds));
|
||
const response = await fetch(url);
|
||
const versions = await response.json();
|
||
```
|
||
|
||
---
|
||
|
||
## 响应格式
|
||
|
||
### Version 对象结构
|
||
|
||
```json
|
||
{
|
||
"id": "IIJJKKLL",
|
||
"project_id": "AABBCCDD",
|
||
"author_id": "EEFFGGHH",
|
||
"name": "Version 1.0.0",
|
||
"version_number": "1.0.0",
|
||
"changelog": "## 更新内容\n\n- 修复了若干 Bug",
|
||
"date_published": "2025-01-01T00:00:00Z",
|
||
"downloads": 1024,
|
||
"version_type": "release",
|
||
"status": "listed",
|
||
"requested_status": null,
|
||
"game_versions": ["1.20.1", "1.20.4"],
|
||
"loaders": ["fabric"],
|
||
"featured": false,
|
||
"dependencies": [
|
||
{
|
||
"dependency_type": "required",
|
||
"project_id": "P7dR8mSH",
|
||
"version_id": null,
|
||
"file_name": null
|
||
}
|
||
],
|
||
"files": [
|
||
{
|
||
"hashes": {
|
||
"sha512": "93ecf5fe...",
|
||
"sha1": "c84dd4b3..."
|
||
},
|
||
"url": "https://cdn.modrinth.com/data/AABBCCDD/versions/1.0.0/my-mod-1.0.0.jar",
|
||
"filename": "my-mod-1.0.0.jar",
|
||
"primary": true,
|
||
"size": 1097270,
|
||
"file_type": null
|
||
},
|
||
{
|
||
"hashes": {
|
||
"sha512": "ab12cd34...",
|
||
"sha1": "ef56gh78..."
|
||
},
|
||
"url": "https://cdn.modrinth.com/data/AABBCCDD/versions/1.0.0/my-mod-1.0.0-sources.jar",
|
||
"filename": "my-mod-1.0.0-sources.jar",
|
||
"primary": false,
|
||
"size": 543210,
|
||
"file_type": "sources-jar"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 关键字段说明
|
||
|
||
#### Version 顶层字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | `string` | 版本唯一 ID(8 位 base62) |
|
||
| `project_id` | `string` | 所属项目 ID |
|
||
| `author_id` | `string` | 发布者用户 ID |
|
||
| `name` | `string` | **版本名称**(如 `"Version 1.0.0"`) |
|
||
| `version_number` | `string` | **版本号**(如 `"1.0.0"`,建议遵循语义化版本) |
|
||
| `changelog` | `string \| null` | 更新日志文本(若使用 `include_changelog=false` 则为 `null`) |
|
||
| `date_published` | `string` | 发布时间(ISO-8601 格式) |
|
||
| `downloads` | `integer` | 下载次数 |
|
||
| `version_type` | `string` | 发布渠道:`release`、`beta`、`alpha` |
|
||
| `status` | `string` | 版本状态:`listed`、`archived`、`draft`、`unlisted`、`scheduled` |
|
||
| `game_versions` | `string[]` | 支持的 Minecraft 版本列表 |
|
||
| `loaders` | `string[]` | 支持的加载器列表 |
|
||
| `featured` | `boolean` | 是否为精选版本 |
|
||
| `dependencies` | `object[]` | 依赖列表(结构见下方) |
|
||
| `files` | `object[]` | 该版本的所有文件列表 |
|
||
|
||
#### dependencies 数组项
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `dependency_type` | `string` | `required`、`optional`、`incompatible`、`embedded` |
|
||
| `project_id` | `string \| null` | 依赖的项目 ID |
|
||
| `version_id` | `string \| null` | 依赖的具体版本 ID |
|
||
| `file_name` | `string \| null` | 依赖文件名 |
|
||
|
||
#### files 数组项(最常需要关注的字段)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `filename` | `string` | **文件名**(如 `"my-mod-1.0.0.jar"`) |
|
||
| `url` | `string` | 文件直链下载地址 |
|
||
| `size` | `integer` | 文件大小(字节) |
|
||
| `primary` | `boolean` | 是否为主文件。每个版本最多一个主文件;若没有一个标记为 `true`,则推断第一个文件为主文件 |
|
||
| `hashes.sha1` | `string` | 文件的 SHA-1 哈希 |
|
||
| `hashes.sha512` | `string` | 文件的 SHA-512 哈希 |
|
||
| `file_type` | `string \| null` | 文件类型:`sources-jar`、`dev-jar`、`javadoc-jar`、`required-resource-pack`、`optional-resource-pack`、`unknown`、`signature`。普通主 jar 为 `null` |
|
||
|
||
---
|
||
|
||
## 常见使用场景
|
||
|
||
### 场景 1:获取项目的最新版本
|
||
|
||
从版本列表中取第一个(通常是时间最新的),再拿到文件信息:
|
||
|
||
```js
|
||
const projectSlug = "my-mod";
|
||
const response = await fetch(
|
||
`https://api.modrinth.com/v2/project/${projectSlug}/version?include_changelog=false`
|
||
);
|
||
const versions = await response.json();
|
||
|
||
const latest = versions[0];
|
||
console.log(`版本: ${latest.name} (${latest.version_number})`);
|
||
console.log(`主文件: ${latest.files.find(f => f.primary).filename}`);
|
||
```
|
||
|
||
### 场景 2:列出某版本的所有文件及其类型
|
||
|
||
```js
|
||
const versionId = "IIJJKKLL";
|
||
const response = await fetch(`https://api.modrinth.com/v2/version/${versionId}`);
|
||
const version = await response.json();
|
||
|
||
for (const file of version.files) {
|
||
const typeLabel = file.file_type ?? "主 jar";
|
||
console.log(`[${typeLabel}] ${file.filename} — ${file.url}`);
|
||
}
|
||
```
|
||
|
||
输出示例:
|
||
|
||
```
|
||
[主 jar] my-mod-1.0.0.jar — https://cdn.modrinth.com/.../my-mod-1.0.0.jar
|
||
[sources-jar] my-mod-1.0.0-sources.jar — https://cdn.modrinth.com/.../my-mod-1.0.0-sources.jar
|
||
```
|
||
|
||
### 场景 3:下载版本的主文件(通过直链)
|
||
|
||
```js
|
||
const version = await fetch("https://api.modrinth.com/v2/version/IIJJKKLL").then(r => r.json());
|
||
const primaryFile = version.files.find(f => f.primary) ?? version.files[0];
|
||
|
||
const fileBuffer = await fetch(primaryFile.url).then(r => r.arrayBuffer());
|
||
require("fs").writeFileSync(primaryFile.filename, Buffer.from(fileBuffer));
|
||
```
|
||
|
||
### 场景 4:仅获取特定加载器 + 游戏版本的版本
|
||
|
||
```js
|
||
const projectId = "AABBCCDD";
|
||
const url = new URL(`https://api.modrinth.com/v2/project/${projectId}/version`);
|
||
url.searchParams.set("loaders", JSON.stringify(["fabric"]));
|
||
url.searchParams.set("game_versions", JSON.stringify(["1.20.4"]));
|
||
url.searchParams.set("include_changelog", "false");
|
||
|
||
const versions = await fetch(url).then(r => r.json());
|
||
for (const v of versions) {
|
||
console.log(`${v.name} (${v.version_number}) — ${v.files.find(f => f.primary)?.filename}`);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 错误码
|
||
|
||
| 状态码 | 说明 |
|
||
|--------|------|
|
||
| `200` | 成功 |
|
||
| `404` | 项目不存在、版本不存在,或无权访问(如草稿版本) |
|
||
|
||
---
|
||
|
||
## 注意事项与最佳实践
|
||
|
||
### 1. 始终使用 `include_changelog=false`
|
||
|
||
除非你真的需要每个版本的 changelog 文本,否则务必传入 `include_changelog=false`。changelog 可能非常长,会显著增大响应体、降低请求速度。Modrinth 官方也强烈建议这样做。
|
||
|
||
### 2. 主文件的判断规则
|
||
|
||
`files` 数组中若有一个 `primary: true`,那就是主文件。如果一个都没有,则**推断第一个文件为主文件**。不要假定 `files[0]` 一定是主 jar——sources jar 也可能排在首位。
|
||
|
||
### 3. 版本列表的排序
|
||
|
||
`GET /project/{id|slug}/version` 返回的列表**按发布日期降序排列**(最新的在前)。若需确定顺序,请以 `date_published` 字段为准。
|
||
|
||
### 4. 别忘了 User-Agent
|
||
|
||
即使是公开 GET 请求,Modrinth 也要求设置 `User-Agent` 请求头:
|
||
|
||
```
|
||
User-Agent: your_username/your_project/1.0.0 (contact@example.com)
|
||
```
|
||
|
||
### 5. 通过 slug 访问更易读
|
||
|
||
项目标识符支持 slug(如 `my-mod`)而非只能用 ID(如 `AABBCCDD`),对于调试和可读性更有帮助。但 slug 可能被项目所有者修改,长期存储建议使用 ID。
|
||
|
||
### 6. 版本号可能不唯一
|
||
|
||
`GET /project/{id|slug}/version/{id\|number}` 在使用版本号查找时,若遇到重名只返回最旧的那个。精确获取请使用版本 ID。
|
||
|
||
### 7. 分页
|
||
|
||
`GET /project/{id|slug}/version` **不支持分页参数**,会一次性返回该项目所有版本。对于版本数量极多的项目,响应体可能较大,此时推荐结合 `loaders` 和 `game_versions` 过滤。
|
||
|
||
---
|
||
|
||
## 可用加载器与游戏版本查询
|
||
|
||
如果你不确定 `loaders` 或 `game_versions` 过滤参数应填什么值,可以通过标签接口查询所有合法值:
|
||
|
||
```bash
|
||
curl "https://api.modrinth.com/v2/tag/loader"
|
||
curl "https://api.modrinth.com/v2/tag/game_version"
|
||
```
|
||
|
||
---
|
||
|
||
## 参考
|
||
|
||
- [Modrinth API 文档](https://docs.modrinth.com)
|
||
- [OpenAPI 规范文件](openapi.yml)
|
||
- [新建版本 API 文档](upload.md)
|