---
title: REST API 通道
description: 宿主实现一组 REST 资源 endpoint(GET + 游标),PAC 按间隔主动拉取的存量加增量统一通道。
icon: Webhook
---

> **一句话**:宿主实现一组只读 REST 资源 endpoint(每类业务一个,GET + 游标分页),PAC 按间隔主动 `GET` 拉,**存量 + 增量同一通道**。
>
> **适用对象**:有业务系统能直出 HTTP JSON、但没把数据 ETL 进数仓的宿主(典型 = OLTP 直供,无 DW)。已有 ClickHouse 数仓的走 [CH 视图](/docs/integration/channel-clickhouse) 成本更低。
>
> **状态**:Pull 三种数据源之一(文件 / [CH 直连](/docs/integration/channel-clickhouse) / REST API)。**REST 适配器 PAC 侧开发中** —— 接口契约稳定,宿主可照本文档先行实现;PAC 侧首个宿主接入时实装鉴权策略(api-key / session / OAuth2)。

---

## 1. 跟其它 Pull 源的关系

三种 Pull 源**数据形态完全一致**,共用同一份[数据字典](/docs/integration/data-request-checklist),切换零返工 —— 区别只在承载协议:

| 源 | 承载 | 增量机制 | 宿主侧工作 |
|---|---|---|---|
| 文件(CSV/JSON) | 裸表文件 | 重新导出 | `SELECT *` 导出 |
| [CH 视图](/docs/integration/channel-clickhouse) | ClickHouse 行 | 视图内单调列 + SQL `WHERE` | 建视图 + 给只读账号 |
| **REST API(本文档)** | **HTTP JSON** | **`?after=<游标>` 查询参数** | **实现资源 endpoint** |

存量(首次无游标的全量,即业内 cold-import)与增量(游标)走**同一条 pull 路径**,只是有无游标之别 —— 宿主不用单独再做一次性 dump。

---

## 2. 资源 endpoint 清单

每个 endpoint = host 侧一张表 / 视图行直出,字段命名 / 嵌套 / 枚举编码**宿主自由**,PAC 侧统一做 raw → canonical 映射(跟文件 / CH / push 共用同一份字典)。

**14 个 endpoint 跟 [数据请求清单](/docs/integration/data-request-checklist) §1 的数据类别一一对齐**(同一份数据字典两路通用)。

> 每行**必带的列**(业务主键 / 患者外键 / 诊所 / 命名空间 / 更新时间)三种 Pull 源通用 —— 见 [数据请求清单 · 每张表必带的列](/docs/integration/data-request-checklist)。

| Endpoint key          | 含义                              | 必/选             |
| --------------------- | ------------------------------- | --------------- |
| `patients`            | 患者主档                            | 🔴 必            |
| `appointments`        | 预约 + 状态变更                       | 🔴 必            |
| `clinical_encounters` | 医生接诊(可嵌套 1:N 子表)                | 🔴 必            |
| `emr_documents` ⭐     | 电子病历(诊断 / 治疗主要载体)               | 🔴 必            |
| `image_studies` ⭐     | 影像 metadata + 医生 finding(无文件本体) | 🔴 必            |
| `orders`              | 收费单 / 医嘱(治疗 / 耗材 / 药品)+ 明细       | 🔴 必            |
| `payments`            | 收款                              | 🔴 必            |
| `recharges`           | 充值 / 储值 / 福利卡                   | 🟠 强烈推荐(精确 LTV) |
| `complaints`          | 投诉                              | 🟠 强烈推荐(合规硬约束)  |
| `referrals`           | 转介绍                             | 🟠 强烈推荐(渠道归因)   |
| `refunds`             | 退费                              | 🟡 可选           |
| `consultations`       | 咨询                              | 🟡 可选           |
| `visit_registrations` | 挂号                              | 🟡 可选           |
| `visit_receptions`    | 接待登记                            | 🟡 可选           |

> **1:N 子表**(如接诊主表 + 诊断 / 治疗子表):在 endpoint 返回里把子表数组嵌套进主对象(一行 = 完整业务对象),避免 PAC 侧多次查询。

---

## 3. 统一响应 envelope

所有 endpoint 走全局[响应信封](/docs/error-codes) —— **HTTP 恒 `200`**,业务结果看 `code`。

