# Bio Radar Bot Integration API

> 面向其他机器人、Agent、自动化脚本和 RSS/信息聚合器的接入说明。本文档描述稳定的只读 API；管理、采集、创建 key 等操作仍由服务维护者通过 CLI 执行。

## 1. 服务定位

Bio Radar 是一个独立的生信/科研热点信息雷达服务，负责：

- 从 PubMed、期刊 RSS、arXiv 和机构/数据库 RSS 收集候选信息；
- 按白名单期刊和方向规则过滤；
- 对条目做去重、主题标签、评分排序；
- 自动补充中文标题 `title_zh` 和中文短摘要 `summary_zh`；
- 通过 JSON API 和 RSS Feed 供网站、机器人或其他客户端调用。

当前采集范围偏向：生物信息工具/方法/数据库/benchmark/workflow/model，以及微生物、动物、植物多组学/基因组相关研究；排除医学/临床/人类疾病/癌症/药物治疗及泛 AI/泛计算内容。

## 2. Base URL

推荐机器人使用独立 Bio Radar API：

```text
https://bioradar.pphd.top
```

本机/内网调试地址：

```text
http://127.0.0.1:18888
```

个人网站也有只读代理接口：

```text
https://pphd.top/api/bio-radar/...
```

但代理接口只覆盖网站展示需要的一部分能力，不建议其他机器人作为长期集成入口。机器人集成应优先使用 `https://bioradar.pphd.top/api/v1/...`。

## 3. 认证

除 `/health` 外，所有 API/RSS 接口都需要 API key。

推荐用 HTTP Bearer：

```http
Authorization: Bearer <BIO_RADAR_API_KEY>
```

curl 示例：

```bash
curl -H "Authorization: Bearer $BIO_RADAR_API_KEY" \
  'https://bioradar.pphd.top/api/v1/hot?window=7d&limit=10'
```

RSS 阅读器如果无法设置 Header，也可以使用 query token：

```text
https://bioradar.pphd.top/feeds/hot.xml?token=<BIO_RADAR_API_KEY>&limit=30
```

注意：query token 可能进入代理日志、浏览器历史或第三方 RSS 服务日志。机器人和服务端程序应优先使用 Header。

## 4. Scopes 权限

API key 按 scope 授权。给普通机器人通常只需要：

```text
items:read,topics:read,feeds:read,digest:read,search:read
```

可用 scope：

| Scope | 用途 |
|---|---|
| `items:read` | 读取条目、热点、期刊统计、主题条目 |
| `topics:read` | 读取主题列表 |
| `feeds:read` | 读取 RSS feed |
| `digest:read` | 读取每日摘要 |
| `search:read` | 搜索条目 |
| `sources:read` | 读取服务状态和 source 数量；通常只给维护机器人 |
| `admin:*` | 管理员通配；不要给普通机器人 |

## 5. 限速和配额

每个 API key 独立配置：

- 每分钟请求数：`rate_limit_per_minute`
- 每日配额：`quota_per_day`
- 每月配额：`quota_per_month`

触发限制时返回 `HTTP 429`，响应体里包含：

```json
{
  "detail": {
    "code": "rate_limited",
    "message": "Rate limit exceeded",
    "retry_after_seconds": 60
  }
}
```

机器人应按 `retry_after_seconds` 退避，不要紧密重试。建议客户端缓存 15–30 分钟；日报类机器人每天拉取 1–4 次即可。

## 6. 数据模型

### 6.1 ItemOut

大部分 JSON 接口返回 `ItemOut`。字段如下：

| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | string | Bio Radar 内部稳定 ID，可用于去重和详情查询 |
| `title` | string | 英文原题 |
| `title_zh` | string/null | 中文标题；只有检测为中文时才返回，否则为 null |
| `type` | string | 条目类型，常见为 `paper` / `resource` 等 |
| `url` | string | 原始链接或文献页面链接 |
| `abstract` | string/null | 英文摘要/简介 |
| `summary_zh` | string/null | 中文短摘要，通常 80 字以内；只有检测为中文时才返回 |
| `source` | string/null | 来源名 |
| `journal` | string/null | 期刊名；优先标准期刊名 |
| `published_at` | string/null | ISO 8601 时间。含义是在线/电子/PubMed 可见日期，不使用未来 issue 日期 |
| `doi` | string/null | DOI |
| `pmid` | string/null | PubMed ID |
| `arxiv_id` | string/null | arXiv ID |
| `tags` | string[] | 主题 tag 列表 |
| `score` | number/null | 综合评分，越高越推荐 |
| `why_it_matters` | string/null | 规则评分给出的推荐理由 |
| `suggested_use` | string/null | 建议用途，例如 `read`, `track`, `tool`, `database` 等 |

展示建议：

```python
display_title = item.get("title_zh") or item["title"]
display_summary = item.get("summary_zh") or item.get("abstract") or ""
```

### 6.2 ItemsResponse

```json
{
  "total": 123,
  "limit": 20,
  "offset": 0,
  "items": [/* ItemOut */]
}
```

分页使用 `limit` + `offset`。`limit` 最大通常为 500；主题 RSS 最大 100。

## 7. 主题 tags

当前主题 ID 和中文名：

| ID | 中文名 |
|---|---|
| `bioinformatics-tool` | 生信工具/方法 |
| `microbial-omics` | 微生物/微生物组 |
| `plant-omics` | 植物/作物组学 |
| `animal-omics` | 动物/进化基因组 |
| `wastewater-resource-recovery` | 污水处理/资源回收 |
| `synthetic-biology` | 合成生物学 |
| `genomics` | 基因组/泛基因组 |
| `transcriptomics` | 转录组/单细胞 |
| `multi-omics` | 多组学整合 |
| `gwas-qtl` | GWAS/QTL/育种 |
| `database-resource` | 数据库/资源/图谱 |
| `ai-biology` | AI/机器学习生物学 |
| `protein-structure` | 蛋白结构/工程 |

机器人不要把主题列表写死；应定期调用 `/api/v1/topics` 获取最新主题和 count。

## 8. Endpoint Reference

### 8.1 Health check

```http
GET /health
```

匿名可访问。用于探活，不消耗 API key 配额。

响应：

```json
{"status":"ok","service":"bio-radar"}
```

### 8.2 Service status

```http
GET /api/v1/status
Scope: sources:read
```

用于维护机器人检查 source 和 item 总数。

响应示例：

```json
{
  "status": "ok",
  "sources": 24,
  "items": 300
}
```

### 8.3 Topic list

```http
GET /api/v1/topics
Scope: topics:read
```

响应示例：

```json
{
  "topics": [
    {"id":"bioinformatics-tool","name":"生信工具/方法","count":42},
    {"id":"wastewater-resource-recovery","name":"污水处理/资源回收","count":18}
  ]
}
```

### 8.4 Journal statistics

```http
GET /api/v1/journals
Scope: items:read
```

返回当前数据库中有记录的期刊及数量，并带白名单等级。

响应示例：

```json
{
  "total": 3,
  "journals": [
    {"name":"Nature Methods","count":12,"level":"A+"},
    {"name":"Water Research","count":18,"level":"A"}
  ]
}
```

### 8.5 Hot items

```http
GET /api/v1/hot
Scope: items:read
```

常用热点列表接口。

Query 参数：

| 参数 | 类型 | 默认 | 说明 |
|---|---:|---:|---|
| `window` | string | `all` | 时间窗：`3d`, `7d`, `30d`, `365d`, `all` |
| `topic` | string | - | 只看某个主题 tag |
| `type` | string | - | 按条目类型过滤 |
| `journal` | string | - | 按标准期刊名过滤，需完全匹配 |
| `sort` | string | `latest` | `latest` 按日期；其他值按综合评分排序 |
| `limit` | int | 50 | 1–500 |
| `offset` | int | 0 | 分页偏移 |

示例：

```bash
curl -H "Authorization: Bearer $BIO_RADAR_API_KEY" \
  'https://bioradar.pphd.top/api/v1/hot?window=7d&topic=bioinformatics-tool&sort=hot&limit=10'
```

