# 请求与响应约定

## 地址与版本

所有业务接口位于 `https://api.screenshare.cn/v1`。不要调用主站或 Dashboard 的内部 `/api/...` 路径；它们使用网站会话或内部服务授权，不属于开放协议。

请求 JSON 使用 UTF-8 和 `Content-Type: application/json`。邀请正文最大 4096 字节（无 Content-Length 的流式正文也检查），读取期限为 5 秒；不接受压缩正文。撤销邀请不发送请求体。路径最多 512 字符，查询字符串最多 2048 字符。仅使用已公开参数，不重复传入同名参数，不在 URL 传递凭证。

当前服务端接口面向服务端集成，不提供跨域浏览器调用；不要在前端暴露 API Key 来绕过这一边界。

## 响应信封

```json
{"ok":true,"data":{"example":"value"},"request_id":"req_UUID"}
```

```json
{"ok":false,"error":{"code":"INSUFFICIENT_SCOPE","message":"需要 records:read 权限。"},"request_id":"req_UUID"}
```

根据 HTTP 状态和 `error.code` 编写逻辑，`message` 供人阅读。每个 API 响应都包含 `X-Request-Id`；请求支持时请提供此编号。响应使用 `Cache-Control: no-store`，客户端不要把受组织权限保护的响应放进共享缓存。

时间采用 ISO 8601，正常输出 UTC `Z`。所有 ID 都应视为不透明字符串；不要推断时间、顺序或权限。只有公开查端记录的 `uuid` 使用明确的 USS 格式。

## 分页

- 组织记录使用 `limit`（1–100，默认 20）和 `cursor`。按 `updated_at`、`id` 升序返回；`next_cursor` 为 `null` 时结束。
- 邀请与工单列表使用 `page`（1–10000，默认 1），每页 20 条，返回 `page_count`。
- 翻页期间保持相同筛选条件。记录列表是实时视图，不是冻结快照；并发修改可能令条目移动。客户端按记录 ID 去重，并用重叠时间窗口同步。
- 邀请列表以创建时间倒序，新邀请可能导致页面移动。完整同步时按邀请 ID 去重。

## 限流

| 范围 | 限制 |
| --- | --- |
| 每把有效 API Key | 60 次/分钟，5,000 次/天 |
| 同一创建账号的所有 API Key | 300 次/分钟，20,000 次/天 |
| 同一组织的全部 API Key（包括不同管理员创建的密钥） | 300 次/分钟，20,000 次/天 |
| 创建邀请的请求（组织共享，包括幂等重试） | 10 次/分钟，60 次/小时，200 次/天 |
| 邀请及工单接口合计（组织共享，包括链接取回、撤销） | 60 次/分钟 |
| 邀请及工单接口正在处理的请求 | 每把密钥 2 个、每组织 4 个、每账号 6 个 |
| 来源 IP 的边缘保护（包括健康接口） | 约 30 次/10 秒，180 次/分钟 |
| 凭证的边缘保护（包括格式有效但不存在的凭证） | 约 20 次/10 秒，60 次/分钟 |

账号、密钥、组织的基础配额由共享数据库原子检查，跨边缘位置生效，不会因更换 IP 或增加密钥而重置。分钟、小时和日配额采用固定窗口；日配额在 **UTC 00:00（北京时间 08:00）** 重置。业务成功与失败请求都计入已通过的配额；某层拒绝后不再执行后续业务。创建邀请重试同样受限，不能通过不断更换幂等编号绕过限制。

边缘保护是按 Cloudflare 位置执行的近似计数，用于在数据库查询前拦截突发流量；不是全局精确配额。另有每边缘位置约 3,000 次/分钟的整体认证保护，降低大量不同凭证冲击数据库的风险。边缘阈值可能先于业务配额触发；生产限流设施不可用时返回 `503 RATE_LIMIT_UNAVAILABLE`，不会自动取消保护。

