Title image of Detect changes in Notion with Azure Logic Apps

Detect changes in Notion with Azure Logic Apps

1 October 2023


Notion is a great platform for writing, that’s why I built this blog on top of it. Notion acts as the headless CMS to a static Nuxt app served via Cloudflare pages. When the Nuxt app is built it downloads the articles from Notion’s API and converts them to static HTML. The HTML is published to Cloudflare Pages which makes it super fast because the static content is served over Cloudflare’s CDN 🚀

It all works pretty well… except for the manual deployments 🤢 Whenever I make changes to the articles stored in Notion I need to manually trigger a new deployment of the blog. The usual way to automate this is to use event-based webhooks. We could subscribe an API to an ‘article updated’ event and trigger a deployment every time we receive this event. But unbelievably Notion doesn’t have webhooks 😟

It’s fine… if Notion doesn’t want to push events to us we have to poll it for them. We will have to call their API periodically to check for updates and redeploy the blog if we find any. I’m not too bothered about articles appearing on my blog instantly after I publish them so we only need to check for updates every 24 hours. When we check we can determine if any article has been changed in the last 24 hours and redeploy the blog.

For the orchestration, we’re going to use an Azure Logic App because they’re cheap and easy to set up. Here is the plan:

The solution design for triggering redeployments

Notion API

The Notion API is very good for querying your Notion database. It has a powerful query filter object to filter the results in any way you choose. We can use the filtering to get the latest published article that has been edited and use that to determine if we need to redeploy the blog.

To set up the filtering we need to see how the Notion database is set up:

My blog CMS inside Notion

Each article has a status property which is either ‘Draft’ or ‘Published’. Every notion page also has a built-in last_edited_time property that records the last time the page was edited. Combining both of these and limiting the page size to 1 gives us a filter to get the latest edited published article.

The filter request to Notion:

    "filter": {
        "property": "Status",
        "select": {
            "equals": "Published"
    "sorts": [
            "timestamp": "last_edited_time",
            "direction": "descending"

And that’s all we need from the Notion API 🙂

Cloudflare API

The blog is hosted in Cloudflare pages so the Cloudflare API is needed to trigger a new deployment. This is very easy because Cloudflare has an API to do just about everything.

It’s a simple HTTP POST to the deployment endpoint to trigger a new deployment:


Connecting them with Azure Logic App

Now we know what to do with Notion and Cloudflare it’s time to connect them together. We will use an Azure Logic App for that because they are easy to set up and cheap.

Here are the steps in our Logic App:

1) App Trigger

A recurrence trigger to run the app every 24 hours:

Setting the Logic App frequency

2) Query Notion

The second step is the query to Notion to get the latest edited published article. This is just a HTP POST with the filter object we put together earlier.

Querying Notion from the Logic App

3) Parsing the response

Parsing the response makes it easier to use in the later steps. Defining the schema is quick when you generate it from a sample of the Notion response.

4) Has an article been edited?

Here’s the important stuff…

This is where we determine if an article has been edited and we need to redeploy the blog. The response from Notion is an array so we need a loop even though we have specified a page size of 1. We need to check the time the article was last edited for each item in the array. If the article was edited within the last 24 hours a new Cloudflare deployment needs to be triggered.

The formula for comparing the time is a little complicated so is best added through the code view of Azure Logic Apps. Here is the formula for getting the number of ticks between the current time and the last edited time:

@sub(ticks(utcNow()), ticks(parseDateTime(items('For_each')?['last_edited_time'])))

One minute is 600,000,000 ticks so 24 hours is 864,000,000,000 ticks. If the difference between the times is less than that the article has been changed.

Looping through each of the blog posts in the Azure Logic App

5) Trigger Cloudflare deployment

Finally, if we need to republish the blog send a HTTP POST to Cloudflare to trigger the redeployment:

Calling Cloudflare from an Azure logic app

Woo no more manual deployments 😊