Tyler Jefford Memoji

Syncing Data to Notion with in Laravel 12

By Tyler Jefford

May 27th, 2025

I’ve got a pretty dialed-in Notion system where I track daily metrics and roll them up by week, month, and year. It’s definitely a nerdy habit, but honestly, I love it.

Some of these metrics come straight from Apple Health, things like steps, weight, and exercise minutes. For a while, I was using an Apple Shortcut to send this data to Notion, but it was flakey and broke more often than not. One weekend, I decided to stop messing around and built a simple Laravel API service. It stores the data locally, then pushes it to Notion in a queued job. I’ll walk through how that works below.


Prerequisites

Before you can send anything to Notion, you’ll need to set up a few things.

1. Get your Notion API key

Head to the Notion integrations page and create a new integration. This will give you your API token. Add that to your .env file like this:

NOTION_TOKEN=your_secret_token_here

2. Get your database ID

Open your Notion database in the browser and grab the ID from the URL (cmd+L). It’s the long string of characters between your workspace name and the ?v= part.

In this example, the xx999... portion is the database ID.

https://www.notion.so/your_notion/xx9999000011112222333344445555xx?v=1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a&pvs=4

NOTION_DB_ID=your_database_id_here

3. Share the integration with the database

Click the three-dot menu in the top right of your database, go to “Connections,” and add your integration so it has access to read and write.


Setting up the Basics

In the Notion database I’m working with, I’ve got two important properties: one called Date and another called Steps. These are case-sensitive and need to match exactly when we send updates.

In my Laravel project, I use report_date and steps in the API request, and map those to the Notion fields later on. I’m skipping over the setup of your models, migrations, and basic Laravel project structure. There are plenty of great guides out there if you need help getting started with that part.


Building the API

This is a POST route in the Laravel API, using a controller method: MetricController@store. I’m also using Laravel Sanctum for API token management, but that’s outside the scope of this post. You can follow the Sanctum docs if you want to add that.

Here’s the general idea:

  • Check if a record already exists for the given report_date

  • If it does, update it; otherwise, create a new one

  • Then dispatch a queued job to update Notion

In the request, I validate the data with a StoreMetricRequest. For now, I’m just checking that report_date is required and steps is numeric, but you can add more validation rules depending on what metrics you’re tracking.


Pushing to Notion (via Job)

The actual Notion update is handled in a queued job. I broke this out into three parts:

1. Finding the Notion entry

We send a query to the Notion API to search for a page with the current date. You need to use the exact field name Date in the filter. All we really need here is the page ID.

2. Building the payload

Once we have the page ID, we build the payload that will be sent to Notion. I keep things flexible by using a language file to map Laravel field names to Notion field names. That way, if I change a label in Notion, I don’t need to hunt through my code to update it. In the PublishNotion job you can see me pushing these mapped values into the array using __('notion.'.$key)

3. Updating the page

We send the payload using the HTTP client in Laravel. If the response isn’t successful, I throw an error so it can be retried later.

Conclusion

Like I said, there is a lot more that can be done with this, and I am doing a lot more on my actual API, but this is something I wish someone had written so I could follow setting up a Notion API sync using Laravel.