> For the complete documentation index, see [llms.txt](https://wiki1.yemapt.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki1.yemapt.org/developer/open-api.md).

# 开放API

更新时间：2026-08-13

## 接口总览

| Method | URI                                                  | 用途                   |
| ------ | ---------------------------------------------------- | -------------------- |
| `POST` | `/openApi/user/fetchBasicInfo.json`                  | 获取当前API用户的基本信息       |
| `POST` | `/openApi/user/authenticate.json`                    | 获取本站对用户身份挑战值的RSA签名   |
| `POST` | `/openApi/torrent/fetchTorrentIdWithPiecesHash.json` | 批量根据piecesHash查询种子ID |
| `POST` | `/openApi/torrent/fetchOpenTorrentList.json`         | 分页查询公开种子列表           |
| `POST` | `/openApi/torrent/generateDownloadKey.json`          | 生成临时种子下载凭证           |
| `POST` | `/openApi/torrent/uploadTorrent.json`                | 上传种子，可用于第三方系统转种      |

## 认证方式

开放API接口URI均以 **`/openApi/`** 开头。请求Header中的 `Authorization` 应直接填写API AuthKey，不要添加 `Bearer` 前缀。

API AuthKey需要在个人详情页创建，有效期为180天，每个用户最多同时保留3个有效AuthKey。用户可以在个人详情页删除AuthKey，删除后立即失效。请勿在URL、日志或公开代码中暴露AuthKey。

调用示例：

```javascript
// node javascript
fetch("https://www.yemapt.org/openApi/xxxxxxxxx", {
  "headers": {
    "Authorization": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  }
});
```

```bash
# bash
curl 'https://www.yemapt.org/openApi/xxxxxxxxx' \
 -H 'Authorization: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
```

Cookie中的登录auth不能用于开放API。如果在 `Authorization` 中传入Cookie auth，接口会返回：

```json
{
    "success": false,
    "showType": 2,
    "errorCode": 403,
    "errorMessage": "need api auth"
}
```

## 通用响应

除下载种子文件的接口外，开放API均返回 `ResultDTO` 格式的JSON。业务调用是否成功应以 `success` 为准，不要只依赖HTTP状态码。

成功响应：

```json
{
    "success": true,
    "showType": 0,
    "data": {}
}
```

失败响应：

```json
{
    "success": false,
    "showType": 2,
    "errorCode": 2401,
    "errorMessage": "参数异常"
}
```

常见错误码：

| errorCode | 说明                                |
| --------- | --------------------------------- |
| `400`     | 未提供AuthKey，或AuthKey格式异常、签名无效、已经过期 |
| `402`     | 当前用户没有访问相关资源的权限                   |
| `403`     | 使用的不是API AuthKey，或API AuthKey已被删除 |
| `1402`    | 当前接口要求用户先完成邮箱验证                   |
| `2401`    | 请求参数或业务校验不通过，具体原因见 `errorMessage` |
| `500`     | 系统内部异常；反馈问题时请同时提供响应中的traceId信息    |

## 1. 用户

### 1.1 获取用户基本信息

<mark style="color:green;">`POST`</mark> `/openApi/user/fetchBasicInfo.json`

原 `GET /openApi/user/fetchBasicInfo.json` 已删除，不再提供兼容。请使用上述POST接口。

<mark style="color:green;">`响应结果`</mark>

```json
{
    "success": true,
    "showType": 0,
    "data": {
        "id": 10,
        "name": "abcde",
        "avatar": "https://img.yemapt.org/avatar/97/97d77c955bf14b0c8807020755ebd8a0.png",
        "bonus": 1000000,
        "level": 7,
        "status": "enable",
        "invitedNum": 100,
        "availableInviteNum": 100,
        "registerTime": "2024-05-01T00:00:00.000+00:00",
        "promotionUploadSize": 1000000,
        "promotionDownloadSize": 1000000,
        "admin": false
    }
}
```

主要字段说明：

| 字段                      | 类型      | 说明                      |
| ----------------------- | ------- | ----------------------- |
| `id`                    | Long    | 用户ID                    |
| `name`                  | String  | 用户名                     |
| `avatar`                | String  | 用户上传头像的完整URL，或系统生成的头像标识 |
| `bonus`                 | Long    | 用户积分                    |
| `level`                 | Integer | 用户等级                    |
| `status`                | String  | 用户状态                    |
| `invitedNum`            | Long    | 已邀请用户数量                 |
| `availableInviteNum`    | Long    | 当前可用邀请数量                |
| `registerTime`          | Date    | 注册时间，ISO 8601格式         |
| `promotionUploadSize`   | Long    | 促销上传量，单位为字节             |
| `promotionDownloadSize` | Long    | 促销下载量，单位为字节             |
| `admin`                 | Boolean | 是否为管理员                  |

备注：用户上传头像后，`avatar`直接返回以 `https://img.yemapt.org/avatar/` 开头的完整URL，无需再拼接域名；如果返回的是32位随机字符串，则需要使用 [Multiavatar](https://github.com/multiavatar) 转换。该组件提供JavaScript、PHP和Python工具包。

### 1.2 校验是否为本站用户

用于第三方系统校验用户提交的auth是否正常，以及获取对应的uid，此功能采用RSA签名技术。

当前使用的publicKey：

{% code overflow="wrap" fullWidth="false" %}

```
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm6OpYYWpF5Js8SWtuAXGZ1iWGsADHSDhdkz9wDQYuvRB3SW2xGSQpwYB7B7Bn6ZfoXtxhMm2v4JzwTe3qZioWmwgyweCyv7FIjvsdYIhAHMj7v7jI7zq0Xn9F6CjBMM0AWtCmhhH/eFNxICiCucVGqa6Z0hf5OcAWefPHIOdtMbWp+4fqkjWc7EuEjfqFr2eDy9kHqZWFpuByQa9jiF4v9HzLfoO/UwqBheYkNSLgoTRQ6sSF1bHlDC8yq3l4d/6fsQ7mZPJzWBf2vlohmOVpjy6s4Z+qtNpWsJhrLW9au49+1eYadKpNLR10izG5boKn+z9i5P/tRQ8WNkZELN2OwIDAQAB
```

{% endcode %}

<mark style="color:green;">`POST`</mark> `/openApi/user/authenticate.json`

<mark style="color:green;">`Header`</mark> `Content-Type: application/json`

<mark style="color:green;">`Body`</mark>

```json
{
    "publicKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "randomContent": "12345678123456781234567812345678"
}
```

备注：

* `publicKey`务必使用当前Wiki中展示的Key。公钥可能轮换，接口返回“publicKey已失效”时应重新读取本文档中的最新值。
* `randomContent`必须为32个字符。建议每次请求都生成新的随机值，例如使用UUID并移除其中的 `-`。
* 验证方应同时校验RSA签名、返回的 `userId` 和本次提交的 `randomContent`，并避免重复接受相同的随机值。

<mark style="color:green;">`响应结果`</mark>

```json
{
    "success": true,
    "showType": 0,
    "data": {
        "userId": 100,
        "signType": "rsa-sha256",
        "publicKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "signature": "OOOOOOOOOOOOOOOOOOOOOOOOOOOO"
    }
}
```

备注：

签名数据使用UTF-8编码，格式为“用户ID、制表符、randomContent”，即：

```java
String data = "{userId}\t{randomContent}"
                .replace("userId","100")
                .replace("randomContent","12345678123456781234567812345678");
```

示例代码：

python：

```python
from base64 import b64decode
import rsa

data = "100\t12345678123456781234567812345678"
publicKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
signature = "OOOOOOOOOOOOOOOOOOOOOOOOOOOO"

PUB = '''
-----BEGIN PUBLIC KEY-----
{publicKey}
-----END PUBLIC KEY-----
'''.format(publicKey=publicKey)

try:
    signType = rsa.verify(data.encode(), b64decode(signature), rsa.PublicKey.load_pkcs1_openssl_pem(PUB))
    print(signType)
except rsa.pkcs1.VerificationError:
    print("verification failed")
```

java:

```java
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;


public static boolean rsaValidate(String publicKeyStr, String sign, String data) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
    PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(
            new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr)));

    Signature verify = Signature.getInstance("SHA256withRSA");
    verify.initVerify(publicKey);
    verify.update(data.getBytes());
    return verify.verify(Base64.getDecoder().decode(sign));
}
```

## 2. 种子

### 2.1 根据piecesHash获取种子id

<mark style="color:green;">`POST`</mark> `/openApi/torrent/fetchTorrentIdWithPiecesHash.json`

<mark style="color:green;">`Header`</mark> `Content-Type: application/json`

<mark style="color:green;">`Body`</mark>

```json
{
    "piecesHashList": [
        "e9f3f5dd32abasdfghfea4d43d32559cf0309764",
        "e9f3f5dd32ab123456fea4d43d32559cf0309764"
    ]
}
```

参数说明：

* `piecesHashList`数组长度不能超过100。
* 空数组会返回空Map，不会返回参数错误。
* piecesHash通常是对种子 `info.pieces` 内容计算得到的40位SHA-1十六进制字符串；无匹配种子的Hash不会出现在响应结果中。

<mark style="color:green;">`响应结果`</mark>

```json
{
    "success": true,
    "showType": 0,
    "data": {
        "e9f3f5dd32abasdfghfea4d43d32559cf0309764": 100
    }
}
```

### 2.2 查询公开种子列表

此接口与站内页面使用的 `/api/torrent/fetchOpenTorrentList` 查询能力一致，供第三方系统分页查询已发布的公开种子。

<mark style="color:green;">`POST`</mark> `/openApi/torrent/fetchOpenTorrentList.json`

<mark style="color:green;">`Header`</mark> `Content-Type: application/json`

<mark style="color:green;">`Body`</mark>

```json
{
    "keyword": "关键词",
    "categoryId": 1,
    "downloadPromotionType": "free",
    "pageParam": {
        "current": 1,
        "pageSize": 20
    },
    "sorter": {
        "field": "listingTime",
        "order": "descend"
    }
}
```

请求参数说明：

* `keyword`：可选，同时匹配种子标题和副标题，长度必须小于128个字符。
* `categoryId`：可选，种子类目ID；查询受限类目时，API auth对应的用户必须拥有相应权限。
* `uploadPromotionType`：可选，上传促销类型，可用值为 `none`、`one_half`、`double_upload`。
* `downloadPromotionType`：可选，下载促销类型，可用值为 `none`、`half`、`free`。
* `pageParam`：必填；`current`按页码从1开始，最大为1000；`pageSize`必须大于0且最大为40。
* `sorter`：可选；`order`可用值为 `ascend`、`descend`。不传时按照置顶状态和发布时间倒序排列。

`sorter.field`支持以下值：

* `id`、`torrentSize`、`fileSize`、`fileNum`
* `torrentCommentNum`、`torrentViewNum`、`torrentDownloadNum`
* `leechNum`、`seedNum`、`completedNum`、`downloadUserNum`
* `status`、`listingTime`、`gmtCreate`、`gmtModified`
* `uploadPromotionEndTime`、`downloadPromotionEndTime`、`reportNum`

<mark style="color:green;">`响应结果`</mark>

以下响应仅展示主要字段。实际响应还可能包含当前用户信息、种子媒体属性以及以后新增的兼容字段，对接系统应忽略不认识的字段，并允许可选字段为 `null` 或不返回。

```json
{
    "success": true,
    "showType": 0,
    "data": [
        {
            "id": 100,
            "showName": "种子标题",
            "shortDesc": "种子副标题",
            "categoryId": 1,
            "categoryName": "电影",
            "fileSize": 1073741824,
            "seedNum": 10,
            "leechNum": 2,
            "uploadPromotion": "none",
            "downloadPromotion": "free",
            "listingTime": "2026-08-02T08:00:00.000+00:00",
            "collect": false
        }
    ]
}
```

主要字段说明：

| 字段                         | 类型      | 说明                             |
| -------------------------- | ------- | ------------------------------ |
| `id`                       | Long    | 种子ID                           |
| `showName`                 | String  | 种子标题                           |
| `shortDesc`                | String  | 种子副标题                          |
| `categoryId`               | Long    | 类目ID                           |
| `categoryKey`              | String  | 包含父子层级的类目标识                    |
| `categoryName`             | String  | 类目名称                           |
| `categoryAvatar`           | String  | 类目图标                           |
| `picture`                  | String  | 种子预览图路径                        |
| `fileSize`                 | Long    | 种子内容总大小，单位为字节                  |
| `seedNum`                  | Integer | 当前做种数量                         |
| `leechNum`                 | Integer | 当前下载数量                         |
| `listingTime`              | Date    | 发布时间，ISO 8601格式；具体时区以响应中的偏移量为准 |
| `isTopping`                | String  | 是否置顶，枚举值为 `y`、`n`              |
| `uploadPromotion`          | String  | 上传促销类型                         |
| `uploadPromotionEndTime`   | Date    | 上传促销结束时间                       |
| `downloadPromotion`        | String  | 下载促销类型                         |
| `downloadPromotionEndTime` | Date    | 下载促销结束时间                       |
| `hrPunishEnable`           | Boolean | 是否启用HR考察                       |
| `userInfo`                 | Object  | 发种用户的展示信息；匿名发布时不会暴露真实身份        |
| `collect`                  | Boolean | 当前API用户是否已收藏                   |
| `userTorrentInfo`          | Object  | 当前API用户对该种子的下载量及做种、下载状态        |

接口只返回状态为 `enable` 的种子，目前不提供配套的总数接口。无符合条件的数据或分页参数超出限制时，`data`返回空数组。对接方可以逐页请求；当返回数量小于 `pageSize` 时，即可认为已经到达当次查询结果的最后一页。分页期间种子数据可能发生变化，对接方应使用种子 `id` 去重。

### 2.3 生成种子下载凭证

第三方系统不能直接使用开放API的 `Authorization` 下载种子文件，需要先为指定种子生成临时下载凭证，再使用凭证下载 `.torrent` 文件。

#### 2.3.1 生成凭证

<mark style="color:green;">`POST`</mark> `/openApi/torrent/generateDownloadKey.json?id={torrentId}`

请求参数说明：

* `id`：必填，需要下载的种子ID。
* 请求Header中必须携带开放API的 `Authorization`。

请求示例：

```bash
curl -X POST 'https://www.yemapt.org/openApi/torrent/generateDownloadKey.json?id=100' \
 -H 'Authorization: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
```

<mark style="color:green;">`响应结果`</mark>

```json
{
    "success": true,
    "showType": 0,
    "data": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
```

`data`即种子下载凭证，有效期为30分钟。生成凭证时会校验当前API用户是否拥有该种子的下载权限；种子不存在或没有下载权限时，接口返回失败。

原 `GET /openApi/torrent/generateDownloadKey.json` 和 `GET /openApi/torrent/generateDownloadKey` 均已删除，不再提供兼容。请使用带 `.json` 后缀的POST接口。

#### 2.3.2 使用凭证下载种子

<mark style="color:green;">`GET`</mark> `/api/torrent/download1?token={downloadKey}`

此下载接口不需要携带 `Authorization`。下载凭证是Base64字符串，可能包含 `+`、`/`、`=` 等字符，作为查询参数使用前必须进行URL编码。

JavaScript示例：

```javascript
const downloadUrl = "https://www.yemapt.org/api/torrent/download1?token="
    + encodeURIComponent(downloadKey);
window.location.href = downloadUrl;
```

cURL示例：

```bash
curl --get 'https://www.yemapt.org/api/torrent/download1' \
 --data-urlencode 'token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' \
 --output download.torrent
```

下载成功时，接口返回 `application/x-bittorrent` 类型的种子文件，而不是JSON。凭证已过期、内容异常、用户被禁用、用户passkey发生变化或下载权限发生变化时，接口返回JSON格式的错误信息。

{% hint style="warning" %}
下载凭证与生成凭证的用户及种子绑定。下载得到的种子文件包含该用户的个人Tracker信息，请勿共享凭证或下载后的种子文件。
{% endhint %}

### 2.4 上传种子

第三方系统可以通过此接口上传 `.torrent` 文件并创建种子，可用于自动转种。上传操作计入API AuthKey所属用户的发种数量，并使用该用户的发种权限。

<mark style="color:green;">`POST`</mark> `/openApi/torrent/uploadTorrent.json`

<mark style="color:green;">`Header`</mark> `Content-Type: multipart/form-data`

请求Header中必须携带开放API的 `Authorization`。请求体不是JSON，种子文件和种子信息都需要作为multipart表单字段提交。

请求参数说明：

| 字段                    | 类型        | 必填 | 说明                                         |
| --------------------- | --------- | -- | ------------------------------------------ |
| `file`                | File      | 是  | 需要上传的 `.torrent` 文件                        |
| `showName`            | String    | 是  | 种子标题，最长512个字符，不能包含换行                       |
| `shortDesc`           | String    | 是  | 种子副标题，最长512个字符，不能包含换行                      |
| `categoryId`          | Long      | 是  | 种子类目ID；受限类目要求当前用户拥有对应的上传权限                 |
| `uploadUserAnonymous` | String    | 是  | 是否匿名发布，可用值为 `y`、`n`                        |
| `longDesc`            | String    | 否  | 种子描述，支持Markdown，不允许使用 `data:image` 内嵌图片    |
| `picture`             | String    | 否  | 预览图的HTTP或HTTPS完整URL，最长512个字符               |
| `mediaInfo`           | String    | 否  | MediaInfo文本                                |
| `imdb`                | String    | 否  | IMDb数字ID，不能带 `tt` 前缀，例如 `0111161`          |
| `season`              | Integer   | 否  | 季编号，剧集类资源可与 `imdb` 一起提交                    |
| `douban`              | String    | 否  | 豆瓣条目ID，例如 `1292052`                        |
| `medium`              | String    | 否  | 媒介选项值                                      |
| `standard`            | String    | 否  | 分辨率选项值                                     |
| `codec`               | String    | 否  | 视频编码选项值                                    |
| `audiocodec`          | String    | 否  | 音频编码选项值                                    |
| `regionList`          | String\[] | 否  | 地区选项值，最多3个；多个值使用同名表单字段重复提交                 |
| `team`                | String    | 否  | 制作组选项值                                     |
| `tagList`             | String\[] | 否  | 标签选项值；多个值使用同名表单字段重复提交                      |
| `screenshotList`      | String\[] | 否  | 截图的HTTP或HTTPS完整URL，最多20个；多个值使用同名表单字段重复提交   |
| `hrPunishEnable`      | Boolean   | 否  | 是否启用HR考察，默认为 `false`；本站关闭HR设置功能时不能传 `true` |

`longDesc`、`screenshotList`、`imdb` 和 `douban` 至少需要填写一项。媒介、分辨率、编码、地区、制作组和标签的选项值参见[枚举值说明](https://wiki1.yemapt.org/developer/pages/5ckEHIiZ0LIYL7FvK5z9#种子)。类目ID可在站内发种页面的类目选项中查看。

数组字段应重复提交同名字段，不要将数组序列化成JSON字符串。例如两个地区应提交两次 `regionList`：

```
regionList=1
regionList=4
```

IMDb页面地址中的ID通常带有 `tt` 前缀，提交前必须移除此前缀。例如 `https://www.imdb.com/title/tt0111161/` 应提交为 `0111161`。

#### cURL

```bash
curl -X POST 'https://www.yemapt.org/openApi/torrent/uploadTorrent.json' \
 -H 'Authorization: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
 -F 'file=@/path/to/example.torrent;type=application/x-bittorrent' \
 -F 'showName=The Shawshank Redemption 1994 BluRay 1080p' \
 -F 'shortDesc=肖申克的救赎 / 1080p BluRay' \
 -F 'categoryId=1' \
 -F 'uploadUserAnonymous=n' \
 -F 'imdb=0111161' \
 -F 'douban=1292052' \
 -F 'medium=2' \
 -F 'standard=4' \
 -F 'codec=4' \
 -F 'audiocodec=4' \
 -F 'regionList=4' \
 -F 'tagList=6' \
 -F 'longDesc=种子描述'
```

#### Python

以下示例使用 `requests`。列表字段通过元组列表重复提交同名字段。

```python
import requests

url = "https://www.yemapt.org/openApi/torrent/uploadTorrent.json"
headers = {
    "Authorization": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
data = [
    ("showName", "The Shawshank Redemption 1994 BluRay 1080p"),
    ("shortDesc", "肖申克的救赎 / 1080p BluRay"),
    ("categoryId", "1"),
    ("uploadUserAnonymous", "n"),
    ("imdb", "0111161"),
    ("douban", "1292052"),
    ("medium", "2"),
    ("standard", "4"),
    ("codec", "4"),
    ("audiocodec", "4"),
    ("regionList", "4"),
    ("tagList", "6"),
    ("longDesc", "种子描述")
]

with open("/path/to/example.torrent", "rb") as torrent_file:
    files = {
        "file": ("example.torrent", torrent_file, "application/x-bittorrent")
    }
    response = requests.post(url, headers=headers, data=data, files=files, timeout=60)

response.raise_for_status()
result = response.json()
if not result.get("success"):
    raise RuntimeError(result.get("errorMessage", "上传失败"))
print(result["data"])
```

#### PHP

```php
<?php
$url = 'https://www.yemapt.org/openApi/torrent/uploadTorrent.json';
$fields = [
    'file' => new CURLFile(
        '/path/to/example.torrent',
        'application/x-bittorrent',
        'example.torrent'
    ),
    'showName' => 'The Shawshank Redemption 1994 BluRay 1080p',
    'shortDesc' => '肖申克的救赎 / 1080p BluRay',
    'categoryId' => '1',
    'uploadUserAnonymous' => 'n',
    'imdb' => '0111161',
    'douban' => '1292052',
    'medium' => '2',
    'standard' => '4',
    'codec' => '4',
    'audiocodec' => '4',
    'regionList' => '4',
    'tagList' => '6',
    'longDesc' => '种子描述'
];

$curl = curl_init($url);
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
    ],
    CURLOPT_POSTFIELDS => $fields,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 60
]);
$response = curl_exec($curl);
if ($response === false) {
    throw new RuntimeException(curl_error($curl));
}
curl_close($curl);

$result = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
if (!$result['success']) {
    throw new RuntimeException($result['errorMessage'] ?? '上传失败');
}
echo $result['data'] . PHP_EOL;
```

#### JavaScript（Node.js 18+）

使用 `FormData` 时不要手动设置 `Content-Type`，运行时会自动生成包含boundary的Header。

```javascript
import { readFile } from "node:fs/promises";

const torrentBytes = await readFile("/path/to/example.torrent");
const torrentBlob = new Blob([torrentBytes], {
  type: "application/x-bittorrent"
});
const formData = new FormData();
formData.append("file", torrentBlob, "example.torrent");
formData.append("showName", "The Shawshank Redemption 1994 BluRay 1080p");
formData.append("shortDesc", "肖申克的救赎 / 1080p BluRay");
formData.append("categoryId", "1");
formData.append("uploadUserAnonymous", "n");
formData.append("imdb", "0111161");
formData.append("douban", "1292052");
formData.append("medium", "2");
formData.append("standard", "4");
formData.append("codec", "4");
formData.append("audiocodec", "4");
formData.append("regionList", "4");
formData.append("tagList", "6");
formData.append("longDesc", "种子描述");

const response = await fetch(
  "https://www.yemapt.org/openApi/torrent/uploadTorrent.json",
  {
    method: "POST",
    headers: {
      Authorization: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    },
    body: formData
  }
);
if (!response.ok) {
  throw new Error(`HTTP ${response.status}`);
}
const result = await response.json();
if (!result.success) {
  throw new Error(result.errorMessage ?? "上传失败");
}
console.log(result.data);
```

<mark style="color:green;">`响应结果`</mark>

```json
{
    "success": true,
    "showType": 0,
    "data": 100
}
```

`data`为新创建的种子ID。是否直接发布由当前用户的发种权限和类目权限决定；没有直接发布权限时，种子会进入与站内发种相同的候选审核流程，响应格式不变。

接口会执行与站内发种相同的校验，包括全站发种开关、用户积分、每日发种上限、类目权限、种子文件格式、infoHash和piecesHash重复检查。校验失败时，接口返回通用失败响应，具体原因见 `errorMessage`。上传成功后，对接方应妥善保存返回的种子ID；网络超时且无法确认结果时，建议先调用 `fetchTorrentIdWithPiecesHash.json` 检查种子是否已经创建，再决定是否重试。

## 变更记录

| 日期         | 变更内容                                                                                                                                               |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| 2026-08-13 | 增加上传种子接口 `/openApi/torrent/uploadTorrent.json` 的说明，补充多语言调用示例; 删除 `fetchBasicInfo` 和 `generateDownloadKey` 的旧GET接口，不再提供兼容                           |
| 2026-08-02 | 增加公开种子列表和种子下载凭证接口说明；新增 `/openApi/torrent/generateDownloadKey.json`；将 `fetchBasicInfo` 和 `generateDownloadKey.json` 调整为POST接口；补充认证、通用响应、错误码、字段与分页规则 |