```jsonc
// 成功
{
  "code": 0,
  "msg":  "ok",
  "data": {
    "items":      [ /* ...资源对象数组... */ ],
    "nextCursor": "string | null"      // null = 没有更多
  }
}

// 失败
{ "code": 10101, "msg": "...", "data": null, "details": null }
```

- 每页 100-200 条,上限 500
- 业务异常通过 envelope `code` 区分(码表见[响应信封与错误码](/docs/error-codes);建议复用 PAC code 表,联调日志好对齐)

---

## 4. 增量游标

```text
GET <endpoint>?after=<cursor>&limit=200
```

- Cursor 形态:ISO 8601 时间戳 或 宿主自定义 opaque string
- **必须单调递增**(不能跳)
- 首次拉取 `after` 省略 / `null`(从最早开始)→ 即存量全量
- 推荐 host 关键资源**逻辑删除 + 更新 `updatedAt`**,避免物删产生"幻读"

PAC 每个 `(host, resource)` 维护一条独立游标,`nextCursor=null` 时跳到下个 cron 周期。

---

## 5. 单患者即时刷新

客服工作台"刷新"按钮触发,拉该患者**当前态全量**(不限增量):

```text
GET <endpoint>?patientExternalId=P00012345
```

- 返回该患者所有相关资源的当前态
- PAC 侧 **30s in-flight 去重 + 60s 冷却**,跟每日增量游标完全隔离,宿主不用担心被刷爆
- endpoint 不支持单患者过滤 → PAC 返回 `30804`(该平台不支持单患者即时刷新),功能降级但不影响每日增量

---

## 6. 错误处理

| 场景 | 宿主返回 | PAC 行为 |
|---|---|---|
| 正常 | `code=0` + items + nextCursor | 消化 + 推 cursor |
| 已最新无更多 | `code=0` + `items=[]` + `nextCursor=null` | 跳过到下个 cron |
| 鉴权失败 | `code=10101` | 触发凭证告警,暂停拉取 |
| 单患者找不到 | `code=10301` | 标 archived |
| 限流 | `code=10003` | 指数退避重试 |
| 内部异常 | `code` 属于 `90xxx` 或 HTTP `5xx` | 重试 3 次 → partial |

---

## 7. 鉴权(PAC 调宿主 endpoint)

PAC 作为客户端调宿主 endpoint,凭据由**宿主颁发给 PAC**(推荐 Bearer `apiKey`)。PAC 侧鉴权策略首个宿主接入时按其形态实装:

| 策略 | 适用 |
|---|---|
| api-key | Bearer token(推荐) |
| http-login | Session cookie |
| oauth2 | OAuth2 / OIDC |

> 注意区分方向:这里是 **PAC → 宿主**(拉数据)。**宿主 → PAC** 的接入换票(iframe 登录态)是另一条链路,见 [登录授权](/docs/integration/auth-login)。

---

## 8. 接入 Checklist(宿主自查)

### 必填
- [ ] 7 个必填 endpoint 实现(`patients` / `appointments` / `clinical_encounters` / `emr_documents` / `image_studies` / `orders` / `payments`)
- [ ] 所有 endpoint 走统一 envelope(`{ code, msg, data, details? }`)
- [ ] 增量 cursor 测试通过(`after` 省略 → 全量;追到末页 `nextCursor=null`)
- [ ] 单患者 pull 实现(`?patientExternalId=...`)
- [ ] PAC 调用凭据(`apiKey`)发给 PAC 团队
- [ ] 数据字典交付(参考 [数据字典示例](/docs/integration/data-dictionary))
- [ ] 试点 clinic 已在 endpoint 侧过滤
- [ ] **字段 / schema 变更提前 2 周通知 PAC**

### 强烈推荐
- [ ] 3 个推荐 endpoint(`recharges` / `complaints` / `referrals`)
- [ ] 1:N 子表已嵌套进主对象(避免 PAC 多次查询)
- [ ] 关键资源逻辑删除 + `updatedAt`(避免物删幻读)

---

## 9. 不在本通道范围的事

REST 通道只覆盖"数据接入"那一段;鉴权换票 / iframe 嵌入 / actionUrls 是独立链路(跟选哪种通道无关),见 [数据请求清单 §8](/docs/integration/data-request-checklist)。

---

**联系**:endpoint 字段含义 / 性能 / 鉴权策略,找 PAC 接入对接人。
