Files
ystp/docs/api.md

686 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API 接口文档v1- ImageForge
面向两类使用者:
- **网站Web**:上传/批量/历史/账单等(可能包含匿名试用)。
- **对外 APIDeveloper API**API Key 调用、可计量可计费、适配 CI/CD 与服务端集成。
产品范围与计费口径见:
- `docs/prd.md`
- `docs/billing.md`
---
## 1. 基础信息
- **Base URL**: `https://your-domain.com/api/v1`
- **数据格式**: JSON除明确标注“返回二进制”接口
- **时间格式**: ISO 8601 / UTC`2025-01-15T10:30:00Z`
- **ID 格式**: UUID 字符串
---
## 2. 认证
支持三种身份:
### 2.1 JWT网站/管理后台)
```http
Authorization: Bearer <token>
```
### 2.2 API Key对外 API
```http
X-API-Key: <your-api-key>
```
> **注意**:仅 **Pro** 和 **Business** 套餐用户可创建 API Key。Free 用户尝试创建时返回 `FORBIDDEN`HTTP `403`)。
### 2.3 匿名试用(仅网站场景)
- 不提供 API Key
- 通过 Cookie 维持匿名会话(服务端签发),仅允许较小文件与较低频率。
- 每日 10 次(以成功压缩文件数计);超出返回 `QUOTA_EXCEEDED`HTTP `402`)。
- 日界自然日UTC+8次日 00:00 重置。
- **匿名试用硬限制Cookie + IP 双限制**(两者任一超出都拒绝),降低刷会话绕过风险。
---
## 3. 通用约定
### 3.1 幂等(强烈建议)
对会产生计费/创建任务的接口,建议客户端传:
```http
Idempotency-Key: <uuid-or-random-string>
```
规则(建议口径):
- 同一个 `Idempotency-Key` 在 TTL 内重复请求,若请求参数一致则返回首次结果(不重复扣费/不重复创建任务)。
- 若参数不一致,返回 `409 IDEMPOTENCY_CONFLICT`
### 3.2 限流Rate Limit
超出限制返回:
- HTTP `429`
- 头:`Retry-After: <seconds>`
建议头(可选):
- `RateLimit-Limit`
- `RateLimit-Remaining`
- `RateLimit-Reset`
### 3.3 配额Quota / Billing
配额不足(当期额度耗尽)返回:
- HTTP `402`
- 错误码:`QUOTA_EXCEEDED`
配额周期:
- Pro/Business付费按订阅周期重置`period_start` ~ `period_end`),不是自然月。
- Free未订阅按自然月UTC+8重置。
- 匿名试用按自然日UTC+8重置。
建议头(可选):
- `X-Quota-Limit`
- `X-Quota-Remaining`
- `X-Quota-Reset-At`
### 3.4 通用响应格式JSON
成功:
```json
{ "success": true, "data": {} }
```
错误:
```json
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "错误描述",
"request_id": "req_..."
}
}
```
### 3.5 错误码(建议集合)
| 错误码 | HTTP | 说明 |
|---|---:|---|
| `INVALID_REQUEST` | 400 | 参数不合法 |
| `INVALID_IMAGE` | 400 | 图片解码失败/文件损坏 |
| `UNSUPPORTED_FORMAT` | 400 | 不支持的格式 |
| `TOO_MANY_PIXELS` | 400 | 像素超限(防图片炸弹) |
| `UNAUTHORIZED` | 401 | 未认证 |
| `FORBIDDEN` | 403 | 权限不足 |
| `NOT_FOUND` | 404 | 资源不存在 |
| `IDEMPOTENCY_CONFLICT` | 409 | 幂等 key 冲突 |
| `QUOTA_EXCEEDED` | 402 | 配额不足 |
| `FILE_TOO_LARGE` | 413 | 文件过大 |
| `RATE_LIMITED` | 429 | 请求过于频繁 |
| `EMAIL_NOT_VERIFIED` | 403 | 邮箱未验证 |
| `INVALID_TOKEN` | 400 | Token 无效或已过期 |
| `COMPRESSION_FAILED` | 500 | 压缩失败 |
| `STORAGE_UNAVAILABLE` | 503 | 存储不可用 |
| `MAIL_SEND_FAILED` | 500 | 邮件发送失败 |
---
## 4. 认证接口
### 4.1 用户注册
```http
POST /auth/register
Content-Type: application/json
```
请求体:
```json
{ "email": "user@example.com", "password": "securepassword123", "username": "myusername" }
```
响应:
```json
{
"success": true,
"data": {
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"username": "myusername",
"email_verified": false,
"created_at": "2025-01-15T10:30:00Z"
},
"token": "eyJhbGciOi...",
"message": "注册成功,验证邮件已发送至您的邮箱"
}
}
```
> **注意**:注册后自动发送验证邮件。用户需验证邮箱后才能使用压缩功能(未验证时调用压缩接口返回 `EMAIL_NOT_VERIFIED`)。
### 4.2 用户登录
```http
POST /auth/login
Content-Type: application/json
```
请求体:
```json
{ "email": "user@example.com", "password": "securepassword123" }
```
响应:
```json
{
"success": true,
"data": {
"token": "eyJhbGciOi...",
"expires_at": "2025-01-22T10:30:00Z",
"user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "username": "myusername", "role": "user" }
}
}
```
### 4.3 刷新 Token
```http
POST /auth/refresh
Authorization: Bearer <token>
```
### 4.4 登出
```http
POST /auth/logout
Authorization: Bearer <token>
```
### 4.5 发送验证邮件
用户注册后自动发送一次;此接口用于重新发送。
```http
POST /auth/send-verification
Authorization: Bearer <token>
```
**限流**:同一用户 1 分钟内最多 1 次
响应:
```json
{ "success": true, "data": { "message": "验证邮件已发送,请查收" } }
```
### 4.6 验证邮箱
```http
POST /auth/verify-email
Content-Type: application/json
```
请求体:
```json
{ "token": "verification-token-from-email" }
```
响应:
```json
{ "success": true, "data": { "message": "邮箱验证成功" } }
```
### 4.7 请求密码重置
```http
POST /auth/forgot-password
Content-Type: application/json
```
请求体:
```json
{ "email": "user@example.com" }
```
**限流**:同一 IP 1 分钟内最多 3 次
响应(无论邮箱是否存在都返回成功,防止枚举):
```json
{ "success": true, "data": { "message": "如果该邮箱已注册,您将收到重置邮件" } }
```
### 4.8 重置密码
```http
POST /auth/reset-password
Content-Type: application/json
```
请求体:
```json
{ "token": "reset-token-from-email", "new_password": "new-secure-password" }
```
响应:
```json
{ "success": true, "data": { "message": "密码重置成功,请重新登录" } }
```
---
## 5. 图片压缩接口
### 5.1 单图压缩(同步,返回 JSON + 下载链接)
适用于网站与轻量同步调用(服务端可选择是否落盘/落对象存储)。
```http
POST /compress
Content-Type: multipart/form-data
Authorization: Bearer <token> # X-API-Key
Idempotency-Key: <key> #
```
表单字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `file` | File | 是 | 图片文件 |
| `compression_rate` | Integer | 否 | 压缩率 1-100压缩后体积占原图比例数值越小压缩越强100 表示不压缩),优先级高于 `level` |
| `level` | String | 否 | `high` / `medium` / `low`(兼容参数,默认 `medium` |
| `output_format` | String | 否 | 已停用,仅支持保持原格式 |
| `max_width` | Integer | 否 | 最大宽度(等比缩放) |
| `max_height` | Integer | 否 | 最大高度(等比缩放) |
| `preserve_metadata` | Boolean | 否 | 是否保留元数据(默认 `false` |
响应:
```json
{
"success": true,
"data": {
"task_id": "550e8400-e29b-41d4-a716-446655440100",
"file_id": "550e8400-e29b-41d4-a716-446655440101",
"format_in": "png",
"format_out": "png",
"original_size": 1024000,
"compressed_size": 256000,
"saved_bytes": 768000,
"saved_percent": 75.0,
"download_url": "/downloads/550e8400-e29b-41d4-a716-446655440101",
"expires_at": "2025-01-15T11:30:00Z",
"billing": { "units_charged": 1 }
}
}
```
### 5.2 单图压缩(同步,直接返回二进制)
更贴近开发者体验,适用于 SDK/CI。
```http
POST /compress/direct
Content-Type: multipart/form-data
X-API-Key: <your-api-key> # Bearer token
Idempotency-Key: <key> #
```
成功响应:
- HTTP `200`
- Body压缩后的图片二进制
- `Content-Type`: `image/png` / `image/jpeg` / `image/webp` / `image/avif` / `image/gif` / `image/bmp` / `image/tiff` / `image/x-icon`
建议响应头(示例):
```http
ImageForge-Original-Size: 1024000
ImageForge-Compressed-Size: 256000
ImageForge-Saved-Bytes: 768000
ImageForge-Saved-Percent: 75.0
ImageForge-Units-Charged: 1
```
### 5.3 批量压缩(异步任务)
适用于多文件或大文件;由 Worker 处理并持续更新进度。
```http
POST /compress/batch
Content-Type: multipart/form-data
Authorization: Bearer <token> # X-API-Key
Idempotency-Key: <key> #
```
表单字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `files[]` | File[] | 是 | 图片文件数组(上限由套餐决定) |
| `compression_rate` | Integer | 否 | 压缩率 1-100压缩后体积占原图比例数值越小压缩越强100 表示不压缩),优先级高于 `level` |
| `level` | String | 否 | `high` / `medium` / `low`(兼容参数) |
| `output_format` | String | 否 | 已停用,仅支持保持原格式 |
| `preserve_metadata` | Boolean | 否 | 是否保留元数据(默认 `false` |
响应:
```json
{
"success": true,
"data": {
"task_id": "550e8400-e29b-41d4-a716-446655440200",
"total_files": 10,
"status": "pending",
"status_url": "/compress/tasks/550e8400-e29b-41d4-a716-446655440200"
}
}
```
配额规则补充:
- 若本周期剩余单位不足以覆盖本次上传的文件数,服务端应直接返回 `402 QUOTA_EXCEEDED`(不创建任务)。
### 5.4 查询任务状态
```http
GET /compress/tasks/{task_id}
Authorization: Bearer <token> # X-API-Key Cookie
```
响应:
```json
{
"success": true,
"data": {
"task_id": "550e8400-e29b-41d4-a716-446655440200",
"status": "completed",
"progress": 100,
"total_files": 10,
"completed_files": 10,
"failed_files": 0,
"files": [
{
"file_id": "550e8400-e29b-41d4-a716-446655440201",
"original_name": "photo1.png",
"original_size": 1024000,
"compressed_size": 256000,
"saved_percent": 75.0,
"status": "completed",
"download_url": "/downloads/550e8400-e29b-41d4-a716-446655440201"
}
],
"download_all_url": "/downloads/tasks/550e8400-e29b-41d4-a716-446655440200",
"created_at": "2025-01-15T10:30:00Z",
"completed_at": "2025-01-15T10:31:00Z",
"expires_at": "2025-01-22T10:30:00Z"
}
}
```
### 5.5 取消任务(可选)
```http
POST /compress/tasks/{task_id}/cancel
Authorization: Bearer <token>
```
### 5.6 删除任务与文件(隐私/合规)
```http
DELETE /compress/tasks/{task_id}
Authorization: Bearer <token>
```
---
## 6. 下载接口
### 6.1 下载单个文件
```http
GET /downloads/{file_id}
Authorization: Bearer <token> # X-API-Key Cookie
```
### 6.2 下载批量 ZIP
```http
GET /downloads/tasks/{task_id}
Authorization: Bearer <token> # X-API-Key Cookie
```
---
## 7. 用户接口
### 7.1 获取当前用户信息
```http
GET /user/profile
Authorization: Bearer <token>
```
响应(示例):
```json
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"username": "myusername",
"role": "user"
}
}
```
### 7.2 更新用户信息
```http
PUT /user/profile
Authorization: Bearer <token>
Content-Type: application/json
```
### 7.3 修改密码
```http
PUT /user/password
Authorization: Bearer <token>
Content-Type: application/json
```
### 7.4 获取压缩历史
```http
GET /user/history?page=1&limit=20
Authorization: Bearer <token>
```
---
## 8. API Key 管理
### 8.1 获取 API Key 列表
```http
GET /user/api-keys
Authorization: Bearer <token>
```
### 8.2 创建 API Key
```http
POST /user/api-keys
Authorization: Bearer <token>
Content-Type: application/json
```
请求体:
```json
{ "name": "Production Server", "permissions": ["compress", "batch_compress"] }
```
响应:
```json
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440300",
"name": "Production Server",
"key": "if_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"message": "请保存此 Key它只会显示一次"
}
}
```
### 8.3 轮换 API Key可选
```http
POST /user/api-keys/{key_id}/rotate
Authorization: Bearer <token>
```
### 8.4 删除/禁用 API Key
```http
DELETE /user/api-keys/{key_id}
Authorization: Bearer <token>
```
---
## 9. 计费与用量Billing
### 9.1 获取套餐列表(公开)
```http
GET /billing/plans
```
响应(示例):
```json
{
"success": true,
"data": {
"plans": [
{
"id": "550e8400-e29b-41d4-a716-446655440900",
"code": "pro_monthly",
"name": "Pro月付",
"currency": "CNY",
"amount_cents": 1999,
"interval": "monthly",
"included_units_per_period": 10000,
"max_file_size_mb": 20,
"max_files_per_batch": 50,
"retention_days": 7,
"features": { "webhook": true }
}
]
}
}
```
### 9.2 获取当前订阅
```http
GET /billing/subscription
Authorization: Bearer <token>
```
### 9.3 获取当期用量
```http
GET /billing/usage
Authorization: Bearer <token>
```
响应:
```json
{
"success": true,
"data": {
"period_start": "2025-01-01T00:00:00Z",
"period_end": "2025-02-01T00:00:00Z",
"used_units": 120,
"included_units": 10000,
"bonus_units": 500,
"total_units": 10500,
"remaining_units": 10380
}
}
```
### 9.4 创建 Checkout订阅/升级)
```http
POST /billing/checkout
Authorization: Bearer <token>
Content-Type: application/json
Idempotency-Key: <key>
```
请求体:
```json
{ "plan_id": "550e8400-e29b-41d4-a716-446655440900" }
```
响应:
```json
{ "success": true, "data": { "checkout_url": "https://pay.example.com/..." } }
```
### 9.5 打开客户 Portal管理支付方式/取消订阅)
```http
POST /billing/portal
Authorization: Bearer <token>
```
### 9.6 发票列表
```http
GET /billing/invoices?page=1&limit=20
Authorization: Bearer <token>
```
---
## 10. Webhooks支付回调
> 无需登录;必须验签与幂等处理,详见 `docs/billing.md` 与 `docs/security.md`。
### 10.1 Stripe 回调(示例)
```http
POST /webhooks/stripe
Content-Type: application/json
Stripe-Signature: t=...,v1=...
```
---
## 11. 管理员接口
> 需要管理员权限(`role: admin`
### 11.1 获取系统统计
```http
GET /admin/stats
Authorization: Bearer <admin_token>
```
### 11.2 用户管理(示例)
```http
GET /admin/users?page=1&limit=20&search=keyword
Authorization: Bearer <admin_token>
```
### 11.3 系统配置
```http
GET /admin/config
Authorization: Bearer <admin_token>
```
```http
PUT /admin/config
Authorization: Bearer <admin_token>
Content-Type: application/json
```
### 11.4 任务管理
```http
GET /admin/tasks?status=processing&page=1
Authorization: Bearer <admin_token>
```
```http
POST /admin/tasks/{task_id}/cancel
Authorization: Bearer <admin_token>
```
### 11.5 计费管理(建议)
```http
GET /admin/billing/subscriptions?page=1&limit=20
Authorization: Bearer <admin_token>
```
```http
POST /admin/billing/credits
Authorization: Bearer <admin_token>
Content-Type: application/json
```
---
## 12. WebSocket网站任务进度
网站侧可用 WebSocket 或 SSESSE 更易穿透代理)。当前先保留 WebSocket 方案:
```
ws://your-domain.com/ws/tasks/{task_id}?token=<jwt_token>
```
消息(示例):
```json
{ "type": "progress", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440200", "progress": 50, "completed_files": 5 } }
```