Connectors
/
Notion
Live · 10 tools

Notion Integration for AI Agents

The Notion API is well-documented. Building a multi-user agent on top of it — where each user's workspace is isolated and tokens never expire at the wrong moment — is the part that takes longer than it should.
Notion
Live

Knowledge Base

Collaboration

Status
Live
Tools
10 pre-built
Auth
OAuth 2.0
Credential storage
Zero
Sandbox support
No

OAuth 2.0

Auto token refresh

Zero credential storage

Revocation detection

Pages + Databases

The real problem

Why this is harder than it looks

Most teams start with Notion's internal integration — a static token, one workspace, done in twenty minutes. The problems start when you try to make it work for real users across their own workspaces.

For a multi-user product you need a public integration, which means registering a Notion OAuth app with a company website, privacy policy, and terms of service, then waiting for Notion's review. Until it clears, your integration only works for workspaces you've manually added as test users. Then there's the capabilities system: unlike most OAuth APIs where scopes are declared at authorization time, Notion's read, write, insert, and comment capabilities are configured on the integration itself. Call an endpoint without the right capability toggled on and you get a 403 — not a scope error. If you add a capability after users have already authorized, existing tokens won't automatically reflect it.

Even after a user completes OAuth, your integration only has access to the pages and databases they explicitly selected in Notion's consent picker. API calls to anything outside that selection return a "page not found" error, not a permissions error. In a multi-tenant deployment, distinguishing "this page doesn't exist" from "this user didn't share it" requires extra logic you have to write and maintain.

None of this is impossible. But it's weeks of work before your agent does anything useful. And then you do it again for the next connector. Scalekit handles the OAuth flow, token lifecycle, and revocation detection — your agent names a tool and passes parameters, nothing else.

Capabilities

What your agent can do with Notion

Once connected, your agent has 10 pre-built tools covering pages, databases, and comments:

  • Search the entire workspace: full-text search across all pages and databases the user has shared with the integration
  • Create and read pages: create pages inside databases or as children of existing pages; fetch page content and metadata by ID
  • Query and manage databases: list rows with filters and sorting, insert new rows, create databases with custom schemas
  • Introspect database schemas at runtime: fetch full property definitions so your agent adapts to each user's actual structure without hardcoding field names
  • Read and write comments: create top-level comments on pages or replies within discussion threads; fetch comment threads by block ID
Setup context

What we're building

This guide connects a knowledge assistant agent to Notion — helping team members search docs, log updates, and manage structured project data without leaving your product.

🤖
Example agent
Knowledge assistant reading and writing Notion pages and databases on behalf of each user
🔐
Auth model
B2B SaaS — each user connects their own workspace. identifier = your user ID
⚙️
Scalekit account
app.scalekit.com — Client ID, Secret, Env URL
🔑
Notion OAuth app
Register at notion.so/profile/integrations — required for BYOC setup
Setup

1 Setup: One SDK, One credential

Install the Scalekit SDK. The only credential your application manages is the Scalekit API key — no Notion secrets, no user tokens, nothing belonging to your customers.

pip install scalekit-sdk-python
import scalekit.client import os from dotenv import load_dotenv load_dotenv() scalekit = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) actions = scalekit.actions
Connected Accounts

2 Per-User Auth: Creating connected accounts

Each user gets their own Connected Account, giving them a dedicated auth context. The identifier is any unique string from your system — a UUID, email, whatever you use internally.

response = actions.get_or_create_connected_account( connection_name="notion", identifier="user_notion_456" # your internal user ID ) connected_account = response.connected_account print(f"Status: {connected_account.status}") # Status: PENDING — user hasn't authorized yet

This call is idempotent — safe to call on every session start. Returns the existing account if one already exists.

Authorization Flow

3 The authorization flow

The user authorizes your agent once. Scalekit generates the OAuth URL with correct capabilities, PKCE challenge, and redirect handling pre-configured. After approval, you never see the token.

if connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name="notion", identifier="user_notion_456" ) # Redirect user → Notion consent screen (page picker) # Scalekit captures the token on callback return redirect(link.link)
Token management is automatic
After the user approves and selects their pages, Scalekit stores encrypted tokens and the connected account moves to ACTIVE. Access tokens refresh before expiry. If a user revokes access from Notion's Settings → Connections, the account moves to REVOKED — no silent failures. Check account.status before critical operations.
Bring Your Own Credentials — required for production
Unlike some connectors, Notion requires you to register your own public integration in the Notion Developer Hub and supply your own Client ID and Secret. This means your users see your app name on the consent screen. Register the Scalekit redirect URI in your Notion integration's OAuth settings, then paste your credentials into the Scalekit dashboard. Token management stays fully handled.
Already have credentials?
Calling Notion

4 Calling Notion: What your agent writes

With the connected account active, your agent calls Notion actions using execute_tool. Name the tool, pass parameters. Scalekit handles token retrieval and request construction.

Search the workspace

Find pages and databases by keyword across everything the user shared with the integration. Use start_cursor for pagination.