达到配额返回 `429 RATE_LIMITED`，同时处理太多工单请求则返回 `429 CONCURRENCY_LIMITED`。以响应中的 **Retry-After 秒数** 为准，不要固定等待 60 秒；日配额耗尽时可能需要等待至次日。并发限制通常返回 2 秒。收到 503 时也应遵守服务端给出的重试时间。

通过基础配额检查的响应携带以下请求时刻的快照；有并发调用时不保证后续仍有同样额度：

| 响应头 | 含义 |
| --- | --- |
| `X-RateLimit-Limit` | 当前策略的窗口最大次数 |
| `X-RateLimit-Remaining` | 本次检查后剩余次数 |
| `X-RateLimit-Reset` | 窗口结束时间，Unix 秒 |
| `X-RateLimit-Policy` | 正常为 `key-minute`；拒绝时说明触发策略，例如 `organization-day`、`invitation-hour`、`ticket-concurrency` |
| `Retry-After` | 至少等待的秒数，仅需重试指导的响应提供 |

业务配额拒绝时，前三个头描述触发的配额。边缘或并发拒绝只保证提供策略名称及 Retry-After，可能没有额度数字。

客户端为每个组织安排共享任务队列，每把密钥同时最多发起 2 个工单请求。优先用 Webhook 同步；状态核对通常以 30–60 秒或更长间隔进行。429 后暂停对应组织/账号的任务，加入少量随机延迟后恢复；不要切换 IP、账号或密钥继续刷请求。

### 个人中心与 Webhook 操作

| 操作 | 共享限制 |
| --- | --- |
| 查看 API 设置或投递列表 | 每账号 30 次/分钟 |
| 配置修改（创建、验证、重发等） | 每账号 10 次/分钟、60 次/小时、200 次/天 |
| 撤销 API Key / 停用 Webhook | 独立的每账号 10 次/分钟，不受上述修改的小时和日配额阻挡 |
| 创建 API Key | 每账号 20 次/小时、50 次/天；最多 20 把未到期有效密钥 |
| 创建 Webhook | 每账号 5 次/小时、20 次/天；每账号及每组织最多 10 个未停用回调 |
| 验证或测试回调 | 同一回调 1 次/分钟；每账号 3 次/分钟、30 次/小时；每组织 60 次/小时 |
| 手动重发 | 同一回调 5 次/分钟；每账号 10 次/小时；每组织 20 次/小时；同一投递 3 次/天 |

个人中心还在会话及审计读取前执行来源 IP 边缘保护：约 30 次/10 秒、60 次/分钟。上述限制不会赋予原本没有的组织权限。

### 限流日志

正常进入业务处理的请求保留脱敏调用日志。已识别密钥的限流拒绝每把密钥每分钟最多保存一条样本，ID 以 `rate_` 开头；边缘拦截和无效凭证不逐条写入业务数据库。个人中心调用统计因此不是被拦截流量的完整计费计数；平台 HTTP 429 指标用于观察整体拒绝量。这避免攻击者利用日志本身放大存储开销。

## 网络故障与幂等

GET 可以在网络错误、超时、429、502、503、504 时进行有限次数重试，使用退避和少量随机延迟。401/403 不应持续自动重试。

新建邀请要求 `Idempotency-Key`。其格式为 16–128 位 ASCII 字母、数字、`_` 或 `-`，推荐随机 UUID。相同密钥、组织、编号和规范化正文再次提交返回同一邀请。正文变化返回 `409 IDEMPOTENCY_CONFLICT`。

首次创建返回 201；重放返回 200，`data.replayed=true`。请求编号不会因为邀请加入、撤销或到期而重新用于新邀请；需要新邀请时使用新编号。网络错误不代表服务器没有创建成功。

## 兼容性

同一 v1 版本可增加可选字段和新的错误码。忽略不认识的响应字段；处理未知枚举时采用保守分支。现有字段的含义或授权范围若发生不兼容变化，会通过版本更新说明。调用方不要把某次返回字段的排列顺序作为协议。
