> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirobody.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 数据

> POST /v1/data、GET /v1/data、DELETE /v1/data —— 写入、读取与擦除结构化健康记录。

把结构化记录直接写进 Subject 的存储，并读回。每次写入都会经过平台的[标准化管线](/zh/api-reference/standardization)：解析值与单位，为识别出的指标补充 LOINC 编码和规范名称，并镜像到 FHIR。未编码的行仍可正常读取。Agent 通过内置工具读取同一份数据。

健康数据有四种形态 —— 每种形态各有一扇门进来：

| 数据形态       | 典型来源                          | 录入方式    | 端点                                                                                                                                                |
| ---------- | ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **结构化读数**  | 设备/穿戴（**由你自己接入**，日聚合后写入）、手动记录 | 结构化记录   | [`POST /v1/data`](/zh/api-reference/data) —— 高频样本先自聚合；episode 型（睡眠、运动）用 `time` + `end_time` 携带时段。见[设备数据 cookbook](/zh/api-reference/device-data)。 |
| **文件/照片**  | 化验单、体检报告 PDF、手机拍照             | 文件上传    | [`POST /v1/files`](/zh/api-reference/files) —— 保存原件并抽取文本；将 `file_key` 传给 [`POST /v1/standardize`](/zh/api-reference/extract) 可创建结构化读数             |
| **带读数的叙事** | "头疼了一天，体温 38.2 °C"、对话口述       | 叙事文本    | [`POST /v1/standardize`](/zh/api-reference/extract) —— 抽取其中的可量化读数，周边叙事被丢弃                                                                         |
| **纯主观日记**  | "整个下午头晕头疼"、心情记录               | 单轮智能体调用 | [`POST /v1/responses`](/zh/api-reference/responses) 带 `store: true` —— 后台固化抽出指标与持久记忆。见[写日记配方](/zh/api-reference/state-and-memory#写日记journaling)。  |

Mirobody 负责存储源数据、标准化结构化读数，并将二者提供给 AI 使用；数据如何采集、是否预处理，由你自行决定。

<Note>
  **`user` 字段是租户隔离键。** 后端把 `(你的账户, user)` 映射为内部的**数据主体(Subject)**；你传入的每个 `user` 彼此完全隔离。为每个终端用户传入其稳定 id，数据就绝不会串。省略时回落到你账户的默认 Subject。Subject 对 Mirobody 消费端 App 和其他开发者均不可见。`user` 值在映射前会被归一化（去首尾空白 + 转小写），`Alice` 与 `alice` 解析为**同一个** Subject —— 请传入稳定、规范的 id。
</Note>

## 写入记录

```http theme={null}
POST /v1/data
Authorization: Bearer mb_live_*
Content-Type:  application/json
```

| 字段           | 类型     | 说明                                                                                                                                                                                                                                         |
| ------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `records`    | array  | 每条记录 `{indicator, value, unit?, time?, end_time?, source?}`。**每次请求最多 500 条。** `end_time`（可选，ISO 时间）标记 episode 的结束 —— 睡眠、运动 —— 其起点为 `time`。`measured_at` / `start_time` 是 `time` 的别名 —— POST /v1/standardize 返回的行（字段名为 `measured_at`）可原样转发。 |
| `user`       | string | 记录所属的 Subject（租户隔离键）。                                                                                                                                                                                                                      |
| `retention`  | string | **必填 —— 没有默认值。** 取值为 `permanent` / `1h` / `2h` / `6h` / `1d` / `session` 之一（`persistent` 作为 `permanent` 的别名也接受）。小时粒度在写入后按时长自动删除（硬上限 ≤ 24h）。省略它 —— 或传枚举之外的任何值 —— 返回 `400`（`code: invalid_retention`）。                                       |
| `session_id` | string | **`retention=session` 时必填**（否则 `400`，`code: invalid_session`）。应使用全局唯一、不含业务语义的 id（如 UUID），且不能跨 Subject 复用。它为记录打标签，使 [`DELETE /v1/sessions/{id}`](/zh/api-reference/lifecycle#会话) 能清除它们。                                                     |

```bash theme={null}
curl https://api.mirobody.ai/v1/data \
  -H "Authorization: Bearer $MIROBODY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "user": "alice",
        "retention": "permanent",
        "records": [
          {"indicator": "fasting_glucose", "value": 97, "unit": "mg/dL", "time": "2026-06-16T07:30:00Z"},
          {"indicator": "fasting_glucose", "value": 92, "unit": "mg/dL", "time": "2026-06-17T07:25:00Z"}
        ]
      }'
```

响应 —— `standardized` 统计写入途中成功解析到 LOINC 编码的记录数：

```json theme={null}
{ "status": "ok", "ingested": 2, "standardized": 2, "subject": "alice" }
```

<Note>
  **每次写入都会运行标准化，而不只是存储。** 每条记录的值/单位会做 UCUM 解析，指标名称通过确定性匹配解析到 LOINC（curated 语料 + embedding —— 不让 LLM 猜码）；低置信度匹配会保留为未编码。见[标准化](/zh/api-reference/standardization)。想在不写入的情况下预览这条管线，请用 [`POST /v1/standardize`](/zh/api-reference/extract) 的 `store=false`。
</Note>

<Warning>
  写入不具备幂等性。重试可能生成重复读数；请求超时时应先核对结果，再决定是否重试，并在调用方维护写入账本。
</Warning>

### Episode 型（睡眠、运动）

Episode 型记录跨越一个时段而非时间点 —— 起点放 `time`，终点放可选的 `end_time`：

```bash theme={null}
curl https://api.mirobody.ai/v1/data \
  -H "Authorization: Bearer $MIROBODY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "user": "alice",
        "retention": "permanent",
        "records": [
          {"indicator": "sleep_duration", "value": 7.5, "unit": "h",
           "time": "2026-07-09T23:10:00Z", "end_time": "2026-07-10T06:40:00Z",
           "source": "garmin"}
        ]
      }'
```

规模化写入设备数据（日聚合、批量、厂商接入）？见[设备数据 cookbook](/zh/api-reference/device-data)。

## 读取记录

```http theme={null}
GET /v1/data?user=alice&indicator=fasting_glucose&limit=100
Authorization: Bearer mb_live_*
```

| Query       | 说明                                                                |
| ----------- | ----------------------------------------------------------------- |
| `user`      | 读取哪个 Subject。                                                     |
| `indicator` | 可选，按指标名过滤（子串匹配）。                                                  |
| `limit`     | `1`–`1000`（默认 `100`）。                                             |
| `offset`    | 跳过 N 条用于翻页(排序稳定:最新在前)。`has_more: true` 时用 `offset += limit` 取下一页。 |

响应为 OpenAI 风格的列表，最新在前。`value` 是**人读字符串**（如 `"97 mg/dL"`）；机读字段并列返回：

```json theme={null}
{
  "object": "list",
  "data": [
    {
      "id": 1287,
      "indicator": "fasting_glucose",
      "value": "97 mg/dL",
      "parsed_value": "97",
      "parsed_unit": "mg/dL",
      "loinc_code": "1558-6",
      "canonical_name": "Fasting glucose [Mass/volume] in Serum or Plasma",
      "fhir_resource_id": "8f3c9a1e-...",
      "time": "2026-06-16T07:30:00+00",
      "end_time": null,
      "source": "api",
      "comment": ""
    }
  ],
  "has_more": false,
  "subject": "alice"
}
```

| 字段                                                                 | 说明                                                                            |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------- |
| `data`                                                             | 记录数组（至多 `limit` 条）。                                                           |
| `id`                                                               | 行 id（整数）—— 传给 `DELETE /v1/data?id=` 做行级删除。                                    |
| `value`                                                            | 人读读数（字符串）。                                                                    |
| `parsed_value` / `parsed_unit`                                     | 标准化管线产出的数值 + **UCUM** 单位（无法解析时为 `null`）。                                      |
| `loinc_code` / `canonical_name`                                    | 确定性 LOINC 解析结果及其展示名（名称未解析时为 `null`）。                                          |
| `fhir_resource_id`                                                 | 该记录 FHIR Observation 镜像的 id。                                                  |
| `end_time`                                                         | Episode 型记录（睡眠、运动）时段的结束时间；时间点读数为 `null`。                                      |
| `reference_low` / `reference_high` / `reference_text` / `abnormal` | 参考范围与异常标记，来源（如化验单）携带时返回；否则为 `null`。                                           |
| `source` / `comment`                                               | `source` 表示**写入通道**（`api`、`extract`）；你在记录里传的 `source` 自由文本标签会在 `comment` 中返回。 |
| `has_more`                                                         | 本页打满 `limit` 时为 `true`——用 `offset += limit` 取下一页。                             |
| `subject`                                                          | 记录所属的 Subject（由 `user` 解析）。                                                   |

## 擦除记录

```http theme={null}
DELETE /v1/data?user=alice&indicator=fasting_glucose
Authorization: Bearer mb_live_*
```

**永久擦除**该 Subject 的记录 —— 被遗忘权语义（数据被真正移除，而非仅从读取中隐藏）。三种范围，由窄到宽：

| Query       | 范围                                                     |
| ----------- | ------------------------------------------------------ |
| `id`        | 恰好**一行** —— 即 `GET /v1/data` 返回的整数 id。优先于 `indicator`。 |
| `indicator` | 单个指标（子串匹配，与 GET 过滤一致）。                                 |
| *（都不传）*     | 该 Subject 的**全部**记录。                                   |

```http theme={null}
DELETE /v1/data?user=alice&id=1287
```

```json theme={null}
{ "status": "ok", "deleted": 1, "subject": "alice" }
```

如需一次性擦除某个 Subject 的*一切*（记录 + 文件 + 对话 + 身份映射），使用 [`DELETE /v1/subjects/{user}`](/zh/api-reference/lifecycle#下线一个-subject) —— 见[合规](/zh/api-reference/compliance)。

## 用完即弃的数据

**没有 `retention: "none"`** —— 写入存储却要求不存储是自相矛盾的，该值与其它非枚举值一样被拒绝。两种干净的替代模式：

* **零副作用的 dry-run 分析** —— [`POST /v1/standardize`](/zh/api-reference/extract) 用 `store=false`（默认）：拿到标准化结果，什么都不写。
* **短生命周期工作数据** —— 以 `retention: "1h"` 写入（一小时后[自动过期](/zh/api-reference/overview#数据留存)），或以 `retention: "session"` + 一个用完即[删](/zh/api-reference/lifecycle#会话)的 `session_id` 写入。
