Connect Apple Health to ChatGPT via Webhook: Your Data, Their Agent

By the end of this page ChatGPT reads your real Apple Health numbers as clean JSON, sent from your iPhone to an endpoint you own, with you deciding what reaches OpenAI. The exact receiver to run, the payload your iPhone sends, the prompts that work, and where privacy holds (and where it does not).

By MetricBridge · Published 3 August 2026 · Updated 27 October 2026 · ~10 min read

AI-assisted, human reviewed. How we use AI

Quick answer: how the webhook path works

ChatGPT doesn't speak MCP natively, so it can't call tools on a local server the way Cursor or Claude Desktop can. Instead, data flows one direction: your iPhone → your endpoint → ChatGPT. MetricBridge on iOS reads Apple Health (read-only) and POSTs a structured JSON payload to a webhook URL you configure. You receive that payload on a server you own and feed it into ChatGPT however you like.

The endpoint is yours. The app never POSTs to a server run by the developer; the full payload contract is in the webhook docs. For a comparison with the direct MCP path, see querying Apple Health with ChatGPT and Cursor.

📱 iPhone (Apple Health, read-only)
┃ POSTs JSON to your webhook
⬇── HTTPS
🖥️ Your endpoint (localhost / n8n)
┃ You copy, paste, or relay
⬇──
🤖 ChatGPT reads your health JSON

What the webhook payload actually looks like

When MetricBridge sends data, the JSON is clean, typed, and ready for any LLM to consume. Here's the real envelope, trimmed to three metrics (the app exports up to 194, but the structure is the same for one or a hundred):

{
  "data": {
    "metrics": [
      {
        "name": "heart_rate_variability",
        "units": "ms",
        "data": [
          { "date": "2026-07-31 00:00:00 +0100", "qty": 71.2 },
          { "date": "2026-08-02 00:00:00 +0100", "qty": 58.4 },
          { "date": "2026-08-03 00:00:00 +0100", "qty": 62.1 }
        ]
      },
      {
        "name": "resting_heart_rate",
        "units": "count/min",
        "data": [
          { "date": "2026-08-02 00:00:00 +0100", "qty": 56 },
          { "date": "2026-08-03 00:00:00 +0100", "qty": 54 }
        ]
      },
      {
        "name": "step_count",
        "units": "count",
        "data": [
          { "date": "2026-07-31 00:00:00 +0100", "qty": 6718 },
          { "date": "2026-08-01 00:00:00 +0100", "qty": 12109 },
          { "date": "2026-08-02 00:00:00 +0100", "qty": 8432 }
        ]
      }
    ]
  }
}

Three things make this useful for an AI model:

  • Every value has a unit. HRV is ms, resting heart rate is count/min. The model doesn't guess.
  • Metric names are stable, lower-case identifiers. heart_rate_variability, not HKQuantityTypeIdentifierHeartRateVariabilitySDNN. These are the same names the MCP server's list_metrics returns, so a call you copy from here works.
  • Dates carry an explicit UTC offset. The format is yyyy-MM-dd HH:mm:ss Z, bucketed to your device's local calendar day, so a model computing day-over-day deltas never has to guess a timezone.

This structure is deliberate: Apple's own export.xml is verbose and drops context when pasted into a chat. For a full comparison, see Apple Health JSON vs CSV vs XML.

Three ways to set up the webhook

You have options, ranging from zero-code to fully automated. Pick the one that matches your setup.

No code Export to file, then paste

Open MetricBridge, tap Export, choose "Save file." The app writes .health-cache.json to your Files app. Drag it into ChatGPT and ask. Fastest path for a one-off analysis: nothing transits a network.

Try: "Here's my Apple Health JSON for the past week. What stands out about my recovery trend? Compare this week's HRV and resting heart rate to last week."

Automated A local Python endpoint

Stand up a tiny HTTP server on your Mac or Linux machine. The app POSTs automatically in the background. Here's a complete receiver in FastAPI:

# save as webhook_receive.py
# pip install fastapi uvicorn

from fastapi import FastAPI, Request, HTTPException
import json
from pathlib import Path

app = FastAPI()
DATA_DIR = Path.home() / "health-data" / "inbox"
DATA_DIR.mkdir(parents=True, exist_ok=True)

@app.post("/health-export")
async def receive_health_data(request: Request):
    token = request.headers.get("x-health-token")
    if token != "your-secret-here":
        raise HTTPException(status_code=403)

    body = await request.json()
    stamp = request.headers.get("webhook-timestamp", "now")
    path = DATA_DIR / f"health-{stamp}.json"
    path.write_text(json.dumps(body, indent=2))

    return {"ok": True, "saved": str(path)}

# Run: uvicorn webhook_receive:app --host 0.0.0.0 --port 8080

Point MetricBridge's webhook destination to http://your-mac.local:8080/health-export with the secret token. Every export lands as a dated JSON file. From there, open the latest in ChatGPT or wire it into a pipeline via the ChatGPT API.

Privacy on LAN. Running the receiver on your Wi-Fi means the JSON never touches the public internet. Pair with Tailscale or ZeroTier for the same guarantee away from home.

