# REST API 参考 所有 v1 接口都在 `/api/v1` 下,通过 `Authorization: Bearer pd_<前缀>_<密钥>` 鉴权。token 在 [/developers/tokens](/developers/tokens) 创建;机器可读的 OpenAPI 3.1 描述位于 [/api/openapi.json](/api/openapi.json)。 **限流:** 新建 token 默认 5 次/分钟,创建时可配置 `rateLimitPerMinute`(1-600)。达到上限会返回 429,并带上 `Retry-After`、`X-RateLimit-Limit` 与 `X-RateLimit-Remaining: 0` 响应头。 **错误信封:** 非 2xx 响应统一是 `{ "error": "<可读消息>", "code": "<机器码>" }`。机器码枚举在所有接口里都相同 (见文末"错误码"小节)。 ## 接口列表 ### `GET /v1/me` 返回 token 所属的用户,以及本次请求走的是哪种鉴权路径。验证 token 是否可用的最快方式。 ```bash curl -H "Authorization: Bearer $TOKEN" $BASE/api/v1/me ``` ```json { "user": { "id": "cm...", "email": "you@example.com", "quotaBytes": 524288000, "usedBytes": 12345 }, "auth": { "source": "token", "tokenId": "cm..." } } ``` ### `GET /v1/files` 列出你的文件。可选 `?folderId=` 限定到某个目录。响应包含 `kind`(HTML / MARKDOWN / TEXT)、`scanStatus`、`shareCount`。 ### `POST /v1/files`(multipart) 上传单个 `.html` / `.htm` / `.md` / `.markdown` / `.txt` / `.text` 文件。可选附带一个 `share` 表单字段(JSON 编码),在同一个事务里直接创建分享链接,并在响应里把 URL 一起返回。新建分享的 URL 形如 `/s/<用户公开段>/<分享 token>`;旧的 `/s/<分享 token>` 仍保持兼容。 ```bash curl -H "Authorization: Bearer $TOKEN" \ -F "file=@notes.md;type=text/markdown" \ -F 'share={"expiresInDays":7,"password":"hello12"}' \ $BASE/api/v1/files ``` 限制:单文件 10 MB;不接受 ZIP、视频、音频、可执行文件或目录打包。同目录下同名上传会返回 409 `DUPLICATE`(如需覆盖 / 自动重命名,请用控制台 UI——版本机制只在 UI 路径生效)。 ### `GET /v1/files/{id}` · `DELETE /v1/files/{id}` 读取元数据,或软删除(同时会撤销该文件的所有分享)。 ### `GET /v1/shares` · `POST /v1/shares` · `GET /v1/shares/{id}` · `DELETE /v1/shares/{id}` 标准的 列表 / 创建 / 获取 / 撤销。`POST /v1/shares` 请求体: ```json { "fileId": "cm...", "expiresInDays": 7, // null = 永久 "password": "hello12", // null = 无密码 "maxVisits": 100, "perVisitorMaxVisits": 3, // 每个独立访客最多访问 3 次;null = 每人不限 "perLoginUserMaxVisits": 2, // 每个登录账号最多访问 2 次;设置后访客必须登录 "oneTime": false, // true 时强制 maxVisits=1 "requireLogin": false, // true = 访客必须登录 PageDrop 后才能查看 "slug": "weekly-report", // 3-32 位,可用字符 base62 + - _ "lockedVersionId": "fv_...", // 钉到某个具体 FileVersion "oneSession": false, // 同一浏览器 session 才能访问 "emailAllowlist": ["a@b.com"], // 访客必须登录且邮箱命中白名单 "copyProtectionEnabled": false, "burnAfterReadEnabled": false // 阅后即焚:当前浏览器记住已读位置,刷新后从未读处继续 } ``` 所有 share 字段都是可选的。返回 `{ share, url }`(`url` 是绝对的查看地址)。 share 里的访问统计包含两个口径:`visitCount` 是累计访问量,每次成功渲染主页面都加 1; `uniqueVisitCount` 是独立访问量,按渲染域访客 Cookie 去重,首次没有 Cookie 时用脱敏 IP 段 + User-Agent 生成初始标识。 ### `POST /v1/validate` 不入库地预校验内容。给 Agent 生成的文本做预检很合适——把问题挡在落盘之前。 ```bash curl -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"content":"# hi","kind":"MARKDOWN"}' \ $BASE/api/v1/validate ``` 响应:`{ ok: boolean, normalized: string, issues: [{ level, message, line? }] }`。 `level` 取值 `error`(会让 ok=false)、`warning`、`info`。`normalized` 是把 CRLF → LF、 Tab → 4 空格、BOM 剥掉、尾随空白裁掉之后的内容。 ## 错误码 | code | HTTP | 含义 | |---|---|---| | `UNAUTHENTICATED` | 401 | token 缺失 / 无效 / 已撤销 | | `FORBIDDEN` | 403 | 已鉴权但没有权限 | | `NOT_FOUND` | 404 | 资源不存在或不属于你 | | `VALIDATION` | 400 | 请求体 / 参数不合法 | | `RATE_LIMITED` | 429 | 单 token 60/min 桶被打空 | | `OVER_QUOTA` | 413 | 文件超大或账号配额已用尽 | | `INFECTED` | 409 | 被 ClamAV 标记为不安全 | | `SLUG_TAKEN` | 409 | 自定义短链已被占用 | | `DUPLICATE` | 409 | 同目录下已有同名文件 | | `CONFLICT` | 409 | 通用冲突 | | `INTERNAL` | 500 | 服务端错误(已写日志 + Sentry) | ## CORS 所有 `/v1/*` 响应都带 `Access-Control-Allow-Origin: *` 和 `Allow-Headers: Authorization, Content-Type`。跨域浏览器代码可以直接带 Bearer token 调用(我们故意不设 Allow-Credentials,所以 cookie 不会跨域传播)。 ## 试一试 [Playground](/developers/playground) 把每个接口都渲染成了带输入框的表单——粘一次 token 然后点 Send 就能跑。