Blog

How to build a Notion API integration with Nango and Claude

Build a customer-facing Notion API integration with Nango and Claude: white-label OAuth, page and database CRUD, with AI agent access over MCP.

Sapnesh Naik
Sapnesh Naik
Developer Advocate
API Integrations
Jun 7, 2026
Copy URL

This guide shows how to build a custom, customer-facing Notion API integration with an AI coding agent (Claude Code, Cursor, Codex, or any other) and Nango.

By the end of this guide, you will have:

  • A Notion auth UI in your product so your customers can connect their Notion workspaces to your app.
  • A durable sync that imports a customer’s Notion pages and keeps them up to date as pages are created and edited.
  • The ability to create pages and database entries in a customer’s Notion, from your UI or from an AI agent in your product (via an MCP tool call).
notion auth sync
Get the working example: the complete demo (frontend, backend, nango-integrations) is on GitHub at NangoHQ/blog-demos/how-to-build-a-notion-api-integration-using-nango-and-claude. Clone it to run the whole thing end to end, or follow the guide below and let Claude generate the same functions in your own project.

Why is it hard to integrate the Notion API into your app?

The list below is useful context for why a Notion API integration is more than a few REST calls:

  • Page content is a tree of blocks, not a document: text, headings, lists, and tables are separate block objects, so you walk the tree to read a full page (Notion docs).
  • Databases are becoming “data sources”: since the 2025-09-03 API version, one database can hold several data sources, so reads and writes target a database_id or a data_source_id (upgrade guide).
  • Max page size is 100: the maximum page_size is 100, so pages, query results, and search all come back a page at a time (Notion docs).
  • The integration only sees what a user grants it: during the OAuth connect flow, the customer picks which pages and databases to share; anything they do not pick returns object_not_found (Notion docs).
  • Rate and size limits apply: about three requests per second per connection (429 with a Retry-After header), plus per-request caps on blocks, payload size, and rich-text length (request limits).
  • OAuth tokens rotate: with token rotation on, each refresh issues a new refresh token and invalidates the old one, a common source of invalid_grant (how to fix it).

Building all of this by hand takes weeks. With Nango and a coding agent like Claude, the same Notion API integration can ship in about an hour.

Why use Nango for Notion API integration

Nango is a code-first integration platform where coding agents build API integrations. Use an agent like Claude, Cursor, or Codex to write the integration as code in your repo, and Nango’s runtime runs it with managed auth, retries, and observability across 800+ APIs.

For a Notion integration, we will use these Nango features:

  • Managed auth for Notion: pre-built Notion OAuth with token storage, refresh, rotation, and encryption handled for you. You connect the workspace, and Nango runs the flow.
  • A coding-agent skill that builds the functions: the universal Nango AI Function Builder skill gives your agent the context to research the Notion API, write a Nango action or sync, test it against a real connection with real data, and iterate until the whole integration works end to end.
  • Integrations infrastructure for every use case: Nango provides auth, actions, durable syncs, webhooks, and a built-in MCP server, so your product and the AI agents inside it can call the integration.

Nango also ships pre-built Notion templates (a pages sync, plus create-page, query-database, search, and comment actions) you can enable and customize. Start from a template or generate your own with the skill, as below.

Prerequisites

  1. Sign up for Nango (the free tier is enough for development).
  2. Add Notion as an integration, using Nango’s developer credentials for local testing or your own Notion OAuth app.
nango notion integration config

  3. Add a test connection (Connections > Add Test Connection) and authorize Notion, selecting a few pages in the picker. Claude uses this real workspace to test the integration as it builds, so you know the generated code actually works.

nango notion add test connection

  4. Install the Nango CLI and run nango init. This creates a nango-integrations folder, where Claude writes your integration code (syncs and actions). Set NANGO_SECRET_KEY_DEV in nango-integrations/.env so Claude can deploy to Nango on your behalf.

  5. Install the Nango skill: npx skills add NangoHQ/skills -s building-nango-functions-locally. This example uses Claude, but the same skill works with Cursor, Codex, and other coding agents.

Tip: LLM training data on Nango is often stale. Add the Nango docs MCP server alongside the skill so your agent pulls current API references while it generates code.

Sync customer Notion pages to your app

A sync keeps a fresh copy of the customer’s Notion content in your app. Here it imports every page they shared when they connect, then refreshes on a schedule so edits show up without anyone clicking refresh. You build it by prompting Claude with the Nango skill loaded:

/building-nango-functions-locally Build a Nango sync for the notion integration that syncs every page shared with the connection and keeps it up to date. Integrate it with my frontend.

With the skill loaded, Claude:

  • Researches the Notion API and the endpoints it needs.
  • Writes the sync and a typed model for your pages.
  • Tests it against your real connection with real data.
  • Iterates on any errors until the sync works end to end.
claude building notion sync

Claude generates the sync and a typed page model. On the first connection it imports every shared page; after that it refreshes on a schedule and pulls only what changed, so your app stays up to date. Your frontend reads the synced pages from Nango, or subscribes to Nango webhooks for live updates.

// Claude generates this sync. You do not write it by hand.
export default createSync({
    description: 'Sync the Notion pages shared with the connection',
    frequency: 'every 5 minutes',
    autoStart: true,
    models: { NotionPage },
    exec: async (nango) => {
        const pages = await nango.post({ endpoint: '/v1/search' }); // pages, newest first
        await nango.batchSave(pages, 'NotionPage');
    },
});