No-code auto n8n or Home Assistant webhook

If you already run n8n or Home Assistant, create a webhook trigger node connected to a storage action: save to file, append to a Sheet, or forward to a custom GPT action via the ChatGPT API. Set the secret token in the app and in the webhook validator.

A real ChatGPT conversation walkthrough

Once the data is in ChatGPT's context, the interaction is fluid. Here's an exchange using the JSON payload shown above:

You: Here is my Apple Health data for this week as JSON. What stands out?

ChatGPT: A few things jump out:

1. **HRV dipped, then partly recovered.** SDNN went from 58.4 ms (Aug 2) to 62.1 ms (Aug 3),
   after 71.2 ms on Jul 31. Compared with your own recent baseline, it is a dip and a partial recovery, not a steady climb.

2. **Resting heart rate is low and steady** at 54 to 56 bpm.

3. **Step count is uneven**: 6,718 steps on Jul 31, 12,109 on Aug 1 and 8,432 on Aug 2.

Want me to compare weekday vs weekend averages?

You: Yes, compare weekday vs weekend steps and HRV.

ChatGPT: • **Weekday avg:** ~9,800 steps · HRV ~64 ms
• **Weekend avg:** ~7,100 steps · HRV ~61 ms

Your activity drops ~28% on weekends. HRV follows by ~3 ms,
within your usual day-to-day variation.

The model reads the JSON, computes the comparisons, references your own baseline (not a population norm), and offers a follow-up, all without a spreadsheet. And it never offers medical conclusions: the language stays in "deviation from your personal baseline" territory.

If you're running a local MCP client instead of ChatGPT, the same prompts produce live, tool-driven answers. See connecting Apple Health to Claude via MCP.

The privacy distinction that matters

MCP path (Cursor, Claude Desktop, opencode): the MCP server reads your local JSON export over stdio and makes no outbound network calls; only the numbers your agent asks for go to its model provider, and with a local model they stay on your machine.

Webhook path (ChatGPT, Gemini, Grok): the data travels from your iPhone to your endpoint, then you feed it into the model. That second hop (from your endpoint to ChatGPT's servers) is when the data leaves your control. The app never sends it to a third party, but once it's in ChatGPT, OpenAI sees it.

This isn't a flaw. It's a trade-off. Use MCP when your agent supports it (the server itself makes no outbound network calls). Use the webhook when you specifically want ChatGPT's reasoning. The app gives you the choice. More in Apple Health data privacy with AI agents.

When the webhook path makes sense

  • You live in ChatGPT. If it's your daily driver for notes and summarisation, the webhook path keeps you in the interface you already use.
  • You want scheduled summaries. Auto-export to your webhook receiver, and a cron job or n8n sends a weekly health prompt to the ChatGPT API.
  • You need a custom GPT action. Wire the webhook into your GPT's action endpoint for on-demand health data.
  • Zero-code is your preference. File export + drag into ChatGPT requires nothing more than the iOS app.

Send Apple Health to your own endpoint in two minutes

ChatGPT reads your real numbers as clean JSON; you own the endpoint and choose what reaches OpenAI.

Where it goes: the app reads Apple Health read-only and sends JSON only to the endpoint or folder you pick. Nothing reaches us; what you hand to ChatGPT reaches OpenAI. What you get: all 194 metrics, 22 tools (20 read-only) and 23 prompts. Setup: about two minutes. Price: $24.99 one time after a 7-day free trial, not a subscription. Your phone: works on any iPhone the app runs on; Apple Intelligence is not needed for the export or MCP.

Frequently asked questions

Can ChatGPT query my Apple Health data directly?

No. ChatGPT can't run a local stdio MCP server like this one. Instead, MetricBridge pushes your Apple Health JSON to a webhook endpoint you control, and you feed that data into ChatGPT manually or through a pipeline. The data flows one direction: your phone to your endpoint to ChatGPT.

What does the webhook JSON payload look like?

The app POSTs a data.metrics array where each metric has a name, units and a data list of points, each with a date and a qty. Every value includes its date and numeric value: no nested XML. A full example is shown above.

Is my Apple Health data sent through a third-party server?

The app never sends your data to a server operated by the developer. Your webhook endpoint is entirely under your control. That said, once you paste or upload the data into ChatGPT, it reaches OpenAI's servers. Use the MCP path with a local model if you need nothing to leave your machine.

Do I need to write code to use the ChatGPT webhook?

No code for the simplest workflow: export to a file, drag it into ChatGPT. For automated webhook delivery, you'll need a small endpoint: either n8n or ~15 lines of Python (the FastAPI receiver above).

Can I use ChatGPT's API to receive the webhook directly?

Not directly. ChatGPT doesn't expose a public HTTP endpoint that receives arbitrary JSON. But you can write a small relay (n8n or a Cloudflare Worker) that receives the webhook and forwards it via the OpenAI API. The API key lives on your relay, never in the app: MetricBridge has no cloud keys of any kind, and its own answers run on the iPhone (how).