# API 接口文档(v1)- ImageForge 面向两类使用者: - **网站(Web)**:上传/批量/历史/账单等(可能包含匿名试用)。 - **对外 API(Developer 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 ``` ### 2.2 API Key(对外 API) ```http X-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: ``` 规则(建议口径): - 同一个 `Idempotency-Key` 在 TTL 内重复请求,若请求参数一致则返回首次结果(不重复扣费/不重复创建任务)。 - 若参数不一致,返回 `409 IDEMPOTENCY_CONFLICT`。 ### 3.2 限流(Rate Limit) 超出限制返回: - HTTP `429` - 头:`Retry-After: ` 建议头(可选): - `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 ``` ### 4.4 登出 ```http POST /auth/logout Authorization: Bearer ``` ### 4.5 发送验证邮件 用户注册后自动发送一次;此接口用于重新发送。 ```http POST /auth/send-verification Authorization: Bearer ``` **限流**:同一用户 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 # 或 X-API-Key;网站匿名试用可不带 Idempotency-Key: # 建议 ``` 表单字段: | 字段 | 类型 | 必填 | 说明 | |---|---|---:|---| | `file` | File | 是 | 图片文件 | | `compression_rate` | Integer | 否 | 压缩率 1-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: # 或 Bearer token(不建议匿名) Idempotency-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 # 或 X-API-Key Idempotency-Key: # 建议 ``` 表单字段: | 字段 | 类型 | 必填 | 说明 | |---|---|---:|---| | `files[]` | File[] | 是 | 图片文件数组(上限由套餐决定) | | `compression_rate` | Integer | 否 | 压缩率 1-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 # 或 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 ``` ### 5.6 删除任务与文件(隐私/合规) ```http DELETE /compress/tasks/{task_id} Authorization: Bearer ``` --- ## 6. 下载接口 ### 6.1 下载单个文件 ```http GET /downloads/{file_id} Authorization: Bearer # 或 X-API-Key;匿名试用需 Cookie 会话 ``` ### 6.2 下载批量 ZIP ```http GET /downloads/tasks/{task_id} Authorization: Bearer # 或 X-API-Key;匿名试用需 Cookie 会话 ``` --- ## 7. 用户接口 ### 7.1 获取当前用户信息 ```http GET /user/profile Authorization: Bearer ``` 响应(示例): ```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 Content-Type: application/json ``` ### 7.3 修改密码 ```http PUT /user/password Authorization: Bearer Content-Type: application/json ``` ### 7.4 获取压缩历史 ```http GET /user/history?page=1&limit=20 Authorization: Bearer ``` --- ## 8. API Key 管理 ### 8.1 获取 API Key 列表 ```http GET /user/api-keys Authorization: Bearer ``` ### 8.2 创建 API Key ```http POST /user/api-keys Authorization: Bearer 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 ``` ### 8.4 删除/禁用 API Key ```http DELETE /user/api-keys/{key_id} Authorization: Bearer ``` --- ## 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 ``` ### 9.3 获取当期用量 ```http GET /billing/usage Authorization: Bearer ``` 响应: ```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 Content-Type: application/json Idempotency-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 ``` ### 9.6 发票列表 ```http GET /billing/invoices?page=1&limit=20 Authorization: Bearer ``` --- ## 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 ``` ### 11.2 用户管理(示例) ```http GET /admin/users?page=1&limit=20&search=keyword Authorization: Bearer ``` ### 11.3 系统配置 ```http GET /admin/config Authorization: Bearer ``` ```http PUT /admin/config Authorization: Bearer Content-Type: application/json ``` ### 11.4 任务管理 ```http GET /admin/tasks?status=processing&page=1 Authorization: Bearer ``` ```http POST /admin/tasks/{task_id}/cancel Authorization: Bearer ``` ### 11.5 计费管理(建议) ```http GET /admin/billing/subscriptions?page=1&limit=20 Authorization: Bearer ``` ```http POST /admin/billing/credits Authorization: Bearer Content-Type: application/json ``` --- ## 12. WebSocket(网站任务进度) 网站侧可用 WebSocket 或 SSE(SSE 更易穿透代理)。当前先保留 WebSocket 方案: ``` ws://your-domain.com/ws/tasks/{task_id}?token= ``` 消息(示例): ```json { "type": "progress", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440200", "progress": 50, "completed_files": 5 } } ```