What I wanted
I’m building a system where all my daily records live in Notion, so I can point an AI at it and get feedback. Goals, tasks, daily logs, finances — those are all manual entry, and that’s fine. But one day it hit me that weight would be nice to sync automatically.
The requirements were simple:
- Every morning, my weight and body fat percentage get appended to a Notion database as one row
- No manual typing
That’s it. My scale is a Withings Body Smart.
The design I picked first
This one:
Scale → vendor app → Apple Health → iOS Shortcut → Notion API
Enter fullscreen mode Exit fullscreen mode
I chose Apple Health as the hub for these reasons:
- It doesn’t depend on the scale model. As long as the data lands in Health, the same implementation works for any vendor.
- No server required. A time-based Shortcuts automation handles it end to end — no always-on machine, no cron.
- Free. No extra subscription.
- Extensible later. Anything that’s already in Health — steps, sleep, heart rate — could be added the same way (if I ever wanted to).
Generic, zero cost, extensible. The design looked sound to me.
Implementation
Here’s what the Shortcut looks like:
1. Find Health Samples [Weight] latest, limit 1
2. Get Details of Health Sample [Value] → variable Kg
3. Get Details of Health Sample [Start Date] → variable SampleDate
4. Format Date yyyy-MM-dd → variable Ymd
5. If Ymd == today
6. Text ← build the JSON
7. Get Contents of URL ← POST to the Notion API
Enter fullscreen mode Exit fullscreen mode
Step 5 matters. Without it, on a day you don’t step on the scale, yesterday’s weight gets appended under today’s date.
Here’s the JSON built in step 6:
{
"parent": { "database_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" },
"properties": {
"Date": { "title": [ { "text": { "content": "@@YMD@@" } } ] },
"Measured": { "date": { "start": "@@YMD@@" } },
"Weight kg": { "number": @@KG@@ },
"Body fat %": { "number": @@FAT@@ }
}
}
Enter fullscreen mode Exit fullscreen mode
(My real database uses Japanese property names. What matters is that they match your database exactly.)
I write this as a plain string in a Text action and hand it to the POST action.
Setting up the Notion side
Use an access token, not OAuth
Notion offers two auth methods for a connection: an internal access token, and OAuth. OAuth is meant for apps that get installed into other people’s workspaces, or listed on the Marketplace — so for this I went with the access token.
I attached the connection at the parent page
Notion permissions are inherited by child pages. If you connect an integration at a parent page, everything underneath it becomes reachable.
In my case I may want to auto-sync things other than weight later, so I granted access at the parent page that holds my personal data.
Note: if you’re doing this at work, you’d want to scope it down to the minimum necessary permissions.
I hit a 400 twice
First: it says there’s no parent
{
"status": 400,
"code": "validation_error",
"message": "Provide a `parent.page_id` or `parent.database_id` parameter to create a page,
or use a public integration with `insert_content` capability.
Internal integrations aren't owned by a single user, so creating
workspace-level private pages is not supported."
}
Enter fullscreen mode Exit fullscreen mode
My JSON has a parent. And I still got this.
The cause was that I never wired the JSON into the request body. When I set up the POST action in Shortcuts, I hadn’t configured it to actually take the JSON — so I was POSTing an empty body. Yeah.
Second: invalid_json
{ "status": 400, "code": "invalid_json", "message": "Error parsing JSON body." }
Enter fullscreen mode Exit fullscreen mode
Weight was appending fine, so I went to add body fat percentage. When I added the property, I forgot the trailing comma on the previous line.
"Weight kg": { "number": 67.878 } ← no comma
"Body fat %": { "number": 16.058 }
Enter fullscreen mode Exit fullscreen mode
Shortcuts has no syntax highlighting and no linter, so I walked right past it.
The only debugging tool you get
Drop a Quick Look action immediately after the Text action. It shows you the expanded JSON exactly as it will be sent, so you can confirm the variables actually resolved to values.
In Shortcuts development this is effectively your only debugging tool. When you’re stuck, look at the payload.
Rounding the numbers
The weight coming out of Health was something like 67.87800598144531.
I first tried to round it inside Shortcuts, but somehow I could not get it to work, so I rounded on the Notion side instead.
Add one formula column to the weight database:
round(prop("Weight kg") * 10) / 10
Enter fullscreen mode Exit fullscreen mode
Then hide the raw column in the view and show only the rounded one. Much easier to read.
As a side effect this turned out to be the better design anyway: the raw value stays in the database, and rounding is a display concern.
It works. And then I noticed something
It ran. Rows appeared in Notion.
But there was one problem left.
Apple Health doesn’t get the data unless I open the Withings app.
Stepping on the scale every morning isn’t enough. If I want a row every day, I have to open the Withings app every day. Background App Refresh is on, and even then there’s no guarantee it syncs daily.
So the actual workflow is:
- Step on the scale
- Open the Withings app ← New!
- The Shortcut runs (I changed the trigger to “when the Withings app is closed”…)
The appending is automated now, but a daily manual step survived. What I actually wanted was for stepping on the scale to be the whole interaction.
What I got wrong
Apple Health is a bucket that gets written to when a connected app launches — it isn’t necessarily something that goes and fetches data on its own. I thought I was picking a hub. What I actually put in the middle of the path was a bucket waiting for the Withings app to open.
Meanwhile, Withings has a public API. The scale is on Wi-Fi and presumably pushes measurements straight to the cloud, so a path like this might work:
Scale --Wi-Fi--> Withings cloud --webhook--> my own endpoint --> Notion
Enter fullscreen mode Exit fullscreen mode
A row appears in Notion the moment I step on the scale. There’s no app to open.
I picked Health because I wanted the design to be generic — but the scale I actually own is one of the models that can skip that generic layer and be called directly. By choosing “a design that works with any scale,” I missed the better path that only my scale had.
The lesson
When you design an automation path, check up front whether each hop can push data forward on its own. If even one hop is pull-based — it only moves data when something comes asking — that’s where a human eventually ends up doing the work.
Originally published in Japanese on Zenn: 体重を自動でNotionに記録したかったが、毎朝アプリを開く仕事が残った
답글 남기기