Let's Build Your First Campaign Together with our Lead Generation Expert

How to Connect Notion to Azure Functions

Table of Contents

You built a Notion workspace that your whole team lives in. You have Azure Functions already running parts of your backend. But they don’t talk to each other — and every time you need to move data between them, someone has to do it manually.

That’s the kind of friction that quietly kills productivity.

The good news: connecting Notion to Azure Functions is entirely doable, and once it’s set up, it unlocks real automation — things like auto-creating Notion pages when a form is submitted, syncing CRM data into your Notion database, or triggering serverless workflows straight from Notion properties.

This guide walks you through exactly how to do it, from getting your API credentials to writing the function code that makes the connection work.

Why Connect Notion to Azure Functions

Notion has grown into one of the most widely used knowledge and project management platforms in the world, with over 35 million users across teams of every size. Azure Functions, Microsoft’s serverless compute service, processes trillions of function executions per month across global infrastructure spanning 60+ regions.

Individually, both tools are powerful. Together, they become something much more useful.

Here’s what the combination makes possible:

  • Triggered automation — A new row appears in your Notion database, and Azure Functions fires off a downstream task automatically
  • Two-way data sync — Keep Notion databases current with data from external APIs, CRMs, or internal systems
  • Event-driven workflows — Use Notion as a lightweight control panel that triggers serverless logic in the background
  • Webhook processing — Capture Notion events and route them to other services without managing a server

According to McKinsey, employees spend roughly 28% of their workweek managing email and data tasks that could be automated. Businesses that connect tools like Notion with serverless compute platforms report up to 20% improvement in team productivity by eliminating manual data transfers.

The integration pattern is straightforward: Notion exposes its data through an official API, and Azure Functions can call or respond to that API based on any trigger you define.

What You Need Before You Start

Before writing a single line of code, make sure you have these in place:

  • A Notion account with admin access to at least one workspace
  • An Azure account with an active subscription (the free tier works for testing)
  • Node.js (v16+) or Python (3.8+) installed locally — pick whichever you’re more comfortable with
  • Azure Functions Core Tools installed on your machine
  • Basic familiarity with REST APIs and environment variables

No prior serverless experience is required, but knowing what a function trigger is will help you follow along faster.

How to Connect Notion to Azure Functions

Create a Notion Integration

The Notion API requires an integration to authenticate requests. Think of it as registering your Azure Function as a trusted application inside your Notion workspace.

Go to https://www.notion.so/my-integrations and click “New Integration.”

Fill in:

  • Name — Something descriptive like Azure Function Sync
  • Associated Workspace — Select the workspace you want to connect
  • Capabilities — Enable Read, Update, or Insert content depending on what your function needs to do

Click Submit and Notion will generate an Internal Integration Token (your API key). Copy this — you’ll need it shortly.

Important: This token has the same access as the integration permissions you set. Treat it like a password. Never hardcode it directly in your function code.

Share a Notion Database with Your Integration

This is the step most people miss the first time.

Even after creating your integration, it has no access to any content by default. You need to explicitly share each database or page with it.

Open the Notion database you want to connect. Click the “…” menu in the top right corner, go to Connections, and select your integration from the list.

Once shared, the integration can read from and write to that database via the API.

Get the Database ID

Every Notion database has a unique ID embedded in its URL. You’ll need this to make API calls to the right place.

Open your database in Notion. Look at the URL — it follows this pattern:

https://www.notion.so/{workspace}/{database_id}?v={view_id}

 

The database ID is the 32-character string before the ?v= parameter. Copy it.

Set Up Your Azure Function Project

If you don’t already have Azure Functions Core Tools installed, run:

npm install -g azure-functions-core-tools@4 –unsafe-perm true

 

Create a new function project:

func init NotionAzureIntegration –javascript

cd NotionAzureIntegration

func new –name NotionSync –template “HTTP trigger”

 

This scaffolds a basic HTTP-triggered function. You can swap the trigger type later (Timer, Queue, Event Grid, etc.) depending on what you need.

Install the Notion SDK

Inside your function project directory, install the official Notion client:

npm install @notionhq/client

 

This SDK wraps the Notion API in a clean interface and handles authentication for you.

Configure Environment Variables

Never put your Notion API key directly in your code. Use environment variables instead.

Open local.settings.json in your project and add:

{

  “IsEncrypted”: false,

  “Values”: {

    “AzureWebJobsStorage”: “”,

    “FUNCTIONS_WORKER_RUNTIME”: “node”,

    “NOTION_API_KEY”: “your_integration_token_here”,

    “NOTION_DATABASE_ID”: “your_database_id_here”

  }

}

 

When you deploy to Azure, you’ll add these same values under Configuration → Application Settings in the Azure Portal — not in this local file.

Write the Integration Code

Open NotionSync/index.js and replace the default code with:

const { Client } = require(“@notionhq/client”);

 

const notion = new Client({

  auth: process.env.NOTION_API_KEY,

});

 

