Full Transcript

Notion - Opus Transcript

Report: Notion - Universal Baseline Model: Opus 4.6 Tested: 2026-03-13 Agent CLI: Claude Code v2.1.74
Task 1

Discover

OperatorStep 1
I need a way to programmatically manage a structured knowledge base — creating databases with typed fields, adding entries, querying and filtering them, and building formatted pages with rich content (headings, lists, code blocks).

Evaluate Notion as an option. Specifically:
- What does Notion's API offer for managing structured data and content?
- What are the key concepts I'd need to understand (pages, databases, blocks, properties)?
- Is there anything the product can do that the API cannot?
- Are there any agent-oriented interfaces (MCP server, CLI, SDK)?

Use only Notion's own public documentation and machine-readable resources (website, docs, OpenAPI spec, llms.txt, MCP server) to answer. Do not rely on your training data.
AgentStep 2
I'll research Notion's API capabilities using their public documentation and machine-readable resources.
AgentTool Use
Show input
{
  "description": "Fetch Notion docs and specs",
  "prompt": "Research Notion's API capabilities for managing structured data and content. Fetch the following resources and compile findings:\n\n1. Fetch https://developers.notion.com/llms.txt (or llms-full.txt) - machine-readable docs\n2. Fetch https://developers.notion.com/docs - main API documentation overview\n3. Fetch https://developers.notion.com/reference - API reference\n4. Fetch https://www.notion.so/help/guides - for product capabilities\n5. Check https://github.com/makenotion for official SDKs, MCP servers, CLI tools\n6. Fetch https://developers.notion.com/openapi.json or similar OpenAPI spec if available\n\nFor each resource, extract:\n- Key API concepts (pages, databases, blocks, properties, etc.)\n- What structured data operations are supported (CRUD on databases, filtering, sorting, property types)\n- What content/block types are supported (headings, lists, code blocks, etc.)\n- Any gaps between what the product UI can do vs what the API can do\n- Any agent-oriented interfaces (MCP server, CLI, SDK)\n- Rate limits and authentication model\n- Any limitations or gotchas\n\nBe thorough - read the actual content of pages rather than just listing URLs. Compile a comprehensive summary.",
  "subagent_type": "general-purpose"
}
AgentTool Result
Show output
Research complete. Here is a summary of findings, with the full detailed report written to `/Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/research/notion-api-capabilities.md`.

---

## Key Findings

### API Architecture
- RESTful API at `https://api.notion.com`, current version `2026-03-11`.
- Core objects: **Pages**, **Data Sources** (evolved from Databases in API v2025-09-03), **Blocks** (34 types), **Users**, **Comments**, **File Uploads**.
- New Markdown endpoints (`GET/PATCH /v1/pages/:id/markdown`) allow reading and writing page content as Notion-flavored Markdown -- a significant improvement for agent workflows.

### Structured Data Operations
- **20 database property types** with full CRUD on most (Title, Rich Text, Number, Select, Multi-select, Date, Checkbox, URL, Email, Phone, Files, People, Relation). Formula and Rollup are read-only.
- **Compound filters** (and/or, nestable) with property-type-specific operators. Sorts on any property or timestamps.
- **Pagination**: cursor-based, max 100 items per page.
- **Cannot create Status properties** via API (can only read/write values on existing ones).

### Content/Block Types
- 34 block types documented. Most are fully creatable (paragraphs, headings, lists, to-dos, code, images, tables, callouts, toggles, etc.).
- Read-only blocks: Link Preview, Meeting Notes.
- UI-only blocks returned as `"unsupported"`: Forms, Buttons, some automation blocks.

### Major UI-vs-API Gaps
- **No database view management** (table, board, timeline, calendar, chart, gallery views cannot be created/read/managed via API).
- **No linked databases or wiki databases** via API.
- **Title-only search** (no full-text content search).
- **No automations, forms, buttons, charts, AI features, page analytics, or permissions management** via API.
- **No Notion Mail or Notion Calendar** API access.

