# API 接口清单 从 FastAPI 自己的 OpenAPI schema 生成的,**不是手写的** —— 手写的接口文档从改代码那天起就开始腐烂,而且烂得无声无息。 重新生成: ```bash ./.venv/Scripts/python.exe docs/gen_api_doc.py ``` ## 通用约定 | | | |---|---| | 前缀 | 所有接口都在 `/api` 下(WebSocket 是 `/api/ws/...`)| | 鉴权 | **Cookie 优先,Bearer 次之**:`token_from_request()` 先读会话 Cookie,读不到再读 `Authorization: Bearer `。浏览器用 Cookie,脚本用 Bearer | | 会话怎么来 | `POST /api/auth/login`(密码),响应种下会话 Cookie;有效期由服务端 `resolve_session()` 判定 | | 错误形状 | FastAPI 默认的 `{"detail": "..."}`;401 是登录失效 | | **没有 `/docs`** | 特意关掉的:`/docs`、`/redoc`、`/openapi.json` 默认**不需要登录**,等于把整份接口地图连同「Try it out」一起送出去。要看交互式的,得挂在鉴权后面 | | WebSocket | `GET /api/ws/logs`(升级为 ws)—— 实时日志流。**不在这里的清单里**:OpenAPI 描述不了 WebSocket。它自己用 `require_ws_auth` 校验会话 Cookie | ## 目录 - [认证](#认证)(4 个) - [采集](#采集)(4 个) - [运营(博主账号)](#运营(博主账号))(8 个) - [数据](#数据)(4 个) - [监控](#监控)(36 个) - [设置](#设置)(2 个) ## 认证 这一组**没有**统一挂 `require_auth`(登录不能要求先登录),所以逐个标。 | 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 | |---|---|:--:|---|---|---| | `POST` | `/api/auth/login` | — | Login | | LoginPayload | | `POST` | `/api/auth/logout` | — | Logout | | | | `GET` | `/api/auth/me` | ✓ | Identity probe. The SPA treats a 401 here as "show the login page". | | | | `POST` | `/api/auth/password` | ✓ | Change the password and log every device out. | | ChangePasswordPayload | ## 采集 | 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 | |---|---|:--:|---|---|---| | `GET` | `/api/crawler/logs` | ✓ | Get recent logs | `limit`(query integer 可选=100) | | | `POST` | `/api/crawler/start` | ✓ | Start crawler task. | | CrawlerStartRequest | | `GET` | `/api/crawler/status` | ✓ | Get crawler status | | | | `POST` | `/api/crawler/stop` | ✓ | Stop crawler task | | | ## 运营(博主账号) | 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 | |---|---|:--:|---|---|---| | `GET` | `/api/creator/accounts` | ✓ | 账号列表。**不含 cookie**,只给 ``has_cookie``。 | | | | `DELETE` | `/api/creator/accounts/{account_id}` | ✓ | Delete Account | `account_id`(path integer 必填) | | | `GET` | `/api/creator/accounts/{account_id}` | ✓ | Get Account Detail | `account_id`(path integer 必填) | | | `POST` | `/api/creator/accounts/{account_id}/check` | ✓ | 重测登录态与数据权限。 | `account_id`(path integer 必填) | | | `POST` | `/api/creator/accounts/{account_id}/sync` | ✓ | 拉取作品数据。 | `account_id`(path integer 必填)
`days`(query integer 可选=90) | | | `DELETE` | `/api/creator/login` | ✓ | Cancel Login | | | | `GET` | `/api/creator/login` | ✓ | 轮询扫码结果;一旦成功就把账号落库并返回它。 | | | | `POST` | `/api/creator/login` | ✓ | Start Login | | | ## 数据 | 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 | |---|---|:--:|---|---|---| | `GET` | `/api/data/download/{file_path}` | ✓ | Download file | `file_path`(path string 必填) | | | `GET` | `/api/data/files` | ✓ | Get data file list | `platform`(query string \| null 可选)
`file_type`(query string \| null 可选) | | | `GET` | `/api/data/files/{file_path}` | ✓ | Get file content or preview | `file_path`(path string 必填)
`preview`(query boolean 可选=True)
`limit`(query integer 可选=100) | | | `GET` | `/api/data/stats` | ✓ | Get data statistics | | | ## 监控 | 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 | |---|---|:--:|---|---|---| | `GET` | `/api/monitor/comment-notes` | ✓ | Works that have comments, newest first, with counts. | `task_id`(query integer \| null 可选)
`platform`(query string \| null 可选) | | | `GET` | `/api/monitor/comments` | ✓ | Comments, each carrying the work it belongs to. | `task_id`(query integer \| null 可选)
`note_id`(query string \| null 可选)
`group_by`(query string \| null 可选)
`limit`(query integer 可选=200)
`platform`(query string \| null 可选) | | | `DELETE` | `/api/monitor/cookie` | ✓ | Clear Cookie Endpoint | `platform`(query string 可选='xhs') | | | `GET` | `/api/monitor/cookie` | ✓ | Cookie health only -- deliberately never returns the cookie value. | `platform`(query string 可选='xhs') | | | `POST` | `/api/monitor/cookie` | ✓ | Set Cookie Endpoint | `platform`(query string 可选='xhs') | CookiePayload | | `GET` | `/api/monitor/covers/{note_id}` | ✓ | 作品封面,从本地缓存读。 | `note_id`(path string 必填) | | | `PUT` | `/api/monitor/creators/{creator_hash}` | ✓ | 给博主起个备注(界面上的「备注」)。 | `creator_hash`(path string 必填)
`platform`(query string 可选='xhs') | CreatorAliasPayload | | `GET` | `/api/monitor/events` | ✓ | List Events | `task_id`(query integer \| null 可选)
`type`(query string \| null 可选)
`since_id`(query integer \| null 可选)
`limit`(query integer 可选=200)
`platform`(query string \| null 可选) | | | `POST` | `/api/monitor/events/read` | ✓ | Mark Events Read | `task_id`(query integer \| null 可选) | | | `GET` | `/api/monitor/export` | ✓ | Download collected data as CSV or Excel. | `kind`(query string 必填)
`task_id`(query integer[] \| null 可选)
`note_id`(query string \| null 可选)
`start_date`(query string \| null 可选)
`end_date`(query string \| null 可选)
`days`(query integer 可选=7)
`format`(query string 可选='csv')
`platform`(query string \| null 可选) | | | `DELETE` | `/api/monitor/login/qr` | ✓ | Drop our tab and stop polling. | | | | `GET` | `/api/monitor/login/qr` | ✓ | Poll the live session: waiting -> success / expired / error. | | | | `POST` | `/api/monitor/login/qr` | ✓ | Open the login page in the CDP browser and return its QR code. | `platform`(query string 可选='xhs') | | | `GET` | `/api/monitor/login/state` | ✓ | Ask the browser itself whether it is signed in. | `force`(query boolean 可选=False) | | | `GET` | `/api/monitor/notes` | ✓ | List Notes | `task_id`(query integer \| null 可选)
`only_new`(query boolean 可选=False)
`limit`(query integer 可选=200)
`platform`(query string \| null 可选)
`tag_id`(query integer[] \| null 可选) | | | `PUT` | `/api/monitor/notes/{note_id}` | ✓ | 给**作品**起个备注。 | `note_id`(path string 必填)
`platform`(query string 可选='xhs') | NoteAliasPayload | | `GET` | `/api/monitor/notes/{note_id}/series` | ✓ | Metric time series for a single note. | `note_id`(path string 必填)
`task_id`(query integer \| null 可选) | | | `PUT` | `/api/monitor/notes/{note_id}/tags` | ✓ | 把一条作品的标签**整体替换**成这一组(空列表 = 全摘掉)。 | `note_id`(path string 必填)
`platform`(query string 可选='xhs') | NoteTagsPayload | | `GET` | `/api/monitor/overview` | ✓ | Headline numbers for the dashboard tiles, scoped to one platform. | `platform`(query string \| null 可选) | | | `GET` | `/api/monitor/report` | ✓ | Daily new-content counts and interaction deltas for the selected tasks. | `task_id`(query integer[] \| null 可选)
`start_date`(query string \| null 可选)
`end_date`(query string \| null 可选)
`days`(query integer 可选=7)
`platform`(query string \| null 可选) | | | `GET` | `/api/monitor/tags` | ✓ | 标签词表 + 各自被用在多少条作品上(删之前能看清代价)。 | | | | `POST` | `/api/monitor/tags` | ✓ | Create Tag | | TagPayload | | `DELETE` | `/api/monitor/tags/{tag_id}` | ✓ | 删标签,连同它在所有作品上的贴纸。 | `tag_id`(path integer 必填) | | | `PUT` | `/api/monitor/tags/{tag_id}` | ✓ | Update Tag | `tag_id`(path integer 必填) | TagPayload | | `GET` | `/api/monitor/tasks` | ✓ | List Tasks | `platform`(query string \| null 可选) | | | `POST` | `/api/monitor/tasks` | ✓ | Create Task | | MonitorTaskCreate | | `DELETE` | `/api/monitor/tasks/{task_id}` | ✓ | Delete Task | `task_id`(path integer 必填) | | | `PATCH` | `/api/monitor/tasks/{task_id}` | ✓ | Update Task | `task_id`(path integer 必填) | MonitorTaskUpdate | | `POST` | `/api/monitor/tasks/{task_id}/run` | ✓ | Queue a run immediately and return; the crawl itself takes minutes. | `task_id`(path integer 必填) | | | `GET` | `/api/monitor/tasks/{task_id}/runs` | ✓ | List Runs | `task_id`(path integer 必填)
`limit`(query integer 可选=50) | | | `GET` | `/api/monitor/upstream` | ✓ | 最近一次上游检查的结果。 | | | | `POST` | `/api/monitor/upstream/check` | ✓ | 立刻检查一次上游仓库,并把结果写回缓存。 | | | | `DELETE` | `/api/monitor/webhook` | ✓ | Clear Webhook | | | | `GET` | `/api/monitor/webhook` | ✓ | Get Webhook | | | | `POST` | `/api/monitor/webhook` | ✓ | Set Webhook | | WebhookPayload | | `POST` | `/api/monitor/webhook/test` | ✓ | Send a test message so the user can verify the robot works before relying on it. | | WebhookTestPayload | ## 设置 | 方法 | 路径 | 登录 | 说明 | 参数 | 请求体 | |---|---|:--:|---|---|---| | `GET` | `/api/settings` | ✓ | Settings for one platform, plus the system-wide ones. | `platform`(query string 可选='xhs') | | | `PUT` | `/api/settings` | ✓ | Partial update: only the keys present in the body are written. | `platform`(query string 可选='xhs') | SettingsUpdatePayload | ## 请求体结构 ### ChangePasswordPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `current` | string | ✓ | | | | `new` | string | ✓ | | | ### CookiePayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `cookie` | string | ✓ | | | ### CrawlerStartRequest | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `platform` | PlatformEnum | ✓ | | | | `login_type` | LoginTypeEnum | | 'qrcode' | | | `crawler_type` | CrawlerTypeEnum | | 'search' | | | `keywords` | string | | '' | | | `specified_ids` | string | | '' | | | `creator_ids` | string | | '' | | | `start_page` | integer | | 1 | | | `enable_comments` | boolean | | True | | | `enable_sub_comments` | boolean | | False | | | `enable_media` | boolean | | False | | | `save_option` | SaveDataOptionEnum | | 'jsonl' | | | `cookies` | string | | '' | | | `headless` | boolean | | False | | | `max_notes_count` | integer \| null | | | | | `max_comments_count` | integer \| null | | | | | `save_data_path` | string \| null | | | | | `enable_cdp_mode` | boolean \| null | | | | | `inject_all_cookies` | boolean \| null | | | | | `save_login_state` | boolean \| null | | | | | `cookies_file` | string \| null | | | | | `max_concurrency_num` | integer \| null | | | | | `crawler_max_sleep_sec` | integer \| null | | | | | `enable_ip_proxy` | boolean \| null | | | | | `ip_proxy_pool_count` | integer \| null | | | | | `ip_proxy_provider_name` | string \| null | | | | | `static_proxy_url` | string \| null | | | | ### CreatorAliasPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `alias` | string | | '' | | ### LoginPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `password` | string | ✓ | | | ### MonitorTaskCreate | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `name` | string | ✓ | | | | `platform` | string | | 'xhs' | | | `mode` | string | ✓ | | | | `interval_minutes` | integer \| null | | | | | `schedule_mode` | string | | 'interval' | | | `schedule_hours` | integer[] | | | | | `schedule_days` | integer[] | | | | | `schedule_minute` | integer | | 0 | | | `max_notes_count` | integer \| null | | | | | `enable_comments` | boolean | | True | | | `max_comments_count` | integer \| null | | | | | `run_timeout_seconds` | integer | | 3600 | | | `enabled` | boolean | | True | | | `notify_enabled` | boolean | | False | | | `notify_failures` | boolean | | True | | | `targets` | string[] | ✓ | | | ### MonitorTaskUpdate | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `name` | string \| null | | | | | `enabled` | boolean \| null | | | | | `interval_minutes` | integer \| null | | | | | `schedule_mode` | string \| null | | | | | `schedule_hours` | integer[] \| null | | | | | `schedule_days` | integer[] \| null | | | | | `schedule_minute` | integer \| null | | | | | `max_notes_count` | integer \| null | | | | | `enable_comments` | boolean \| null | | | | | `max_comments_count` | integer \| null | | | | | `run_timeout_seconds` | integer \| null | | | | | `notify_enabled` | boolean \| null | | | | | `notify_failures` | boolean \| null | | | | | `targets` | string[] \| null | | | | ### NoteAliasPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `alias` | string | | '' | | ### NoteTagsPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `tag_ids` | integer[] | | | | ### SettingsUpdatePayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| ### TagPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `name` | string | ✓ | | | | `color` | string | | '' | | ### WebhookPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `url` | string | | '' | 企业微信机器人 Webhook 地址,留空表示停用 | ### WebhookTestPayload | 字段 | 类型 | 必填 | 默认 | 说明 | |---|---|:--:|---|---| | `url` | string \| null | | | 不传则使用已保存的地址 | > **响应没有结构可列。** 这些接口返回的是普通 dict,没有声明 `response_model`,所以 OpenAPI 里没有响应的 shape。要看响应就调一次,或者读对应的 `service.py`。