Files
EveryPublish/docs/api.md
T

162 lines
6.5 KiB
Markdown
Raw 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.
# EveryPublish 服务端接口文档(v1)
> 基地址:`/api/v1` · 统一响应:`{"code":0,"message":"ok","data":{...}}`,code!=0 为业务错误。
> 认证:`Authorization: Bearer <accessToken>`(15min,前端自动用 refresh 轮换)。
## 业务错误码
| code | 含义 |
|---|---|
| 1001 | 参数不合法 |
| 1002 | 未登录/令牌无效 |
| 1003 | 无权限 |
| 1004 | 资源不存在 |
| 2001 | 邮箱已注册 |
| 2002 | 邮箱或密码错误 |
| 2003 | 刷新令牌无效 |
| 2004 | 已是成员 |
| 2005 | 邀请链接无效或过期 |
| 1006 | 需要两步验证(2FA,默认关) |
| 3001-3005 | 业务冲突(账号不可删/已绑定/挑战已结束/链接过期/任务状态不允许) |
## 认证 /auth
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /auth/register | 注册 {email,password,nickname} → 返回令牌对+用户+默认工作空间 |
| POST | /auth/login | 登录 {email,password} → 令牌对+用户 |
| POST | /auth/refresh | {refreshToken} → 轮换新令牌对(旧 refresh 立即吊销) |
| POST | /auth/logout | 登出(吊销 refresh) |
| GET | /auth/me | 当前用户+工作空间+角色 |
## 工作空间 /workspaces(登录)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /workspaces | 创建 {name}(创建者为 owner) |
| GET | /workspaces | 我所在的工作空间列表 |
| PUT | /workspaces/:id | 改名(owner/admin) |
## 成员 /members(登录)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /members | 成员列表(含 email/nickname) |
| POST | /members/invite | 邀请 {email,role} → {token,link}(owner/admin;role: admin/operator/reviewer/viewer) |
| POST | /members/join | 接受邀请 {token}(须与登录邮箱一致) |
| PUT | /members/:id/role | 改角色 {role}(不可改 owner) |
| DELETE | /members/:id | 移除(不可移除 owner) |
## 账号台账 /accounts(登录)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /accounts?platform=&status=&page=&size= | 台账列表(状态:unbound/binding/active/suspended/expired) |
| POST | /accounts | 新增 {platform(douyin/kuaishou/xiaohongshu/bilibili),accountName,avatarUrl?,ipProfile?} |
| PUT | /accounts/:id | 改资料(名称/头像/IP 画像) |
| DELETE | /accounts/:id | 删除(仅 unbound) |
| POST | /accounts/:id/bind | 发起绑定 → 创建挑战记录(status→binding)→ {challengeId} |
## 素材 /materials(登录)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /materials?kind=&group=&page=&size= | 素材列表 |
| POST | /materials | multipart 上传:file 字段 + 可选 group/tags;流式 sha256,同工作区去重(dedup:true 返回已有素材) |
| GET | /materials/:id/url | 生成签名直链(10 分钟、一次性)→ {url,expiresAt} |
| DELETE | /materials/:id | 删除素材及文件 |
| GET | /files/:token | 凭 token 下载文件(无鉴权,token 即凭证;一次性) |
## 任务 /tasks(登录;状态机)
```mermaid
flowchart LR
D[draft] -->|submit| P[pending_review]
P -->|approve| Q[queued] -->|dispatch| DP[dispatched] -->|start| R[running]
R -->|success| S[success]
R -->|fail| F[failed] -->|retry| Q
R -->|suspend| SU[suspended] -->|resume| Q
P -->|reject| RJ[rejected] -->|resubmit| P
D -->|cancel| C[cancelled]
Q -->|cancel| C
DP -->|cancel| C
R -->|cancel| C
SU -->|cancel| C
```
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /tasks?status=&schedule=&page=&size= | 任务列表 |
| POST | /tasks | 新建草稿 {title,content?,tags?,accountIds[],materialIds[],scheduleAt?(unix ms),priority?(1-10)} |
| GET | /tasks/:id | 详情 |
| PUT | /tasks/:id | 编辑(仅 draft/rejected) |
| DELETE | /tasks/:id | 删除(仅 draft) |
| POST | /tasks/:id/submit | 提交审核 |
| POST | /tasks/:id/approve | 审核通过 → queued(通知创建人) |
| POST | /tasks/:id/reject | 驳回 {note}(通知创建人) |
| POST | /tasks/:id/resubmit | 驳回后重提 |
| POST | /tasks/:id/retry | 失败重试 → queued |
| POST | /tasks/:id/cancel | 取消 |
## 挑战 /challenges(登录)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /challenges?status=&accountId= | 挑战列表(过期自动置 expired) |
| POST | /challenges/:id/solve | 人工完成 {value?}(验证码/APP 确认;扫码由 Agent 完成) |
| POST | /challenges/:id/resend | 一键重发(expired/suspended → active,重置 30min) |
| POST | /challenges/:id/suspend | 挂起 |
## 通知 /notifications(登录)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /notifications?kind= | 我的通知 + unread 计数 |
| POST | /notifications/:id/read | 标记已读 |
| POST | /notifications/read-all | 全部已读 |
## 审计 /audit-logs(登录)
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /audit-logs?userId=&action=&page=&size= | 审计日志(中间件自动埋点:登录/登出/增删改/审核/挑战等) |
## 设备配对 /agent
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| POST | /agent/pair-code | Bearer | 生成配对码(6 位,5 分钟一次性) |
| POST | /agent/pair | 无(凭码) | 配对 {code,deviceName,os,version,publicKey(Ed25519 base64)} → {deviceId} |
| GET | /agent/devices | Bearer | 设备列表(在线状态) |
## WSS 双通道
### Agent 通道 `/ws/agent`(Ed25519 设备签名,无 JWT)
| 方向 | 消息 | 说明 |
|---|---|---|
| C→S | `hello` | {deviceId,nonce,ts,sig(base64, 签名原文 nonce+`\|`+ts),version} |
| S→C | `hello.ack` | {serverNonce,sessionId,serverTs,sig} |
| C→S | `heartbeat`(10-30s) / S→C `heartbeat.ack` | 保活 |
| S→C | `task.push` | 任务下发 {taskId,platform,accountId,title,content,tags,materialUrls(一次性签名直链),priority} |
| C→S | `task.ack` | {taskId,accept,reason?}(accept→running) |
| C→S | `task.result` | {taskId,status(success/failed),publishedUrl,receipts,error,finishedAt} |
| S→C | `challenge.new` | 绑定扫码挑战 {challengeId,accountId,platform,kind,qrToken,qrUrl,prompt,expiresAt} |
| C→S | `challenge.ack` / `challenge.solve` | 应答 / 完成(solve 后账号→active) |
### 浏览器通道 `/ws/browser?token=<JWT>`(只读订阅)
| 事件 | 说明 |
|---|---|
| `task.status` | {taskId,status,errorMessage,publishedUrls}(下发/执行/成功/失败实时推送) |
| `agent.status` | {deviceId,online} |
| `challenge.status` | {challengeId,status,accountId} |
> 实测:任务下发延迟(approve→task.push)≈ 28.7ms(本机,硬指标 <300ms)。
## 健康检查
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /health | 服务健康(db/redis 状态) |