result = actions.execute_tool( identifier="user_notion_456", tool_name="notion_data_fetch", tool_input={ "query": "Q3 roadmap", "page_size": 10 } ) # Returns pages and databases matching the query, # limited to content the user shared with the integration.

Query a database

Fetch rows from a specific database with optional sorting. Extract the database_id from the Notion URL — the last 32 characters, formatted as a hyphenated UUID (8-4-4-4-12).

result = actions.execute_tool( identifier="user_notion_456", tool_name="notion_database_query", tool_input={ "database_id": "2561ab6c-418b-8072-beec-c4779fa811cf", "page_size": 50, "sorts": [ { "property": "Due Date", "direction": "ascending" } ] } )

Insert a row into a database

Add a new page (row) to an existing database. Call notion_database_fetch first to confirm exact property names — they are case-sensitive. For title fields, always use "title" as the key.

result = actions.execute_tool( identifier="user_notion_456", tool_name="notion_database_insert_row", tool_input={ "database_id": "2561ab6c-418b-8072-beec-c4779fa811cf", "properties": { "title": { "title": [{"text": {"content": "Q3 Roadmap Review"}}] }, "Status": {"select": {"name": "Not Started"}}, "Due Date": {"date": {"start": "2026-07-15"}}, "Priority": {"select": {"name": "High"}} } } )

Create a standalone page

Create a new child page under an existing parent. Provide parent_page_id and optional child_blocks for body content.

result = actions.execute_tool( identifier="user_notion_456", tool_name="notion_page_create", tool_input={ "parent_page_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "properties": { "title": { "title": [{"text": {"content": "Meeting Notes — 2026-07-01"}}] } }, "child_blocks": [ { "object": "block", "type": "paragraph", "paragraph": { "rich_text": [{"type": "text", "text": {"content": "Action items from today's sync."}}] } } ] } )
Framework wiring

5 Wiring into your agent framework

Scalekit integrates directly with LangChain. The agent decides what to look up or write; Scalekit handles auth on every invocation. No token plumbing in your agent logic.

from langchain_anthropic import ChatAnthropic from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from scalekit.langchain import get_tools notion_tools = get_tools( connection_name="notion", identifier="user_notion_456" ) prompt = ChatPromptTemplate.from_messages([ ("system", "You are a knowledge assistant. Use the available tools to help search and manage Notion content."), MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad"), ]) agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-6"), notion_tools, prompt) result = AgentExecutor(agent=agent, tools=notion_tools).invoke({ "input": "Find all high-priority tasks in the Projects database due this month" })
Other frameworks supported
Tool reference

All 10 Notion tools

Grouped by capability. Your agent calls tools by name — no API wrappers to write.

Search
notion_data_fetch
Full-text search across the workspace using the Notion /search endpoint. Supports pagination via start_cursor
Pages
notion_page_create
Create a page inside a database (as a row) or as a child of an existing page. Accepts properties, child blocks, icon, and cover
Databases
notion_database_create
Create a new database under a parent page with a fully defined property schema
notion_database_fetch
Retrieve a database's title, properties, and full schema definition by ID
notion_database_insert_row
Insert a new row (page) into a database. Property keys must match the database schema exactly — case-sensitive
notion_database_property_retrieve
Query a database and return only specific properties by property ID — reduces payload for large databases
notion_database_query
Query database rows with optional sorting and pagination. Returns pages with all property values
Comments
notion_comment_create
Create a top-level comment on a page or reply within an existing discussion thread
notion_comment_retrieve
Retrieve a single comment by its ID
notion_comments_fetch
Fetch all comments for a given block or page. Supports pagination
Connector notes

Notion-specific behavior

BYOC is required — no managed app available
Unlike some Scalekit connectors, Notion requires you to register your own public integration in the Notion Developer Hub, configure the redirect URI, and supply your Client ID and Secret in the Scalekit dashboard before the authorization flow will work.
Agent access is limited to pages the user explicitly selected
During OAuth, Notion shows a page picker where the user selects which pages and databases to share. Your agent can only access those resources. API calls to anything outside that selection return a "page not found" error — not a permissions error. Communicate to users which pages and databases your agent needs before they complete the authorization flow.
Infrastructure decision

Why not build this yourself

The Notion OAuth flow is documented. Token storage isn't technically hard. But here's what you're actually signing up for:

PROBLEM 01
Registering and maintaining a public Notion integration with required legal pages, passing Notion's review, and managing OAuth app credentials separately from your application secrets
PROBLEM 02
Capability management — Notion's integration capabilities are set at registration time, not at auth time. Adding new capabilities after users have authorized does not update existing tokens
PROBLEM 03
Per-user token isolation across a multi-tenant system — one user's Notion access token must never be used for another user's workspace
PROBLEM 04
Revocation detection when users disconnect your integration from Notion's Settings — and proactive token refresh before expiry, not after a failed call

That's one connector. Your agent product will eventually need Salesforce, Gmail, HubSpot, Slack, and whatever else your customers ask for. Each has its own OAuth quirks and failure modes.

Scalekit maintains every connector. You maintain none of them.

Ready to ship

Connect your agent to Salesforce in minutes

Free to start. No Salesforce Connected App required. Token management fully handled.