把 Apple Health 資料傳送到 webhook
Apple Health 沒有網路 API,所以只有 iPhone 上的 App 把資料送出去,你的 webhook 才收得到。Marrow Health 免費提供這項功能:自動化操作會依你選的排程,在 App 關閉的情況下,把你的健康指標、體能訓練、重訓組數、飲食日記,或症狀與心情,以 JSON 或 CSV 格式 POST 到任何網址。下面有設定方式、資料內容,以及 n8n、Home Assistant 和一般伺服器可用的接收端範例。Marrow 是我們做的。
設定自動化操作
- 在 Marrow Health 中,打開「匯出」分頁,再點自動化,然後點新增自動化操作.
- 貼上你的 webhook 網址(請用 HTTPS)。加上接收端會檢查的標頭,例如
Authorizationbearer token 或 n8n 的 header-auth 金鑰。 - 選擇資料種類:健康指標、體能訓練、重訓記錄、營養日記,或症狀與心情。一個自動化操作只送一種資料,最多可以建立十個。
- 選擇 JSON 或 CSV、日期範圍(預設是自上次跑步以來),以及執行頻率,可設為幾分鐘、幾小時或幾天。
- 開啟它,點一下立即執行,一邊看著接收端,一邊送出第一筆資料。
每個請求都是一個 POST,帶有 Content-Type: application/json(或 text/csv)和你設定的標頭。每次執行和它的回應碼,都會列在 App 內該自動化操作的記錄裡。
會收到什麼
健康指標以每日總計的形式送達,單位就是 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 接收
- 新增一個 Webhook 節點。把 HTTP Method 設為
POST,並給它一個路徑,例如apple-health. - 如果要設密鑰,請把 Authentication 設為 Header Auth,並在 Marrow 自動化操作中加入相同的標頭名稱和值。
- 點 Listen for test event,然後在兩分鐘內到 Marrow 點立即執行。資料內容就會出現在編輯器裡。
- 發布工作流程,並讓 Marrow 指向 Production URL(含
/webhook/的那個,不是/webhook-test/)。測試網址在測試之後就不再監聽。
資料內容在 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 }}
- JSON 內容在
trigger.json裡,因為 Marrow 送出的是Content-Type: application/json. local_only預設為開啟,只接受來自你家中網路或 Nabu Casa 雲端 webhook 網址的 POST。如果手機是透過網際網路 POST 到你自己的 HTTPS 位址,請把它設為false。- Webhook ID 是唯一的密鑰,所以請設得又長又隨機。
(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 智慧代理也能查詢它。
讓接收端永不遺失資料的三個原則
- 以最新為準。每個值依指標和日期儲存,重複時就覆寫。自上次跑步以來會刻意重送最近兩天,因為 Apple Health 在一天結束後還會繼續補資料。
- 先存下原始內容,再解析。剖析錯誤絕不該讓你損失資料。
- 快速回應。Marrow 最多會等你設定的逾時時間(預設 60 秒),失敗的那次執行會在下一輪從上一次成功的區間重試。
什麼時候會執行?
只要 iOS 允許 Marrow 執行就會:與 Apple Health 同步後、你打開它時,以及背景更新期間,只要你選的間隔時間已過。背景更新何時進行由 iOS 決定,所以整天鎖著的手機,會在下次解鎖時送出,而自上次跑步以來會補上中間的空檔。
其他做法
- Health Auto Export 也會把 Apple Health 資料 POST 到 webhook,它的指標 JSON 結構與 Marrow 相同。它的自動化功能需要 Premium 方案。
- Apple 捷徑可以讀取健康樣本,並用取得 URL 內容送出,搭配固定時間的個人自動化。它免費,但只有在手機解鎖時才能讀取健康資料,而且每個指標都要你自己建立和維護。
- Apple 的 export.zip 是一次性的完整備份,不是持續的資料流。要把它轉成 CSV,請用我們的瀏覽器內轉換器.