数据面
数据
POST /v1/data、GET /v1/data、DELETE /v1/data —— 写入、读取与擦除结构化健康记录。
把结构化记录直接写进 Subject 的存储,并读回。每次写入都会经过平台的标准化管线:解析值与单位,为识别出的指标补上 LOINC 编码和规范名称,每条记录都镜像到 FHIR。未解析出编码的行仍可正常读取。agent 通过内置工具读取同一份数据。
健康数据有四种形态 —— 每种形态各有一扇门进来:
| 数据形态 | 典型来源 | 录入方式 | 端点 |
|---|---|---|---|
| 结构化读数 | 设备/穿戴(由你自己接入,日聚合后写入)、手动记录 | 结构化记录 | POST /v1/data —— 高频样本先自聚合;episode 型(睡眠、运动)用 time + end_time 携带时段。见设备数据 cookbook。 |
| 文件/照片 | 化验单、体检报告 PDF、手机拍照 | 文件上传 | POST /v1/files —— 保存原件、抽取文本,并自动抽出标准化读数。POST /v1/standardize 可同步执行同一抽取,例如做 dry-run 预览。 |
| 带读数的叙事 | “头疼了一天,体温 38.2 °C”、对话口述 | 叙事文本 | POST /v1/standardize —— 抽取其中的可量化读数,周边叙事被丢弃。 |
| 纯主观日记 | “整个下午头晕头疼”、心情记录 | 单轮智能体调用 | POST /v1/responses 带 store: true —— 自动从中抽取读数与持久记忆。见写日记配方。 |
Mirobody 负责存储源数据、标准化结构化读数,并将二者提供给 AI 使用;数据如何采集、是否预处理,由你自行决定。
POST /v1/dataAuthorization: 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 的别名也接受)。有时限的档位到期即自动删除 —— 1d 是最长的一档。省略它 —— 或传枚举之外的任何值 —— 返回 400(code: invalid_retention)。 |
session_id | string | retention=session 时必填(否则 400,code: invalid_session)。应使用全局唯一、不含业务语义的 id(如 UUID),且不能跨 Subject 复用。它为记录打标签,使 DELETE /v1/sessions/{id} 能清除它们。 |
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 编码的记录数:
{ "status": "ok", "ingested": 2, "standardized": 2, "subject": "alice" }Episode 型(睡眠、运动)
Section titled “Episode 型(睡眠、运动)”Episode 型记录跨越一个时段而非时间点 —— 起点放 time,终点放可选的 end_time:
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。
GET /v1/data?user=alice&indicator=fasting_glucose&limit=100Authorization: Bearer mb_live_*| Query | 说明 |
|---|---|
user | 读取哪个 Subject。 |
indicator | 可选,按指标名过滤(子串匹配)。 |
limit | 1–1000(默认 100)。 |
offset | 跳过 N 条用于翻页(排序稳定:最新在前)。has_more: true 时用 offset += limit 取下一页。 |
响应为 OpenAI 风格的列表,最新在前。value 是原样写入的值(如 "97"),单位单独放在 parsed_unit 中,与其它机读字段一同返回:
{ "object": "list", "data": [ { "id": 1287, "indicator": "fasting_glucose", "value": "97", "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 | 原样写入的值(字符串,如 "97");单位放在 parsed_unit 中。 |
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 | 记录的来源方式:api(经 POST /v1/data 写入)、extract(来自 POST /v1/standardize)、upload(从 /v1/files 上传中读出)或 consolidation(从已存储的对话中得来)。你在记录自己的 source 字段里传入的来源标签,会在 comment 中返回。 |
has_more | 本页打满 limit 时为 true —— 用 offset += limit 取下一页。 |
subject | 记录所属的 Subject(由 user 解析)。 |
DELETE /v1/data?user=alice&indicator=fasting_glucoseAuthorization: Bearer mb_live_*永久擦除该 Subject 的记录 —— 被遗忘权语义(数据被真正移除,而非仅从读取中隐藏)。三种范围,由窄到宽:
| Query | 范围 |
|---|---|
id | 恰好一行 —— 即 GET /v1/data 返回的整数 id。优先于 indicator。 |
indicator | 单个指标(子串匹配,与 GET 过滤一致)。 |
| (都不传) | 该 Subject 的全部记录。 |
DELETE /v1/data?user=alice&id=1287{ "status": "ok", "deleted": 1, "subject": "alice" }如需一次性擦除某个 Subject 的一切(记录 + 文件 + 对话 + 身份映射),使用 DELETE /v1/subjects/{user} —— 见合规。
用完即弃的数据
Section titled “用完即弃的数据”没有 retention: "none" —— 写入存储却要求不存储是自相矛盾的,该值与其它非枚举值一样被拒绝。两种干净的替代模式:
- 零副作用的 dry-run 分析 ——
POST /v1/standardize用store=false(默认):拿到标准化结果,什么都不写。 - 短生命周期工作数据 —— 以
retention: "1h"写入(一小时后自动过期),或以retention: "session"+ 一个用完即删的session_id写入。