Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.notion.com/llms.txt

Use this file to discover all available pages before exploring further.

Every capability’s execute function receives a Notion API client as context.notion. This is the official @notionhq/client SDK (the same one you’d use outside of Workers):
worker.tool("example", {
  // ...
  execute: async (input, { notion }) => {
    const page = await notion.pages.retrieve({ page_id: "..." });
    return page;
  },
});

Authentication

How the client is authenticated depends on how the capability runs:
ContextHow it works
Tool called by a Custom AgentThe platform sets NOTION_API_TOKEN automatically. The client has the same permissions as the Custom Agent. No setup needed.
Syncs, local testing, ntn workers execYou must provide a token yourself.
To set a token for syncs or local development, you have two options:
  • Personal access token: acts as you, with access to everything your user has access to. Simpler to set up since you don’t need to manually connect it to each page.
  • Internal integration token: acts as a bot, with access limited to pages explicitly connected via the Connections menu.
1

Create a token

Create a personal access token or an internal integration and copy the token.
2

Store the token as a secret

ntn workers env set NOTION_API_TOKEN=ntn_...
3

Grant access (internal integrations only)

If using an internal integration, open each page or database your worker needs access to, click the three-dot menu in the top right, and add the integration under Connections. This step is not needed for personal access tokens.
For local development, pull secrets to a .env file so the token is available when running ntn workers exec:
ntn workers env pull

Common operations

The examples below use { notion } destructured from the second argument to execute. They work the same way in tools and syncs:

Query a database

const response = await notion.databases.query({
  database_id: "...",
  filter: {
    property: "Status",
    select: { equals: "Active" },
  },
});

for (const page of response.results) {
  // process each page
}

Retrieve a page

const page = await notion.pages.retrieve({
  page_id: "...",
});

Create a page

await notion.pages.create({
  parent: { database_id: "..." },
  properties: {
    Name: {
      title: [{ text: { content: "New item" } }],
    },
    Status: {
      select: { name: "Open" },
    },
  },
});

Update page properties

await notion.pages.update({
  page_id: "...",
  properties: {
    Status: {
      select: { name: "Done" },
    },
  },
});
const results = await notion.search({
  query: "meeting notes",
  filter: { property: "object", value: "page" },
});

Read page content (blocks)

const blocks = await notion.blocks.children.list({
  block_id: pageId,
});

Permissions

What the client can access depends on the token type:
  • Custom Agent tools: the client has the same permissions as the Custom Agent.
  • Personal access token: the client can access everything you can access in Notion.
  • Internal integration token: the client can only access pages and databases that the integration has been explicitly connected to via the Connections menu.
If a request returns a 403 or 404, check that your token has access to the relevant page. For full SDK documentation, see the Notion API reference and the TypeScript SDK on GitHub.

Next steps

Syncs

Sync external data into Notion databases.

Agent tools

Build custom tools for Notion AI.

OAuth

Connect to third-party APIs with user authorization.

Secrets

Store API keys and credentials securely.