Add TMDB search and media detail pages, HDHive resource ingestion flow, unified error handling, Docker single-container runtime, and project docs/config updates for local deployment. Co-authored-by: Cursor <cursoragent@cursor.com>
519 lines
15 KiB
Markdown
519 lines
15 KiB
Markdown
# 接口列表
|
||
|
||
OpenAPI 分为两类接口:
|
||
|
||
- **用户授权接口**:以 `/api/public/openapi/oauth` 为前缀,用于授权预览、确认授权、换取 Token 和撤销 Token。
|
||
- **业务接口**:以 `/api/open` 为前缀,请求必须携带 `X-API-Key`。需要代表具体用户执行的接口,还应携带用户 Access Token;个人 API Key 或绑定用户的应用可回退到绑定用户。
|
||
|
||
## 接口总览
|
||
|
||
### 用户授权接口
|
||
|
||
| 方法 | 路径 | 认证 | 说明 |
|
||
|---|---|---|---|
|
||
| GET | `/api/public/openapi/oauth/authorize` | 站内登录 Cookie | 授权页预览信息 |
|
||
| POST | `/api/public/openapi/oauth/authorize` | 站内登录 Cookie | 用户确认授权并生成授权码 |
|
||
| POST | `/api/public/openapi/oauth/token` | `X-API-Key` 应用 Secret | 授权码或刷新令牌换取用户 Token |
|
||
| POST | `/api/public/openapi/oauth/revoke` | `X-API-Key` 应用 Secret | 撤销刷新令牌 |
|
||
|
||
### 业务接口
|
||
|
||
| scope | 方法 | 路径 | 说明 |
|
||
|---|---|---|---|
|
||
| `meta` | GET | `/api/open/ping` | 健康检查 |
|
||
| `meta` | GET | `/api/open/quota` | 查询当前凭证配额状态 |
|
||
| `meta` | GET | `/api/open/usage` | 查询历史用量 |
|
||
| `meta` | GET | `/api/open/usage/today` | 查询今日用量 |
|
||
| `query` | GET | `/api/open/resources/:type/:tmdb_id` | 根据 TMDB ID 获取资源列表 |
|
||
| `query` | GET | `/api/open/shares/:slug` | 获取分享详情 |
|
||
| `query` | POST | `/api/open/check/resource` | 检查资源链接类型 |
|
||
| `unlock` | POST | `/api/open/resources/unlock` | 解锁资源 |
|
||
| `write` | GET | `/api/open/shares` | 获取我的分享列表 |
|
||
| `write` | POST | `/api/open/shares` | 创建分享 |
|
||
| `write` | PATCH | `/api/open/shares/:slug` | 更新分享 |
|
||
| `write` | DELETE | `/api/open/shares/:slug` | 删除分享 |
|
||
| `vip` | GET | `/api/open/me` | 获取当前用户信息 |
|
||
| `vip` | POST | `/api/open/checkin` | 每日签到 |
|
||
| `vip` | GET | `/api/open/vip/weekly-free-quota` | 获取长期 Premium 每周免费解锁状态 |
|
||
|
||
---
|
||
|
||
## 用户授权流程接口
|
||
|
||
第三方应用的用户授权入口应使用前端页面:
|
||
|
||
```text
|
||
GET /openapi/authorize?client_id=app_xxx&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&scope=query%20unlock&state=opaque-state
|
||
```
|
||
|
||
前端页面会要求用户登录,并调用下面的后端授权接口。
|
||
|
||
---
|
||
|
||
## GET /api/public/openapi/oauth/authorize
|
||
|
||
获取授权页展示信息。该接口需要站内登录 Cookie;未登录会返回 `401`,前端授权页会跳转到登录页。
|
||
|
||
### Query 参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| `client_id` | string | 是 | OpenAPI 应用公开 Client ID |
|
||
| `redirect_uri` | string | 是 | 授权完成回调地址,必须在应用配置中 |
|
||
| `scope` | string | 否 | 请求 scope,空格分隔,例如 `query unlock` |
|
||
| `state` | string | 否 | 第三方应用自定义状态 |
|
||
|
||
### 成功响应字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `data.client_id` | string | 应用 Client ID |
|
||
| `data.app_name` | string | 应用名称 |
|
||
| `data.description` | string | 应用描述 |
|
||
| `data.auth_level` | string | 应用授权等级 |
|
||
| `data.redirect_uri` | string | 本次授权回调地址 |
|
||
| `data.requested_scopes` | string[] | 本次请求 scope |
|
||
| `data.allowed_scopes` | string[] | 应用实际允许 scope |
|
||
| `data.user` | object | 当前登录用户摘要 |
|
||
| `data.expires_in` | integer | 授权码有效期秒数 |
|
||
|
||
---
|
||
|
||
## POST /api/public/openapi/oauth/authorize
|
||
|
||
用户确认授权并生成授权码。该接口需要站内登录 Cookie。
|
||
|
||
该接口本身返回 JSON 给 HDHive 前端授权页。HDHive 前端收到 `data.code` 后,会重定向到第三方 `redirect_uri`,并追加 `code` 和原始 `state`:
|
||
|
||
```text
|
||
https://client.example.com/callback?code=authorization-code&state=opaque-state
|
||
```
|
||
|
||
### Body 参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| `client_id` | string | 是 | OpenAPI 应用公开 Client ID |
|
||
| `redirect_uri` | string | 是 | 授权完成回调地址 |
|
||
| `scope` | string | 否 | 请求 scope,空格分隔 |
|
||
| `state` | string | 否 | 第三方应用自定义状态 |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -X POST https://hdhive.com/api/public/openapi/oauth/authorize \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{
|
||
"client_id": "app_xxx",
|
||
"redirect_uri": "https://client.example.com/callback",
|
||
"scope": "query unlock",
|
||
"state": "opaque-state"
|
||
}'
|
||
```
|
||
|
||
### 成功响应
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"code": "200",
|
||
"message": "success",
|
||
"data": {
|
||
"code": "authorization-code",
|
||
"redirect_uri": "https://client.example.com/callback",
|
||
"expires_in": 600
|
||
}
|
||
}
|
||
```
|
||
|
||
第三方应用通过自己的回调地址收到授权码后,应在服务端用应用 Secret 换取用户 Token。
|
||
|
||
---
|
||
|
||
## POST /api/public/openapi/oauth/token
|
||
|
||
使用授权码或刷新令牌换取 OpenAPI 用户 Token。该接口必须携带 OpenAPI 应用 Secret。
|
||
|
||
`redirect_uri` 只在 `authorization_code` 模式下需要。它不是跳转地址,而是授权码校验字段,必须与用户授权阶段传入的 `redirect_uri` 完全一致;后端会同时校验授权码、应用 Secret 和 `redirect_uri` 的绑定关系。
|
||
|
||
### Header
|
||
|
||
```http
|
||
X-API-Key: app-secret
|
||
Content-Type: application/json
|
||
```
|
||
|
||
### authorization_code Body
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| `grant_type` | string | 是 | 固定为 `authorization_code` |
|
||
| `code` | string | 是 | 用户确认授权后得到的授权码 |
|
||
| `redirect_uri` | string | 是 | 安全校验字段,必须与授权码创建时传入的回调地址完全一致;不会触发跳转 |
|
||
|
||
### refresh_token Body
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| `grant_type` | string | 是 | 固定为 `refresh_token` |
|
||
| `refresh_token` | string | 是 | 刷新令牌 |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -X POST https://hdhive.com/api/public/openapi/oauth/token \\
|
||
-H "X-API-Key: app-secret" \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{
|
||
"grant_type": "authorization_code",
|
||
"code": "authorization-code",
|
||
"redirect_uri": "https://client.example.com/callback"
|
||
}'
|
||
```
|
||
|
||
### 成功响应字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `data.access_token` | string | OpenAPI 用户 Access Token |
|
||
| `data.refresh_token` | string | Refresh Token,刷新时可能返回新值 |
|
||
| `data.token_type` | string | 固定为 `Bearer` |
|
||
| `data.expires_in` | integer | Access Token 有效期秒数 |
|
||
| `data.refresh_expires_in` | integer | Refresh Token 有效期秒数 |
|
||
| `data.scope` | string | 空格分隔 scope |
|
||
| `data.scopes` | string[] | scope 数组 |
|
||
|
||
---
|
||
|
||
## POST /api/public/openapi/oauth/revoke
|
||
|
||
撤销某个 Refresh Token。撤销后该刷新令牌不能再换取新的用户 Access Token。
|
||
|
||
### Header
|
||
|
||
```http
|
||
X-API-Key: app-secret
|
||
Content-Type: application/json
|
||
```
|
||
|
||
### Body 参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| `refresh_token` | string | 是 | 要撤销的刷新令牌 |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -X POST https://hdhive.com/api/public/openapi/oauth/revoke \\
|
||
-H "X-API-Key: app-secret" \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{"refresh_token": "refresh-token"}'
|
||
```
|
||
|
||
---
|
||
|
||
## GET /api/open/ping
|
||
|
||
健康检查接口,用于验证 API Key 是否有效。
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -H "X-API-Key: your-api-key" https://hdhive.com/api/open/ping
|
||
```
|
||
|
||
### 成功响应
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"code": "200",
|
||
"message": "success",
|
||
"data": {
|
||
"message": "pong",
|
||
"api_key_id": 1,
|
||
"name": "My App"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## GET /api/open/quota
|
||
|
||
查询当前 API Key 的配额状态。该接口用于展示服务端返回的当前状态,不应在客户端写死限制值。
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -H "X-API-Key: your-api-key" https://hdhive.com/api/open/quota
|
||
```
|
||
|
||
### 响应字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `data.daily_reset` | integer | 配额重置时间 |
|
||
| `data.endpoint_limit` | integer / null | 当前接口限制状态,未配置时为空 |
|
||
| `data.endpoint_remaining` | integer / null | 当前接口剩余状态,未配置时为空 |
|
||
|
||
---
|
||
|
||
## GET /api/open/usage
|
||
|
||
查询当前 API Key 的历史用量统计。
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 位置 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|---|
|
||
| `start_date` | query | string | 否 | 开始日期,格式 `YYYY-MM-DD` |
|
||
| `end_date` | query | string | 否 | 结束日期,格式 `YYYY-MM-DD` |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -H "X-API-Key: your-api-key" \\
|
||
"https://hdhive.com/api/open/usage?start_date=2026-04-01&end_date=2026-04-25"
|
||
```
|
||
|
||
### 响应字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `data.daily_stats` | array | 每日调用统计 |
|
||
| `data.endpoint_stats` | array | 按接口聚合的统计 |
|
||
| `data.summary` | object | 汇总统计 |
|
||
|
||
---
|
||
|
||
## GET /api/open/resources/:type/:tmdb_id
|
||
|
||
根据媒体类型和 TMDB ID 获取资源列表。
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 位置 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|---|
|
||
| `type` | path | string | 是 | 媒体类型,`movie` 或 `tv` |
|
||
| `tmdb_id` | path | string | 是 | TMDB ID |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -H "X-API-Key: your-api-key" \\
|
||
-H "Authorization: Bearer user-access-token" \\
|
||
https://hdhive.com/api/open/resources/movie/550
|
||
```
|
||
|
||
### 响应字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `data[].slug` | string | 资源唯一标识 |
|
||
| `data[].title` | string / null | 资源标题 |
|
||
| `data[].pan_type` | string / null | 网盘类型 |
|
||
| `data[].share_size` | string / null | 分享文件大小 |
|
||
| `data[].video_resolution` | string[] | 视频分辨率 |
|
||
| `data[].source` | string[] | 片源 |
|
||
| `data[].subtitle_language` | string[] | 字幕语言 |
|
||
| `data[].subtitle_type` | string[] | 字幕类型 |
|
||
| `data[].unlock_points` | integer / null | 解锁所需积分 |
|
||
| `data[].is_unlocked` | boolean | 当前用户是否已解锁 |
|
||
| `data[].user` | object / null | 分享者信息 |
|
||
| `meta.total` | integer | 返回数量 |
|
||
|
||
---
|
||
|
||
## POST /api/open/resources/unlock
|
||
|
||
代表当前用户解锁资源并获取链接。第三方应用调用时应携带用户 Access Token。
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 位置 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|---|
|
||
| `slug` | body | string | 是 | 资源 slug,支持带横杠或不带横杠的 UUID |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -X POST \\
|
||
-H "X-API-Key: app-secret" \\
|
||
-H "Authorization: Bearer user-access-token" \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{"slug": "a1b2c3d4e5f647898765432112345678"}' \\
|
||
https://hdhive.com/api/open/resources/unlock
|
||
```
|
||
|
||
### 成功响应
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"code": "200",
|
||
"message": "解锁成功",
|
||
"data": {
|
||
"url": "https://pan.example.com/s/abc123",
|
||
"access_code": "x1y2",
|
||
"full_url": "https://pan.example.com/s/abc123?pwd=x1y2",
|
||
"already_owned": false
|
||
}
|
||
}
|
||
```
|
||
|
||
### 错误响应
|
||
|
||
| 场景 | HTTP 状态码 | 错误码 |
|
||
|---|---|---|
|
||
| 参数无效 | 400 | `400` |
|
||
| 缺少用户身份 | 403 | `OPENAPI_USER_REQUIRED` |
|
||
| 资源不存在 | 404 | `404` |
|
||
| 积分不足 | 402 | `INSUFFICIENT_POINTS` |
|
||
| 用户请求过快 | 429 | `RATE_LIMIT_EXCEEDED` |
|
||
|
||
> unlock 接口保留用户阶梯风控。第三方应用触发时,处罚对象是当前授权用户,不是整个应用。
|
||
|
||
---
|
||
|
||
## POST /api/open/check/resource
|
||
|
||
检查资源链接所属网盘类型,并尝试解析部分网盘的访问码。
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 位置 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|---|
|
||
| `url` | body | string | 是 | 资源分享链接 |
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -X POST \\
|
||
-H "X-API-Key: your-api-key" \\
|
||
-H "Authorization: Bearer user-access-token" \\
|
||
-H "Content-Type: application/json" \\
|
||
-d '{"url": "https://115.com/s/example 访问码:1234"}' \\
|
||
https://hdhive.com/api/open/check/resource
|
||
```
|
||
|
||
---
|
||
|
||
## GET /api/open/me
|
||
|
||
获取当前用户信息。该接口需要 `vip` scope,并要求当前用户满足 Premium 条件。
|
||
|
||
### 请求示例
|
||
|
||
```bash
|
||
curl -H "X-API-Key: app-secret" \\
|
||
-H "Authorization: Bearer user-access-token" \\
|
||
https://hdhive.com/api/open/me
|
||
```
|
||
|
||
### 响应字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `data.id` | number | 用户 ID |
|
||
| `data.nickname` | string | 昵称 |
|
||
| `data.username` | string | 用户名 |
|
||
| `data.email` | string | 邮箱 |
|
||
| `data.avatar_url` | string | 头像 |
|
||
| `data.is_vip` | boolean | 是否 Premium |
|
||
| `data.user_meta` | object | 用户积分、签到、分享等元信息 |
|
||
|
||
---
|
||
|
||
## POST /api/open/checkin
|
||
|
||
代表当前用户执行每日签到。该接口需要 `vip` scope,并要求当前用户满足 Premium 条件。
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 位置 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|---|
|
||
| `is_gambler` | body | boolean | 否 | 是否使用高波动签到模式 |
|
||
|
||
---
|
||
|
||
## GET /api/open/vip/weekly-free-quota
|
||
|
||
获取当前用户长期 Premium 每周免费解锁状态。该接口只返回状态,不建议客户端假设配置固定。
|
||
|
||
### 响应字段
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| `is_forever_vip` | boolean | 是否长期 Premium |
|
||
| `limit` | int | 服务端当前配置的基础状态值 |
|
||
| `used` | int | 本周已使用次数 |
|
||
| `remaining` | int | 当前可用状态 |
|
||
| `unlimited` | boolean | 是否不限制 |
|
||
| `bonus_quota` | int | 累积状态值 |
|
||
| `bonus_quota_max` | int | 累积上限状态值 |
|
||
|
||
---
|
||
|
||
## GET /api/open/shares
|
||
|
||
获取当前用户的分享列表。需要 `write` scope。
|
||
|
||
### 请求参数
|
||
|
||
| 参数 | 位置 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|---|
|
||
| `page` | query | integer | 否 | 页码 |
|
||
| `page_size` | query | integer | 否 | 每页数量 |
|
||
|
||
---
|
||
|
||
## GET /api/open/shares/:slug
|
||
|
||
获取指定分享详情。该接口不返回资源下载链接和访问码,需要调用 unlock 接口解锁后获取。
|
||
|
||
---
|
||
|
||
## POST /api/open/shares
|
||
|
||
创建新的资源分享。需要 `write` scope。
|
||
|
||
### 关键参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---|---|---|
|
||
| `url` | string | 是 | 分享链接 |
|
||
| `tmdb_id` | string | 条件必填 | TMDB ID,需配合 `media_type` |
|
||
| `media_type` | string | 条件必填 | `movie` 或 `tv` |
|
||
| `movie_id` | integer | 条件必填 | 系统电影 ID |
|
||
| `tv_id` | integer | 条件必填 | 系统电视剧 ID |
|
||
| `collection_id` | integer | 否 | 系统合集 ID |
|
||
| `title` | string | 否 | 资源标题 |
|
||
| `access_code` | string | 否 | 访问码 |
|
||
| `unlock_points` | integer | 否 | 解锁积分,未传或 0 表示免费 |
|
||
| `is_anonymous` | boolean | 否 | 是否匿名分享 |
|
||
| `hide_link` | boolean | 否 | 是否在通知中隐藏链接 |
|
||
|
||
> 影视关联至少需要提供 `tmdb_id + media_type`、`movie_id`、`tv_id` 或 `collection_id` 之一。
|
||
|
||
---
|
||
|
||
## PATCH /api/open/shares/:slug
|
||
|
||
部分更新已有分享。需要 `write` scope。只能更新自己创建的分享,或当前用户具备对应权限的分享。
|
||
|
||
---
|
||
|
||
## DELETE /api/open/shares/:slug
|
||
|
||
删除分享。需要 `write` scope。只能删除自己创建的分享,或当前用户具备对应权限的分享。
|
||
|
||
---
|
||
|
||
# 变更日志
|
||
|
||
| 日期 | 变更内容 |
|
||
|---|---|
|
||
| 2026-04-25 | 文档更新为新版 OpenAPI 应用授权、用户授权 Token、scope、限制与错误码口径 |
|