### 8.6 General item list

```http
GET /api/v1/items
Scope: items:read
```

更通用的条目列表接口。

Query 参数：

| 参数 | 类型 | 默认 | 说明 |
|---|---:|---:|---|
| `topic` | string | - | 主题 tag |
| `type` | string | - | 条目类型 |
| `journal` | string | - | 标准期刊名 |
| `sort` | string | `hot` | `latest` 按日期；其他值按评分 |
| `min_score` | number | - | 最低综合评分 |
| `limit` | int | 20 | 1–500 |
| `offset` | int | 0 | 分页偏移 |

示例：

```bash
curl -H "Authorization: Bearer $BIO_RADAR_API_KEY" \
  'https://bioradar.pphd.top/api/v1/items?journal=Water%20Research&min_score=40&limit=20'
```

### 8.7 Topic items

```http
GET /api/v1/topics/{topic}/items
Scope: items:read
```

按主题读取条目，默认按综合评分排序。

Query 参数：

| 参数 | 类型 | 默认 | 说明 |
|---|---:|---:|---|
| `limit` | int | 20 | 1–100 |
| `offset` | int | 0 | 分页偏移 |

示例：

```bash
curl -H "Authorization: Bearer $BIO_RADAR_API_KEY" \
  'https://bioradar.pphd.top/api/v1/topics/wastewater-resource-recovery/items?limit=10'
```

### 8.8 Item detail

```http
GET /api/v1/items/{item_id}
Scope: items:read
```

返回单条 `ItemOut`。

注意：当前未找到时返回：

```json
{"error":{"code":"not_found","message":"Item not found"}}
```

客户端应同时处理 HTTP 200 中带 `error` 字段的情况。

### 8.9 Search

```http
GET /api/v1/search
Scope: search:read
```

全文模糊搜索标题、中文标题、摘要、中文摘要、source、journal、DOI。

Query 参数：

| 参数 | 类型 | 默认 | 说明 |
|---|---:|---:|---|
| `q` | string | 必填 | 搜索词 |
| `limit` | int | 20 | 1–500 |
| `offset` | int | 0 | 分页偏移 |

示例：

```bash
curl -H "Authorization: Bearer $BIO_RADAR_API_KEY" \
  'https://bioradar.pphd.top/api/v1/search?q=spatial%20transcriptomics&limit=10'
```

### 8.10 Daily digest

```http
GET /api/v1/digest/daily
Scope: digest:read
```

返回适合日报/推送机器人的候选清单。当前实现按评分取 top items；`date` 主要作为响应日期标记。

Query 参数：

| 参数 | 类型 | 默认 | 说明 |
|---|---:|---:|---|
| `date` | string | 今天 | YYYY-MM-DD |
| `limit` | int | 8 | 1–20 |

响应示例：

```json
{
  "date": "2026-06-28",
  "title": "今日生信热点候选",
  "items": [/* ItemOut */]
}
```

### 8.11 RSS feeds

```http
GET /feeds/hot.xml
GET /feeds/topic/{topic}.xml
Scope: feeds:read
```

Query 参数：

| 参数 | 类型 | 默认 | 说明 |
|---|---:|---:|---|
| `limit` | int | 30 | 1–100 |
| `token` | string | - | 可选；RSS 客户端无法设置 Header 时使用 |

示例：

```bash
curl -H "Authorization: Bearer $BIO_RADAR_API_KEY" \
  'https://bioradar.pphd.top/feeds/topic/bioinformatics-tool.xml?limit=20'
```

RSS 当前主要输出英文原题和英文摘要；需要中文标题/摘要的机器人请优先使用 JSON API。

## 9. 错误格式

FastAPI 认证/限速错误通常使用：

```json
{
  "detail": {
    "code": "invalid_api_key",
    "message": "Invalid API key"
  }
}
```

常见错误：

