Marrow Health
简
下载

把 Apple Health 数据发送到 webhook

Apple Health 没有网络 API,所以只有你 iPhone 上的应用主动发送,数据才会到达 webhook。Marrow Health 可以免费做到这一点:一个自动化会按你选的计划,在应用关闭的状态下,把你的健康指标、训练、力量组、饮食日记,或症状与心情,以 JSON 或 CSV 的形式 POST 到任意 URL。下面是设置方法、负载,以及 n8n、Home Assistant 和普通服务器上可用的接收端。Marrow 由我们开发。

设置自动化

  1. 在 Marrow Health 中打开“导出”标签页,选择自动,再点按新建自动化.
  2. 粘贴你的 webhook URL(请使用 HTTPS)。再添加接收端会检查的标题(请求头),比如 Authorization 承载令牌,或 n8n 的 header-auth 密钥。
  3. 选择数据类型:健康指标、训练、力量日志、饮食日记或症状与心情。一个自动化只发送一种,最多可以建十个。
  4. 选择 JSON 或 CSV、日期范围(默认是距离上次跑步),以及运行频率,单位可以是分钟、小时或天。
  5. 开启后点按立即运行,在你盯着接收端的同时发出第一份负载。

每个请求都是一个 POST,带有 Content-Type: application/json(或 text/csv)和你设置的标题。每次运行及其响应码都会列在应用中该自动化的历史记录里。

收到的内容

健康指标以每日总计的形式送达,单位见 units。心率给出每天的平均值、最小值和最大值,睡眠则按每晚给出各个阶段,以小时为单位:

{"data": {"metrics": [
  {"name": "body_mass", "units": "kg",
   "data": [{"date": "2026-09-11", "qty": 81.3}]},
  {"name": "step_count", "units": "count",
   "data": [{"date": "2026-09-11", "qty": 8746}]},
  {"name": "heart_rate", "units": "bpm",
   "data": [{"date": "2026-09-11", "Avg": 71, "Min": 52, "Max": 148}]},
  {"name": "sleep_analysis", "units": "h",
   "data": [{"date": "2026-09-11", "totalSleep": 7.2, "asleep": 7.2, "deep": 1.1, "rem": 1.6, "core": 4.3, "awake": 0.2,
             "sleepStart": "2026-09-10 23:36:00 -0400", "sleepEnd": "2026-09-11 07:02:00 -0400"}]}
]}}

训练、力量、营养和心情的负载、用原始样本代替每日总计的格式,以及 CSV 的排布,见自动化参考页面.

在 n8n 中接收

  1. 添加一个 Webhook 节点。把 HTTP Method 设为 POST,并给它一个路径,比如 apple-health.
  2. 如果要设密钥,把 Authentication 设为 Header Auth,并把同样的标题名称和值添加到 Marrow 的自动化里。
  3. 点击 Listen for test event,然后在两分钟内到 Marrow 里点按立即运行。负载会出现在编辑器中。
  4. 发布工作流,再让 Marrow 指向 Production URL(带 /webhook/ 的那个,不是 /webhook-test/)。测试 URL 在一次测试之后就不再监听。

负载在 body 下面,所以在表达式中,今天的步数是 {{ $json.body.data.metrics.find(m => m.name === 'step_count').data.at(-1).qty }}。在 body.data.metrics 上添加一个 Split Out 节点,就能把每项指标当作单独的条目来处理。n8n 默认接受最大 16 MB 的负载,足够容纳数年的每日总计。正式运行显示在 Executions 下,而不是编辑器里。 (n8n Webhook 文档)

在 Home Assistant 中接收

webhook 触发器在 /api/webhook/<webhook_id> 接收这个 POST。下面这个自动化把最新的步数存入名为 input_number.steps_today 的数字辅助元素(请先创建它,最大值要高于你步数最多的那天):

automation:
  - alias: "Apple Health from Marrow"
    triggers:
      - trigger: webhook
        webhook_id: "pick-a-long-random-id"
        allowed_methods:
          - POST
        local_only: false
    actions:
      - action: input_number.set_value
        target:
          entity_id: input_number.steps_today
        data:
          value: >-
            {{ ((trigger.json.data.metrics
                 | selectattr('name', 'eq', 'step_count') | first).data
                 | last).qty }}

(Home Assistant webhook 触发器文档)

在你自己的服务器上接收

任何接受 HTTPS POST 并返回 2xx 的端点都行。下面这个会把每份负载存档到一个文件里:

from http.server import BaseHTTPRequestHandler, HTTPServer
import time

class H(BaseHTTPRequestHandler):
    def do_POST(self):
        body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
        with open(f"marrow-{int(time.time())}.json", "wb") as f:
            f.write(body)
        self.send_response(200)
        self.end_headers()

HTTPServer(("0.0.0.0", 8798), H).serve_forever()

用 Cloudflare Tunnel、Tailscale Funnel 或反向代理把它放到 HTTPS 后面。如果你想要的是可查询的数据库,而不是一个文件夹,Marrow 的自托管镜像就是已经写好的这种接收端,AI 智能体也能查询它。

不丢数据的接收端要守的三条规则

它什么时候运行?

只要 iOS 允许 Marrow 运行就会运行:在它与 Apple Health 同步之后、你打开它时,以及后台刷新期间,前提是你选的间隔已过。后台刷新何时发生由 iOS 决定,所以整天锁屏的手机会在下次解锁时发送,距离上次跑步会补上这段空档。

其他做法