module.exports = async function (context, req) {

  const databaseId = process.env.NOTION_DATABASE_ID;

 

  try {

    // Query the Notion database

    const response = await notion.databases.query({

      database_id: databaseId,

      filter: {

        property: “Status”,

        select: {

          equals: “Active”,

        },

      },

    });

 

    const pages = response.results.map((page) => ({

      id: page.id,

      title: page.properties?.Name?.title?.[0]?.plain_text || “Untitled”,

      status: page.properties?.Status?.select?.name || “Unknown”,

    }));

 

    context.res = {

      status: 200,

      headers: { “Content-Type”: “application/json” },

      body: { success: true, count: pages.length, data: pages },

    };

  } catch (error) {

    context.log.error(“Notion API error:”, error.message);

    context.res = {

      status: 500,

      body: { success: false, error: error.message },

    };

  }

};

 

This function queries your Notion database and returns all pages where the Status property equals “Active.” Adjust the filter and property names to match your actual database structure.

Test the Connection Locally

Run your function locally:

func start

 

Azure Functions Core Tools will start a local server, typically at http://localhost:7071. Open your browser or use a tool like Postman to hit:

http://localhost:7071/api/NotionSync

 

If the connection is working, you’ll get back a JSON response with your Notion database records. If you see an authentication error, double-check your integration token and that the database has been shared with your integration.

Deploy to Azure

Once local testing passes, deploy to Azure:

az login

func azure functionapp publish <YourFunctionAppName>

 

If you haven’t created a Function App yet, do that first through the Azure Portal or with the Azure CLI:

az functionapp create \

  –resource-group MyResourceGroup \

  –consumption-plan-location eastus \

  –runtime node \

  –runtime-version 18 \

  –functions-version 4 \

  –name YourFunctionAppName \

  –storage-account YourStorageAccount

 

After deployment, add your environment variables in the Azure Portal under Function App → Configuration → Application Settings.

Writing Data Back to Notion

Reading from Notion is useful. Writing back is where automation gets powerful.

Here’s how to create a new page in your Notion database from Azure Functions:

const newPage = await notion.pages.create({

  parent: { database_id: databaseId },

  properties: {

    Name: {

      title: [{ text: { content: “New Entry from Azure” } }],

    },

    Status: {

      select: { name: “Pending” },

    },

    Created: {

      date: { start: new Date().toISOString() },

    },

  },

});

 

This creates a new row in your Notion database every time the function runs. You can trigger this from a form submission, a webhook, a timer, or any event Azure Functions supports.

Common Integration Patterns

Once the basic connection is working, the possibilities expand quickly:

Timer-triggered sync — Run a function on a schedule (every hour, every morning) that pulls data from an external API and writes it into a Notion database. Teams use this to keep project trackers, pipeline dashboards, and status boards up to date automatically.

Webhook receiver — Point external tools (Stripe, GitHub, HubSpot) at your Azure Function endpoint. The function processes the webhook payload and creates or updates Notion pages accordingly.

Notion as a trigger — Use Notion’s API to poll for changes on a schedule. When a record’s status changes to “Ready for Review,” fire an Azure Function that notifies a Slack channel or kicks off a downstream process.

Data aggregation — Pull data from multiple sources into a single Notion database for reporting. Azure Functions handles the aggregation logic; Notion becomes the readable, shareable output.

 

Troubleshooting Common Issues

“Could not find database” — The database ID in your environment variable is wrong, or you haven’t shared the database with your integration. Both need to be correct.

401 Unauthorized — Your API key is invalid or wasn’t loaded from environment variables correctly. Add a console.log(process.env.NOTION_API_KEY) temporarily to confirm it’s being read (then remove it before deploying).

403 Forbidden on specific properties — The integration doesn’t have permission to access that property type. Go back to your integration settings and verify capabilities.

Rate limiting (429 errors) — The Notion API has a limit of 3 requests per second per integration. If you’re making bulk queries, add delay logic between requests or batch your operations.

Timeout errors in Azure — The default execution timeout for Azure Functions on the Consumption plan is 5 minutes. For long-running sync operations, switch to a Premium or Dedicated plan or break the task into smaller chunks.

🚀 Stop Managing Data. Start Closing Deals.

We book qualified meetings for you using proven cold outbound systems

7-day Free Trial |No Credit Card Needed.

FAQs

Does Notion have an official API?

Yes. Notion launched its public API in 2021. It supports reading, writing, and querying databases, pages, and blocks. The API is REST-based and has official SDKs for JavaScript and Python, plus community libraries for other languages.

Can I use Python instead of JavaScript for this integration?

Yes. The Notion Python SDK (notion-client) works the same way. Replace the Node.js setup steps with a Python virtual environment and pip install notion-client, then write your function in Python using the azure-functions package. The API calls and logic are nearly identical.

How often can I poll the Notion API?

The Notion API enforces a rate limit of 3 requests per second per integration. For real-time syncing, consider using Azure Event Grid or a queue-based approach to manage request pacing rather than making direct polling calls on a tight loop.

Can Azure Functions listen for changes in Notion in real time?

Not natively — Notion doesn't push webhooks (as of the current API version). The standard workaround is polling: run an Azure Timer Function every few minutes to check for updated records. For near-real-time needs, set the polling interval to 1–2 minutes, which stays well within rate limits for most database sizes.

We deliver 100–400+ qualified appointments in a year through tailored omnichannel strategies

What to Build a High-Converting B2B Sales Funnel from Scratch

Lead Generation Agency

Build a Full Lead Generation Engine in Just 30 Days Guaranteed