| HTTP | code | 场景 | 客户端处理 |
|---:|---|---|---|
| 401 | `missing_api_key` | 没有传 key | 检查 Header/配置 |
| 401 | `invalid_api_key` | key 不正确 | 停止重试，联系维护者 |
| 403 | `disabled_api_key` | key 被禁用 | 停止重试，联系维护者 |
| 403 | `expired_api_key` | key 过期 | 停止重试，申请新 key |
| 403 | `insufficient_scope` | scope 不足 | 申请对应 scope |
| 429 | `rate_limited` | 每分钟限速 | 按 `retry_after_seconds` 退避 |
| 429 | `quota_exceeded` | 日/月配额超限 | 降低频率或申请更高配额 |
| 5xx | - | 服务临时异常 | 指数退避，稍后重试 |

## 10. 机器人接入建议

### 10.1 每日生信热点机器人

流程：

1. 每天固定时间调用 `/api/v1/digest/daily?limit=8`；
2. 使用 `title_zh || title` 作为标题；
3. 使用 `summary_zh || abstract[:160]` 作为摘要；
4. 附上 `journal`、`published_at`、`doi/pmid`、`url`；
5. 只推送候选清单，不自动生成正式解读，不自动发布到外部平台。

Python 示例：

```python
import os
import requests

BASE = "https://bioradar.pphd.top"
KEY = os.environ["BIO_RADAR_API_KEY"]

resp = requests.get(
    f"{BASE}/api/v1/digest/daily",
    params={"limit": 8},
    headers={"Authorization": f"Bearer {KEY}"},
    timeout=20,
)
resp.raise_for_status()
data = resp.json()

for item in data["items"]:
    title = item.get("title_zh") or item["title"]
    summary = item.get("summary_zh") or (item.get("abstract") or "")[:160]
    print(f"- {title}\n  {item.get('journal') or ''} | {item.get('published_at') or ''}\n  {summary}\n  {item['url']}")
```

### 10.2 主题监控机器人

适合盯单细胞、微生物、污水资源回收等方向：

```bash
curl -H "Authorization: Bearer $BIO_RADAR_API_KEY" \
  'https://bioradar.pphd.top/api/v1/hot?topic=wastewater-resource-recovery&window=30d&sort=latest&limit=20'
```

客户端应保存已处理的 `id`，下次只推送新 ID。

### 10.3 搜索/问答机器人

用户问“最近有什么空间转录组工具？”时：

1. 先调用 `/api/v1/search?q=spatial transcriptomics tool&limit=10`；
2. 如果结果太泛，再加 topic 走 `/api/v1/hot?topic=transcriptomics&window=365d&limit=20`；
3. 回答时引用 `url`/`doi`，不要臆造结论。

### 10.4 RSS 聚合器

不能设置 Header 时：

```text
https://bioradar.pphd.top/feeds/hot.xml?token=<API_KEY>&limit=30
https://bioradar.pphd.top/feeds/topic/bioinformatics-tool.xml?token=<API_KEY>&limit=30
```

RSS 适合机器拉取和粗略聚合；需要中文摘要、score、tags、DOI/PMID 等结构化字段时用 JSON。

## 11. 客户端最佳实践

- **缓存**：热点/主题列表缓存 15–30 分钟；日报缓存 1–12 小时。
- **去重**：优先用 `id`；跨系统可辅以 DOI、PMID、URL。
- **排序**：`sort=latest` 适合“最新动态”；`sort=hot` 或默认评分适合“值得关注”。
- **中文显示**：`title_zh`/`summary_zh` 非空时优先；为空时回退英文。
- **日期解释**：`published_at` 表示在线/电子/PubMed 可见日期，不是未来 issue 日期。
- **安全**：不要把 API key 放进前端 JS、公开仓库、截图或日志。
- **退避**：遇到 429/5xx 用指数退避，不要循环重试。
- **引用**：机器人总结时应带原始 URL、DOI 或 PMID，避免把候选清单说成确定结论。
- **发布边界**：Bio Radar 只提供候选信息；不要自动生成正式文献解读页面或自动对外发布，除非维护者另行确认。

## 12. Machine-readable API spec

本仓库同时提供机器可读 OpenAPI 文件：

```text
docs/bot-api.openapi.json
```

外部机器人可以用它生成客户端，但仍应以本文档中的字段解释、展示建议和限速策略为准。
