Marrow Health
HE
הורדה

שליחת נתוני Apple Health ל-webhook

ל-Apple Health אין API לרשת, ולכן הנתונים שלכם מגיעים ל-webhook רק כשאפליקציה ב-iPhone שולחת אותם. Marrow Health עושה זאת בחינם: אוטומציה שולחת POST עם מדדי הבריאות, האימונים, סטי הכוח, יומן התזונה או התסמינים ומצב הרוח שלכם לכל כתובת, כ-JSON או כ-CSV, לפי הלוח שתבחרו, כשהאפליקציה סגורה. להלן ההגדרה, המטען, ומקבלים שעובדים עבור n8n, Home Assistant ושרת פשוט. אנחנו מפתחים את Marrow.

הגדרת האוטומציה

  1. ב-Marrow Health, פתחו את לשונית ייצוא, ואז אוטומטי, ואז אוטומציה חדשה.
  2. הדביקו את כתובת ה-webhook שלכם (השתמשו ב-HTTPS). הוסיפו את הכותרות שהמקבל שלכם בודק, כמו אסימון bearer של Authorization או מפתח header-auth של n8n.
  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/). כתובת הבדיקה מפסיקה להאזין אחרי בדיקה אחת.

המטען נמצא תחת body, ולכן הצעדים של היום הם {{ $json.body.data.metrics.find(m => m.name === 'step_count').data.at(-1).qty }} בביטוי. הוסיפו צומת Split Out על body.data.metrics כדי לטפל בכל מדד כפריט נפרד. n8n מקבל כברירת מחדל מטענים עד 16 MB, מה שמכסה שנים של סיכומים יומיים. הרצות בייצור מופיעות תחת Executions, לא בעורך. (תיעוד n8n Webhook)

קבלה ב-Home Assistant

טריגר webhook מקבל את ה-POST בכתובת /api/webhook/<webhook_id>. האוטומציה הזו שומרת את ספירת הצעדים האחרונה בעזר מספרי בשם 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 }}

(תיעוד הטריגר webhook של Home Assistant)

קבלה בשרת שלכם

כל נקודת קצה שמקבלת POST ב-HTTPS ועונה 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()

שימו אותה מאחורי HTTPS עם Cloudflare Tunnel, Tailscale Funnel או reverse proxy. אם אתם מעדיפים מסד נתונים שאפשר לשאול עליו שאילתות במקום תיקייה של קבצים, המראה באירוח עצמי של Marrow היא המקבל הזה כבר כתוב, וגם סוכני AI יכולים לשאול אותה.

שלושה כללים למקבל שאף פעם לא מאבד נתונים

מתי זה רץ?

בכל פעם ש-iOS מאפשר ל-Marrow לרוץ: אחרי סנכרון עם Apple Health, כשפותחים אותו, ובמהלך רענון ברקע, אחרי שעבר המרווח שבחרתם. iOS מחליט מתי רענון ברקע קורה, ולכן טלפון שנשאר נעול כל היום שולח כשיפתחו אותו שוב, ומאז הריצה האחרונה מכסה את הפער.

דרכים אחרות לעשות את זה