### Rate Limits
- **3 requests/second average** (quite restrictive). HTTP 429 with `Retry-After` header.
- 500KB max request body, 1000 blocks max per request, 100 blocks per append, rich text capped at 2,000 chars.
- File URLs expire after 1 hour.

### Agent Interfaces
- **Official MCP Server** (`@notionhq/notion-mcp-server`): 22 tools for AI agents, supports STDIO and HTTP transport. Deprecation warning -- Notion is shifting to a remote MCP server.
- **Official JS/TypeScript SDK** (`@notionhq/client`): Full API coverage, auto-retry, pagination utilities, type-safe.
- **No official CLI tool** found.
- **Notion Custom Agents**: Built-in product feature where agents connect to external tools via MCP; integrates with Cursor IDE.

### Authentication
- Internal integrations: static token (`ntn_****`), pages must be explicitly shared.
- Public integrations: OAuth 2.0 with refresh tokens (`nrt_****`).
- Key constraint: integration access is page-by-page, not workspace-wide.

### Critical Gotchas
1. The 25-reference limit on relations in formulas/rollups can silently produce wrong results.
2. Template application is async -- pages return blank, requiring polling or webhooks.
3. The data source vs database split (v2025-09-03) is a breaking change requiring migration from `database_id` to `data_source_id`.
4. No bulk operations -- each page is a separate API call at 3 req/sec.
5. `table_width` and synced block content are immutable after creation.
agentId: a79d53ccaeab62537 (for resuming to continue this agent's work if needed)
<usage>total_tokens: 32474
tool_uses: 20
duration_ms: 265555</usage>
AgentStep 3
## Notion API Evaluation

### Core Concepts

Notion's data model has four primitives:

| Concept | Role |
|---|---|
| **Page** | A container — can hold blocks (content) or be a row in a database. Every page has a parent (workspace, page, or database). |
| **Database** | A typed schema (called "Data Source" in API v2025+). Defines property columns; each row is a page. |
| **Block** | A unit of content inside a page — paragraph, heading, list item, code block, table, image, etc. (34 types). Blocks nest to form trees. |
| **Property** | A typed field on a database — 20 types including Title, Number, Select, Multi-select, Date, Relation, Formula, Rollup, Checkbox, URL, etc. |

### What the API Can Do

**Structured data (databases):**
- Full CRUD on databases and their rows (pages)
- 20 property types with typed schemas
- Compound filters (nested and/or) with type-specific operators (contains, equals, before, greater_than, etc.)
- Sorting on any property or timestamp
- Cursor-based pagination (100 items/page)

**Rich content (blocks):**
- Create/read/update/delete ~30 block types: headings (h1-h3), bulleted/numbered/to-do lists, code blocks (with language), tables, callouts, toggles, images, embeds, dividers, quotes, bookmarks
- New Markdown endpoints (`GET/PATCH /v1/pages/:id/markdown`) for reading/writing entire pages as Markdown — very useful for agent workflows
- Append up to 100 child blocks per request; nest blocks arbitrarily

**Other:**
- Search across page/database titles (not full-text content)
- Comments API (read/write)
- File upload API
- User listing

### What the Product Can Do That the API Cannot

This is a significant list:

- **Database views** — table, board, timeline, calendar, gallery, chart views are completely invisible to the API
- **Linked/wiki databases** — cannot create or manage
- **Status properties** — can read/write values but cannot create the property itself
- **Forms, Buttons, Automations** — product-only features, returned as `"unsupported"` block types
- **AI features** — summarization, Q&A, autofill — no API access
- **Full-text search** — API only searches titles, not page content
- **Permissions/sharing** — no API for managing access controls
- **Page analytics, Notion Calendar, Notion Mail** — no API access
- **Formula/Rollup properties** — read-only (cannot create or modify definitions)
- **Bulk operations** — no batch endpoints; each page is a separate call

### Agent-Oriented Interfaces

| Interface | Status |
|---|---|
| **MCP Server** (`@notionhq/notion-mcp-server`) | Official, 22 tools, STDIO+HTTP transport. Being deprecated in favor of a remote MCP server hosted by Notion. |
| **JS/TS SDK** (`@notionhq/client`) | Official, full API coverage, auto-retry, pagination helpers, type-safe. |
| **Python SDK** | Community-maintained only. |
| **CLI** | None official. |
| **Notion Custom Agents** | Product feature — build agents inside Notion that call external MCP tools. |

### Key Constraints for Programmatic Use

1. **Rate limit: 3 req/sec** — very restrictive for bulk operations. No batch endpoints exist, so inserting 1,000 rows takes ~6 minutes minimum.
2. **Explicit sharing required** — integrations only see pages explicitly shared with them (not workspace-wide).
3. **Rich text capped at 2,000 characters** per rich-text element; request body max 500KB.
4. **File URLs expire** after 1 hour — must re-fetch.
5. **Title-only search** — for full-text search you'd need to fetch and index content yourself.
6. **No views API** — you can define the data schema but not how it's displayed.

### Bottom Line

Notion's API is solid for **CRUD on structured databases with typed properties** and **building pages with rich block content**. The filtering/sorting on databases is well-designed. The new Markdown endpoints and official MCP server make it practical for agent workflows.

The main gaps are: no view management, no full-text search, no bulk operations, a tight rate limit, and several product features (automations, AI, forms, charts) that have no API surface. If your use case is primarily "create schemas, insert/query typed records, and build formatted pages programmatically," Notion covers that well. If you need high-throughput bulk operations or advanced UI features, the limitations are real.
Task 2

Onboard

OperatorStep 1
Set up everything needed to make API calls against a Notion workspace. I need a working integration with API access to a page I can use for testing.

Do as much as you can autonomously. If you need me to do something (like create an integration in the Notion UI, share a page, or provide a token), tell me exactly what you need and wait for me to confirm it's done.
AgentStep 2
I'll set up the project scaffolding now while you handle the parts that require the Notion UI.

**I need you to do these 3 things:**

### Step 1: Create an internal integration
1. Go to **https://www.notion.so/profile/integrations**
2. Click **"New integration"**
3. Name it something like `api-test`
4. Select your workspace
5. Keep the default capabilities (Read/Update/Insert content)
6. Click **Submit**
7. Copy the **Internal Integration Secret** (starts with `ntn_`)

### Step 2: Create a test page
1. In Notion, create a new page called **"API Testing"** (or any name)
2. It can be empty — we'll populate it via the API

### Step 3: Share the page with your integration
1. On that test page, click **"..."** (top-right) → **"Connections"** → **"Connect to"**
2. Search for your integration name (`api-test`) and add it

Once done, paste me:
- The **integration token** (`ntn_...`)
- The **page URL** (I'll extract the page ID from it)

While you do that, I'll set up the SDK and test harness.
BashTool Use
Show input
{
  "command": "ls /Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/",
  "description": "List current project directory"
}
BashTool Result
Show output
RUN-CHECKLIST.md
model-id.txt
prompts
research
BashTool Use
Show input
{
  "command": "npm init -y 2>&1 | tail -5",
  "description": "Initialize npm project"
}
BashTool Result
Show output
  "license": "ISC",
  "type": "commonjs"
}
BashTool Use
Show input
{
  "command": "npm install @notionhq/client 2>&1 | tail -3",
  "description": "Install official Notion SDK"
}
BashTool Result
Show output
npm error To permanently fix this problem, please run:
npm error   sudo chown -R 501:20 "/Users/mattsteen/.npm"
npm error A complete log of this run can be found in: /Users/mattsteen/.npm/_logs/2026-03-13T12_42_25_868Z-debug-0.log
BashTool Use
Show input
{
  "command": "npm install @notionhq/client 2>&1 | tail -5",
  "description": "Retry Notion SDK install",
  "dangerouslyDisableSandbox": true
}
BashTool Result
Show output
added 1 package, and audited 2 packages in 1s

found 0 vulnerabilities
WriteTool Use
Show input
{
  "file_path": "/Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/.env.example",
  "content": "NOTION_TOKEN=ntn_[REDACTED]_TOKEN_HERE\nNOTION_TEST_PAGE_ID=YOUR_PAGE_ID_HERE\n"
}
WriteTool Result
Show output
File created successfully at: /Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/.env.example
WriteTool Use
Show input
{
  "file_path": "/Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/.gitignore",
  "content": "node_modules/\n.env\n"
}
WriteTool Result
Show output
File created successfully at: /Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/.gitignore
WriteTool Use
Show input
{
  "file_path": "/Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/scripts/verify-connection.mjs",
  "content": "/**\n * Verify Notion API connection.\n * Usage: NOTION_TOKEN=ntn_... NOTION_TEST_PAGE_ID=... node scripts/verify-connection.mjs\n */\nimport { Client } from \"@notionhq/client\";\n\nconst token = process.env.NOTION_TOKEN;\nconst pageId = process.env.NOTION_TEST_PAGE_ID;\n\nif (!token || !pageId) {\n  console.error(\"Set NOTION_TOKEN and NOTION_TEST_PAGE_ID env vars\");\n  process.exit(1);\n}\n\nconst notion = new Client({ auth: token });\n\n// 1. Verify auth by fetching bot user info\nconst me = await notion.users.me({});\nconsole.log(`✓ Authenticated as: ${me.name} (${me.type})`);\n\n// 2. Verify page access\nconst page = await notion.pages.retrieve({ page_id: pageId });\nconst title =\n  page.properties?.title?.title?.[0]?.plain_text ??\n  page.properties?.Name?.title?.[0]?.plain_text ??\n  \"(untitled)\";\nconsole.log(`✓ Page accessible: \"${title}\" (${page.id})`);\n\n// 3. Append a test block to prove write access\nconst response = await notion.blocks.children.append({\n  block_id: pageId,\n  children: [\n    {\n      object: \"block\",\n      type: \"paragraph\",\n      paragraph: {\n        rich_text: [\n          {\n            type: \"text\",\n            text: { content: `API connection verified at ${new Date().toISOString()}` },\n          },\n        ],\n      },\n    },\n  ],\n});\nconsole.log(`✓ Write access confirmed (appended block ${response.results[0].id})`);\n\nconsole.log(\"\\nNotion API setup is working. Ready to go.\");\n"
}
WriteTool Result
Show output
File created successfully at: /Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/scripts/verify-connection.mjs
AgentStep 3
The SDK is installed and the verification script is ready. Here's what I set up:

- **`@notionhq/client`** — official Notion JS SDK
- **`scripts/verify-connection.mjs`** — tests auth, page read, and page write in one shot
- **`.env.example`** / **`.gitignore`** — keeps your token out of version control

**Waiting on you** — once you've created the integration, test page, and shared it, give me:
1. Your integration token (`ntn_...`)
2. The test page URL (e.g. `https://www.notion.so/My-Page-abc123def456...`)
OperatorStep 4
Your instructions landed me on the public integration form, which requires OAuth setup, company
  details, etc. I can see "Internal integrations" in the left sidebar — I'll use that instead.
  Continuing with your other steps.
AgentStep 5
Good catch — yes, **Internal integration** is the right one. It gives you a token immediately without OAuth setup.

I'll save this for future reference.
WriteTool Use
Show input
{
  "file_path": "/Users/mattsteen/.claude/projects/-Users-mattsteen-dev-audits-notion-universal-baseline-2026-03-13-opus/memory/feedback_notion_integration_setup.md",
  "content": "---\nname: Notion integration setup path\ndescription: The correct URL path for creating Notion internal integrations vs public ones\ntype: feedback\n---\n\nWhen directing users to create a Notion internal integration, link to https://www.notion.so/profile/integrations and tell them to click \"Internal integrations\" in the left sidebar, then \"New integration\". The default landing page at that URL shows the public integration form which requires OAuth setup, company details, etc.\n\n**Why:** User landed on the public integration form and had to find the internal integrations section themselves.\n**How to apply:** Always specify \"Internal integrations\" sidebar link when giving Notion setup instructions.\n"
}
WriteTool Result
Show output
File created successfully at: /Users/mattsteen/.claude/projects/-Users-mattsteen-dev-audits-notion-universal-baseline-2026-03-13-opus/memory/feedback_notion_integration_setup.md
ReadTool Use
Show input
{
  "file_path": "/Users/mattsteen/.claude/projects/-Users-mattsteen-dev-audits-notion-universal-baseline-2026-03-13-opus/memory/MEMORY.md"
}
ReadTool Result
Show output
File does not exist. Note: your current working directory is /Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus.
WriteTool Use
Show input
{
  "file_path": "/Users/mattsteen/.claude/projects/-Users-mattsteen-dev-audits-notion-universal-baseline-2026-03-13-opus/memory/MEMORY.md",
  "content": "# Memory Index\n\n- [feedback_notion_integration_setup.md](feedback_notion_integration_setup.md) — Correct URL/path for creating Notion internal integrations\n"
}
WriteTool Result
Show output
File created successfully at: /Users/mattsteen/.claude/projects/-Users-mattsteen-dev-audits-notion-universal-baseline-2026-03-13-opus/memory/MEMORY.md
AgentStep 6
Thanks for the correction. Standing by for your token and page URL whenever you're ready.
OperatorStep 7
Ok, I completed steps 1 to 3:

integration secret: ntn_[REDACTED]

Page URL: https://www.notion.so/API-Testing-32226b2ff6f1801c90d1fe890660d065
WriteTool Use
Show input
{
  "file_path": "/Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/.env",
  "content": "NOTION_TOKEN=ntn_[REDACTED]\nNOTION_TEST_PAGE_ID=32226b2ff6f1801c90d1fe890660d065\n"
}
WriteTool Result
Show output
File created successfully at: /Users/mattsteen/dev/audits/notion-universal-baseline-2026-03-13-opus/.env
BashTool Use
Show input
{
  "command": "export $(cat .env | xargs) && node scripts/verify-connection.mjs 2>&1",
  "description": "Run Notion API verification script"
}
BashTool Result
Show output
Exit code 1
node:internal/modules/run_main:107
    triggerUncaughtException(
    ^

[TypeError: fetch failed] {
  [cause]: Error: getaddrinfo ENOTFOUND api.notion.com
      at GetAddrInfoReqWrap.onlookupall [as oncomplete] (node:dns:121:26) {
    errno: -3008,
    code: 'ENOTFOUND',
    syscall: 'getaddrinfo',
    hostname: 'api.notion.com'
  }
}

Node.js v25.6.1
AgentStep 8
Sandbox is blocking the network request. Let me retry with network access.
BashTool Use
Show input
{
  "command": "export $(cat .env | xargs) && node scripts/verify-connection.mjs 2>&1",
  "description": "Run Notion API verification script",
  "dangerouslyDisableSandbox": true
}
BashTool Result
Show output
✓ Authenticated as: api-test (bot)
✓ Page accessible: "API Testing" (32226b2f-f6f1-801c-90d1-fe890660d065)
✓ Write access confirmed (appended block 32226b2f-f6f1-81e5-a895-d02eb71fc056)

Notion API setup is working. Ready to go.
AgentStep 9
Everything works. You should see a new paragraph on your "API Testing" page confirming the connection.

**Setup summary:**
- **Auth:** `api-test` bot, authenticated
- **Page:** "API Testing" (`32226b2f-f6f1-801c-90d1-fe890660d065`) — read and write confirmed
- **Token/config:** stored in `.env` (git-ignored)
- **SDK:** `@notionhq/client` installed, scripts in `scripts/`

Ready to start exercising the API.