The full sync, with the page model, the last_edited_time checkpoint, and the descending-search pagination, is in the demo repo: data-source-entries.ts.

When Claude finishes, it deploys the sync for you (approve the deploy when it asks). Because the prompt said to integrate the frontend, Claude also wires Nango Connect into your app, so customers can link their workspace and the sync starts on its own.

image 20260607112038486

You can see the sync in progress on the Nango dashboard right after a user authorizes Notion in your app.

notion database sync view

Do a quick check to confirm everything works: open your app, click connect, authorize Notion, and watch the pages appear. The first sync runs in the background and finishes within a few seconds, so the list fills in shortly after you connect. Claude has already tested the integration; this is just your own sanity check.

Want changes to show up instantly? Ask Claude to add Notion webhooks to the sync. Nango routes Notion’s events to your integration, so an edit in Notion syncs within seconds instead of waiting for the next scheduled run.

Create pages in customer’s Notion from your app

An action is a one-off operation your product or an agent triggers on demand. Here we use one to write back to Notion: let a customer (or an agent) create a page or a database row in their workspace. Prompt Claude to build it with the Nango skill:

/building-nango-functions-locally Add an action to the notion integration that creates a page in the customer's Notion from a title and body.

Claude writes the action, tests it by creating a real page in your connected workspace, and deploys it when you approve.

claude notion integration build
// Claude generates this action; approve the deploy when it asks.
export default createAction({
    description: 'Create a Notion page',
    retries: 0, // creating is not idempotent, so a retry must not make a duplicate
    exec: async (nango, input) => {
        const res = await nango.post({ endpoint: '/v1/pages', data: buildPage(input) });
        return { id: res.data.id, url: res.data.url };
    },
});

The full action, with input validation and the body-to-blocks conversion, is in the demo repo: create-page.ts.

notion integration demo app

You can test the action straight from your app, or run it from the Nango dashboard with the Playground against your connection.

nango playground notion create page

Give AI Agents in your app access to customer’s Notion

You can also enable the AI agents inside your products to list, create, and read Notion content on a customer’s behalf. Your agent can reuse the same Nango sync/actions using the Nango MCP server.

In this demo, the product’s assistant takes a prompt like “create a page called Nango agent demo under Others.” The agent calls the create-page tool through Nango, and returns a link you can open in Notion to verify. The demo orchestrates this from its Express backend, which holds the Nango secret and calls Nango’s MCP server.

nango agent notion mcp demo

Point your MCP client at Nango’s server and pass three values:

Authorization:        Bearer <YOUR-NANGO-SECRET-KEY>
provider-config-key:  notion
connection-id:        <CONNECTION-ID>
  • Authorization: your Nango secret key.
  • provider-config-key: your Notion integration’s id (the notion key shown on its integration page).
  • connection-id: the connection for the current user. Fetch it per logged-in user rather than hardcoding it, so each user’s agent acts on their own workspace.

Claude can wire this into your agent for you. Prompt it:

/building-nango-functions-locally Wire my product's AI agent to Nango's MCP server for the notion integration,
passing the logged-in user's connection id, so it can create and read Notion pages.

To give the agent more abilities (querying databases, appending blocks, searching), enable the matching pre-built actions on the Notion integration page in Nango. Each enabled action becomes another tool.

If you do not have an agent interface in your product yet but want to try this in your own coding agent, add Nango’s MCP server to Claude Code directly:

claude mcp add nango-notion https://api.nango.dev/mcp \
  --transport http \
  --header "Authorization: Bearer $NANGO_SECRET_KEY" \
  --header "connection-id: <CONNECTION-ID>" \
  --header "provider-config-key: notion"

Then ask Claude: “Create a page titled ‘Launch checklist’ under my Notion project page using the nango notion mcp.”

Tip: you can view detailed action and sync logs on the Nango dashboard.

nango logs notion

Common issues

IssueCause and fix
object_not_found on a page or databaseThe customer did not grant it to your connection. Reconnect and select it in Notion's page picker. The integration only sees what was shared.
listRecords is empty right after connectingThe first sync run is asynchronous. Read records once a run has completed (Claude wires this into your app).
Query or create fails on a multi-source databaseA database with more than one data source must be addressed by its `data_source_id` (`2025-09-03`+). Single-source databases still work by `database_id`.
Duplicate pages on a retried createA create is not idempotent. The action uses `retries: 0` so a retry never re-creates a page.
429 rate_limitedNotion allows about three requests per second per connection. Nango respects the `Retry-After` header and backs off for you.
invalid_grant on token refreshWith token rotation enabled, the newest refresh token must be persisted after every refresh. Nango handles this; see the fix guide.
Synced pages have no body contentA page record carries its properties, not body text. Fetch the page's blocks with `GET /v1/blocks/{page_id}/children` to read the body.

Conclusion

Building a production-grade, end-to-end Notion API integration (customer auth, a live sync of their pages, creating and reading content, real-time updates, and access for the AI agents in your product) used to take weeks. With Nango and a coding agent like Claude (or Cursor or Codex), you can ship it in about an hour and put it in front of your customers.

It works because Nango is code-first and coding agents are good at writing code. Nango brings the rest: white-label auth with token refresh and rotation, durable syncs, webhooks, retries, observability, and a secure runtime, across 800+ APIs.

Clone the demo project on GitHub to run it end to end, or build your first integration from the quickstart.

Related reading:

Ready to get started?

Ship the integrations your customers need — with 800+ APIs and infrastructure built for scale.

Custom needs?