mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-18 04:41:56 +00:00
feat(skills/notion): overhaul for Notion Developer Platform (May 2026) (#26612)
* feat(skills/notion): overhaul for Notion Developer Platform (May 2026) Notion shipped its Developer Platform on May 13, 2026: ntn CLI, Workers, Markdown API, bidirectional webhooks, agent tools. The existing skill only covered curl + integration token CRUD, so it didn't surface any of the new ergonomics — particularly the /markdown endpoints (much easier for agents to consume) and the ntn CLI for headless API + Workers management. This rewrite (v1.0.0 -> v2.0.0): - Splits setup into Path A (HTTP, cross-platform incl. Windows), Path B (ntn CLI on macOS/Linux, with NOTION_API_TOKEN env var for headless), and Path C (Windows fallback — HTTP API or WSL2; native ntn is 'coming soon'). - Keeps the full curl reference (still the only Windows-compatible path). - Adds /markdown endpoints — GET and PATCH page-as-markdown, plus POST /v1/pages with a markdown body param. Agent-friendly, no CLI required. - Adds ntn CLI cheat sheet for raw API shorthand, file uploads, and workspace flags. - Adds Notion Workers section: scaffold, tool/webhook capability shapes, lifecycle commands. Gated on Business/Enterprise plans + macOS/Linux. - Adds Notion-flavored Markdown reference (callouts, toggles, columns, mentions, colors) for the /markdown endpoints. - Adds a 'choose the right path' decision table at the bottom. - Notes the new efficient Notion MCP server as an optional wiring path. Auto-generated docs page regenerated via website/scripts/generate-skill-docs.py. * docs(skills-catalog): update notion description for v2.0.0
This commit is contained in:
parent
887ba1fb03
commit
42070ecefb
3 changed files with 632 additions and 80 deletions
|
|
@ -1,35 +1,158 @@
|
||||||
---
|
---
|
||||||
name: notion
|
name: notion
|
||||||
description: "Notion API via curl: pages, databases, blocks, search."
|
description: "Notion API + ntn CLI: pages, databases, markdown, Workers."
|
||||||
version: 1.0.0
|
version: 2.0.0
|
||||||
author: community
|
author: community
|
||||||
license: MIT
|
license: MIT
|
||||||
platforms: [linux, macos, windows]
|
platforms: [linux, macos, windows]
|
||||||
metadata:
|
|
||||||
hermes:
|
|
||||||
tags: [Notion, Productivity, Notes, Database, API]
|
|
||||||
homepage: https://developers.notion.com
|
|
||||||
prerequisites:
|
prerequisites:
|
||||||
env_vars: [NOTION_API_KEY]
|
env_vars: [NOTION_API_KEY]
|
||||||
|
metadata:
|
||||||
|
hermes:
|
||||||
|
tags: [Notion, Productivity, Notes, Database, API, CLI, Workers]
|
||||||
|
homepage: https://developers.notion.com
|
||||||
---
|
---
|
||||||
|
|
||||||
# Notion API
|
# Notion
|
||||||
|
|
||||||
Use the Notion API via curl to create, read, update pages, databases (data sources), and blocks. No extra tools needed — just curl and a Notion API key.
|
Talk to Notion two ways. Same integration token works for both — pick by what's available.
|
||||||
|
|
||||||
## Prerequisites
|
◆ **`ntn` CLI** — Notion's official CLI. Shorter syntax, one-line file uploads, required for Workers. macOS + Linux only as of May 2026 (Windows support "coming soon"). **Default when installed.**
|
||||||
|
◆ **HTTP + curl** — works everywhere including Windows. **Default fallback** when `ntn` isn't installed.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### 1. Get an integration token (required for both paths)
|
||||||
|
|
||||||
1. Create an integration at https://notion.so/my-integrations
|
1. Create an integration at https://notion.so/my-integrations
|
||||||
2. Copy the API key (starts with `ntn_` or `secret_`)
|
2. Copy the API key (starts with `ntn_` or `secret_`)
|
||||||
3. Store it in `~/.hermes/.env`:
|
3. Store in `~/.hermes/.env`:
|
||||||
```
|
```
|
||||||
NOTION_API_KEY=ntn_your_key_here
|
NOTION_API_KEY=ntn_your_key_here
|
||||||
```
|
```
|
||||||
4. **Important:** Share target pages/databases with your integration in Notion (click "..." → "Connect to" → your integration name)
|
4. **Share target pages/databases with the integration** in Notion: page menu `...` → `Connect to` → your integration name. Without this, the API returns 404 for that page even though it exists.
|
||||||
|
|
||||||
|
### 2. Install `ntn` (preferred path on macOS / Linux)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Recommended
|
||||||
|
curl -fsSL https://ntn.dev | bash
|
||||||
|
|
||||||
|
# Or via npm (needs Node 22+, npm 10+)
|
||||||
|
npm install --global ntn
|
||||||
|
|
||||||
|
ntn --version # verify
|
||||||
|
```
|
||||||
|
|
||||||
|
**Skip `ntn login` — use the integration token instead.** This works headlessly, no browser needed:
|
||||||
|
```bash
|
||||||
|
export NOTION_API_TOKEN=$NOTION_API_KEY # ntn reads NOTION_API_TOKEN
|
||||||
|
export NOTION_KEYRING=0 # don't try to use the OS keychain
|
||||||
|
```
|
||||||
|
|
||||||
|
Add those exports to your shell profile (or to `~/.hermes/.env`) so every session inherits them.
|
||||||
|
|
||||||
|
### 3. Choose path at runtime
|
||||||
|
|
||||||
|
```bash
|
||||||
|
if command -v ntn >/dev/null 2>&1; then
|
||||||
|
# use ntn
|
||||||
|
else
|
||||||
|
# fall back to curl
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows users: skip step 2 entirely until native `ntn` ships — Path B works fine. If you want CLI ergonomics now, install `ntn` inside WSL2.
|
||||||
|
|
||||||
## API Basics
|
## API Basics
|
||||||
|
|
||||||
All requests use this pattern:
|
`Notion-Version: 2025-09-03` is required on all HTTP requests. `ntn` handles this for you. In this version, what users call "databases" are called **data sources** in the API.
|
||||||
|
|
||||||
|
## Path A — `ntn` CLI (preferred, macOS / Linux)
|
||||||
|
|
||||||
|
### Raw API calls (shorthand for curl)
|
||||||
|
```bash
|
||||||
|
ntn api v1/users # GET
|
||||||
|
ntn api v1/pages parent[page_id]=abc123 \ # POST with inline body
|
||||||
|
properties[title][0][text][content]="Notes"
|
||||||
|
ntn api v1/pages/abc123 -X PATCH archived:=true # PATCH; := is non-string (bool/num/null)
|
||||||
|
```
|
||||||
|
|
||||||
|
Syntax notes:
|
||||||
|
- `key=value` — string fields
|
||||||
|
- `key[nested]=value` — nested object fields
|
||||||
|
- `key:=value` — typed assignment (booleans, numbers, null, arrays)
|
||||||
|
|
||||||
|
### Search
|
||||||
|
```bash
|
||||||
|
ntn api v1/search query="page title"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page metadata
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages/{page_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page as Markdown (agent-friendly)
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages/{page_id}/markdown
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page content as blocks
|
||||||
|
```bash
|
||||||
|
ntn api v1/blocks/{page_id}/children
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create page from Markdown
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages \
|
||||||
|
parent[page_id]=xxx \
|
||||||
|
properties[title][0][text][content]="Notes from meeting" \
|
||||||
|
markdown="# Agenda
|
||||||
|
|
||||||
|
- Q3 roadmap
|
||||||
|
- Hiring"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Patch a page with Markdown
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages/{page_id}/markdown -X PATCH \
|
||||||
|
markdown="## Update
|
||||||
|
|
||||||
|
Shipped the prototype."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Query a database (data source)
|
||||||
|
```bash
|
||||||
|
ntn api v1/data_sources/{data_source_id}/query -X POST \
|
||||||
|
filter[property]=Status filter[select][equals]=Active
|
||||||
|
```
|
||||||
|
|
||||||
|
For complex queries with `sorts`, multiple filter clauses, or compound logic, pipe JSON in:
|
||||||
|
```bash
|
||||||
|
echo '{"filter": {"property": "Status", "select": {"equals": "Active"}}, "sorts": [{"property": "Date", "direction": "descending"}]}' | \
|
||||||
|
ntn api v1/data_sources/{data_source_id}/query -X POST --json -
|
||||||
|
```
|
||||||
|
|
||||||
|
### File uploads (one-liner — biggest CLI win)
|
||||||
|
```bash
|
||||||
|
ntn files create < photo.png
|
||||||
|
ntn files create --external-url https://example.com/photo.png
|
||||||
|
ntn files list
|
||||||
|
```
|
||||||
|
|
||||||
|
Compare to the 3-step HTTP flow (create upload → PUT bytes → reference).
|
||||||
|
|
||||||
|
### Useful env vars
|
||||||
|
| Var | Effect |
|
||||||
|
|---|---|
|
||||||
|
| `NOTION_API_TOKEN` | Auth token (overrides keychain) — set this to your integration token |
|
||||||
|
| `NOTION_KEYRING=0` | File-based creds at `~/.config/notion/auth.json` instead of OS keychain |
|
||||||
|
| `NOTION_WORKSPACE_ID` | Skip the workspace picker prompt |
|
||||||
|
|
||||||
|
## Path B — HTTP + curl (cross-platform, default on Windows)
|
||||||
|
|
||||||
|
All requests share this pattern:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X GET "https://api.notion.com/v1/..." \
|
curl -s -X GET "https://api.notion.com/v1/..." \
|
||||||
|
|
@ -38,12 +161,9 @@ curl -s -X GET "https://api.notion.com/v1/..." \
|
||||||
-H "Content-Type: application/json"
|
-H "Content-Type: application/json"
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Notion-Version` header is required. This skill uses `2025-09-03` (latest). In this version, databases are called "data sources" in the API.
|
On Windows the `curl` shipped with Windows 10+ works as-is. PowerShell users can also use `Invoke-RestMethod`.
|
||||||
|
|
||||||
## Common Operations
|
|
||||||
|
|
||||||
### Search
|
### Search
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/search" \
|
curl -s -X POST "https://api.notion.com/v1/search" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -52,24 +172,56 @@ curl -s -X POST "https://api.notion.com/v1/search" \
|
||||||
-d '{"query": "page title"}'
|
-d '{"query": "page title"}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Get Page
|
### Read page metadata
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s "https://api.notion.com/v1/pages/{page_id}" \
|
curl -s "https://api.notion.com/v1/pages/{page_id}" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
-H "Notion-Version: 2025-09-03"
|
-H "Notion-Version: 2025-09-03"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Get Page Content (blocks)
|
### Read page as Markdown (agent-friendly)
|
||||||
|
|
||||||
|
Easier to feed to a model than block JSON.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s "https://api.notion.com/v1/pages/{page_id}/markdown" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page content as blocks (when you need structure)
|
||||||
```bash
|
```bash
|
||||||
curl -s "https://api.notion.com/v1/blocks/{page_id}/children" \
|
curl -s "https://api.notion.com/v1/blocks/{page_id}/children" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
-H "Notion-Version: 2025-09-03"
|
-H "Notion-Version: 2025-09-03"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create Page in a Database
|
### Create page from Markdown
|
||||||
|
|
||||||
|
`POST /v1/pages` accepts a `markdown` body param.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "https://api.notion.com/v1/pages" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"parent": {"page_id": "xxx"},
|
||||||
|
"properties": {"title": [{"text": {"content": "Notes from meeting"}}]},
|
||||||
|
"markdown": "# Agenda\n\n- Q3 roadmap\n- Hiring\n\n## Decisions\n- Ship MVP Friday"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Patch a page with Markdown
|
||||||
|
```bash
|
||||||
|
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}/markdown" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"markdown": "## Update\n\nShipped the prototype."}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create page in a database (typed properties)
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/pages" \
|
curl -s -X POST "https://api.notion.com/v1/pages" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -84,8 +236,7 @@ curl -s -X POST "https://api.notion.com/v1/pages" \
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Query a Database
|
### Query a database (data source)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \
|
curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -97,8 +248,7 @@ curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query"
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create a Database
|
### Create a database
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/data_sources" \
|
curl -s -X POST "https://api.notion.com/v1/data_sources" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -115,8 +265,7 @@ curl -s -X POST "https://api.notion.com/v1/data_sources" \
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Update Page Properties
|
### Update page properties
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
|
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -125,8 +274,7 @@ curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
|
||||||
-d '{"properties": {"Status": {"select": {"name": "Done"}}}}'
|
-d '{"properties": {"Status": {"select": {"name": "Done"}}}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Add Content to a Page
|
### Append blocks to a page
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
|
curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -139,6 +287,21 @@ curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### File uploads (3-step flow)
|
||||||
|
```bash
|
||||||
|
# 1. Create upload
|
||||||
|
curl -s -X POST "https://api.notion.com/v1/file_uploads" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"filename": "photo.png", "content_type": "image/png"}'
|
||||||
|
|
||||||
|
# 2. PUT bytes to the upload_url returned above
|
||||||
|
curl -s -X PUT "{upload_url}" --data-binary @photo.png
|
||||||
|
|
||||||
|
# 3. Reference {file_upload_id} in a page/block payload
|
||||||
|
```
|
||||||
|
|
||||||
## Property Types
|
## Property Types
|
||||||
|
|
||||||
Common property formats for database items:
|
Common property formats for database items:
|
||||||
|
|
@ -154,19 +317,132 @@ Common property formats for database items:
|
||||||
- **Email:** `{"email": "user@example.com"}`
|
- **Email:** `{"email": "user@example.com"}`
|
||||||
- **Relation:** `{"relation": [{"id": "page_id"}]}`
|
- **Relation:** `{"relation": [{"id": "page_id"}]}`
|
||||||
|
|
||||||
## Key Differences in API Version 2025-09-03
|
## API Version 2025-09-03 — Databases vs Data Sources
|
||||||
|
|
||||||
- **Databases → Data Sources:** Use `/data_sources/` endpoints for queries and retrieval
|
- **Databases became data sources.** Use `/data_sources/` endpoints for queries and retrieval.
|
||||||
- **Two IDs:** Each database has both a `database_id` and a `data_source_id`
|
- **Two IDs per database:** `database_id` and `data_source_id`.
|
||||||
- Use `database_id` when creating pages (`parent: {"database_id": "..."}`)
|
- `database_id` when creating pages: `parent: {"database_id": "..."}`
|
||||||
- Use `data_source_id` when querying (`POST /v1/data_sources/{id}/query`)
|
- `data_source_id` when querying: `POST /v1/data_sources/{id}/query`
|
||||||
- **Search results:** Databases return as `"object": "data_source"` with their `data_source_id`
|
- Search returns databases as `"object": "data_source"` with the `data_source_id` field.
|
||||||
|
|
||||||
|
## Notion Workers (advanced, requires `ntn`)
|
||||||
|
|
||||||
|
Workers are TypeScript programs Notion hosts for you. One worker can expose any combination of:
|
||||||
|
- **Syncs** — pull data from external APIs into a Notion database on a schedule (default 30 min).
|
||||||
|
- **Tools** — appear as callable tools inside Notion's Custom Agents.
|
||||||
|
- **Webhooks** — receive HTTP events from external services (GitHub, Stripe, etc.) and act in Notion.
|
||||||
|
|
||||||
|
**Plan / platform gating:**
|
||||||
|
- CLI works on all plans. **Deploying Workers requires Business or Enterprise.**
|
||||||
|
- `ntn` is macOS/Linux only as of May 2026. Windows users need WSL2 or to wait for native support.
|
||||||
|
- Free through August 11, 2026; metered on Notion credits after.
|
||||||
|
|
||||||
|
### Minimal Worker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ntn workers new my-worker # scaffold
|
||||||
|
cd my-worker
|
||||||
|
# Edit src/index.ts
|
||||||
|
ntn workers deploy --name my-worker
|
||||||
|
```
|
||||||
|
|
||||||
|
`src/index.ts`:
|
||||||
|
```typescript
|
||||||
|
import { Worker } from "@notionhq/workers";
|
||||||
|
|
||||||
|
const worker = new Worker();
|
||||||
|
export default worker;
|
||||||
|
|
||||||
|
worker.tool("greet", {
|
||||||
|
title: "Greet a User",
|
||||||
|
description: "Returns a friendly greeting",
|
||||||
|
inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] },
|
||||||
|
execute: async ({ name }) => `Hello, ${name}!`,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Webhook capability
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
worker.webhook("onGithubPush", {
|
||||||
|
title: "GitHub Push Handler",
|
||||||
|
execute: async (events, { notion }) => {
|
||||||
|
for (const event of events) {
|
||||||
|
// event.body, event.rawBody (for signature verification), event.headers
|
||||||
|
console.log("got delivery", event.deliveryId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
After deploy: `ntn workers webhooks list` shows the URL Notion generates. Treat that URL as a secret — anyone with it can POST events unless you add signature verification.
|
||||||
|
|
||||||
|
### Worker lifecycle commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ntn workers deploy
|
||||||
|
ntn workers list
|
||||||
|
ntn workers exec <capability-key> -d '{"name": "world"}'
|
||||||
|
ntn workers sync trigger <key> # run a sync now
|
||||||
|
ntn workers sync pause <key>
|
||||||
|
ntn workers env set GITHUB_WEBHOOK_SECRET=...
|
||||||
|
ntn workers runs list # recent invocations
|
||||||
|
ntn workers runs logs <run-id>
|
||||||
|
ntn workers webhooks list
|
||||||
|
```
|
||||||
|
|
||||||
|
When asked to build a Worker, scaffold with `ntn workers new`, write the code in `src/index.ts`, set any secrets with `ntn workers env set`, and deploy. Notion's docs at https://developers.notion.com/workers cover the full API surface.
|
||||||
|
|
||||||
|
## Notion-Flavored Markdown (used by `/markdown` endpoints)
|
||||||
|
|
||||||
|
Standard CommonMark plus XML-like tags for Notion-specific blocks. Use **tabs** for indentation.
|
||||||
|
|
||||||
|
**Blocks beyond CommonMark:**
|
||||||
|
```
|
||||||
|
<callout icon="🎯" color="blue_bg">
|
||||||
|
Ship the MVP by **Friday**.
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
<details color="gray">
|
||||||
|
<summary>Toggle title</summary>
|
||||||
|
Children indented one tab
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<columns>
|
||||||
|
<column>Left side</column>
|
||||||
|
<column>Right side</column>
|
||||||
|
</columns>
|
||||||
|
|
||||||
|
<table_of_contents color="gray"/>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Inline:**
|
||||||
|
- Mentions: `<mention-user url="..."/>`, `<mention-page url="...">Title</mention-page>`, `<mention-date start="2026-05-15"/>`
|
||||||
|
- Underline: `<span underline="true">text</span>`
|
||||||
|
- Color: `<span color="blue">text</span>` or block-level `{color="blue"}` on the first line
|
||||||
|
- Math: inline `$x^2$`, block `$$ ... $$`
|
||||||
|
- Citations: `[^https://example.com]`
|
||||||
|
|
||||||
|
**Colors:** `gray brown orange yellow green blue purple pink red`, plus `*_bg` variants for backgrounds.
|
||||||
|
|
||||||
|
Headings 5/6 collapse to H4. Multiple `>` lines render as separate quote blocks — use `<br>` inside a single `>` for multi-line quotes.
|
||||||
|
|
||||||
|
## Choosing the Right Path
|
||||||
|
|
||||||
|
| Task | mac / Linux | Windows |
|
||||||
|
|---|---|---|
|
||||||
|
| Read/write pages, search, query databases | `ntn api ...` | curl |
|
||||||
|
| Read a page for an agent to summarize | `ntn api v1/pages/{id}/markdown` | curl `/markdown` endpoint |
|
||||||
|
| Upload a file | `ntn files create < file` | 3-step HTTP flow |
|
||||||
|
| One-off API exploration | `ntn api ...` | curl |
|
||||||
|
| Build a sync / webhook / agent tool hosted by Notion | `ntn workers ...` | WSL2 + `ntn workers ...` |
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- Page/database IDs are UUIDs (with or without dashes)
|
- Page/database IDs are UUIDs (with or without dashes — both accepted).
|
||||||
- Rate limit: ~3 requests/second average
|
- Rate limit: ~3 requests/second average. The CLI doesn't bypass this.
|
||||||
- The API cannot set database view filters — that's UI-only
|
- The API cannot set database **view** filters — that's UI-only.
|
||||||
- Use `is_inline: true` when creating data sources to embed them in pages
|
- Use `"is_inline": true` when creating data sources to embed them in a page.
|
||||||
- Add `-s` flag to curl to suppress progress bars (cleaner output for Hermes)
|
- Always pass `-s` to curl to suppress progress bars (cleaner agent output).
|
||||||
- Pipe output through `jq` for readable JSON: `... | jq '.results[0].properties'`
|
- Pipe JSON through `jq` when reading: `... | jq '.results[0].properties'`.
|
||||||
|
- Notion also ships an MCP server now (`Notion MCP`, ~91% more token-efficient on DB ops than the previous version) — wire it via Hermes' MCP support if you want streaming Notion access from inside a session, but the paths above are enough for most one-shot tasks.
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ If a skill is missing from this list but present in the repo, the catalog is reg
|
||||||
| [`linear`](/docs/user-guide/skills/bundled/productivity/productivity-linear) | Linear: manage issues, projects, teams via GraphQL + curl. | `productivity/linear` |
|
| [`linear`](/docs/user-guide/skills/bundled/productivity/productivity-linear) | Linear: manage issues, projects, teams via GraphQL + curl. | `productivity/linear` |
|
||||||
| [`maps`](/docs/user-guide/skills/bundled/productivity/productivity-maps) | Geocode, POIs, routes, timezones via OpenStreetMap/OSRM. | `productivity/maps` |
|
| [`maps`](/docs/user-guide/skills/bundled/productivity/productivity-maps) | Geocode, POIs, routes, timezones via OpenStreetMap/OSRM. | `productivity/maps` |
|
||||||
| [`nano-pdf`](/docs/user-guide/skills/bundled/productivity/productivity-nano-pdf) | Edit PDF text/typos/titles via nano-pdf CLI (NL prompts). | `productivity/nano-pdf` |
|
| [`nano-pdf`](/docs/user-guide/skills/bundled/productivity/productivity-nano-pdf) | Edit PDF text/typos/titles via nano-pdf CLI (NL prompts). | `productivity/nano-pdf` |
|
||||||
| [`notion`](/docs/user-guide/skills/bundled/productivity/productivity-notion) | Notion API via curl: pages, databases, blocks, search. | `productivity/notion` |
|
| [`notion`](/docs/user-guide/skills/bundled/productivity/productivity-notion) | Notion API + ntn CLI: pages, databases, markdown, Workers. | `productivity/notion` |
|
||||||
| [`ocr-and-documents`](/docs/user-guide/skills/bundled/productivity/productivity-ocr-and-documents) | Extract text from PDFs/scans (pymupdf, marker-pdf). | `productivity/ocr-and-documents` |
|
| [`ocr-and-documents`](/docs/user-guide/skills/bundled/productivity/productivity-ocr-and-documents) | Extract text from PDFs/scans (pymupdf, marker-pdf). | `productivity/ocr-and-documents` |
|
||||||
| [`powerpoint`](/docs/user-guide/skills/bundled/productivity/productivity-powerpoint) | Create, read, edit .pptx decks, slides, notes, templates. | `productivity/powerpoint` |
|
| [`powerpoint`](/docs/user-guide/skills/bundled/productivity/productivity-powerpoint) | Create, read, edit .pptx decks, slides, notes, templates. | `productivity/powerpoint` |
|
||||||
| [`teams-meeting-pipeline`](/docs/user-guide/skills/bundled/productivity/productivity-teams-meeting-pipeline) | Operate the Teams meeting summary pipeline via Hermes CLI — summarize meetings, inspect pipeline status, replay jobs, manage Microsoft Graph subscriptions. | `productivity/teams-meeting-pipeline` |
|
| [`teams-meeting-pipeline`](/docs/user-guide/skills/bundled/productivity/productivity-teams-meeting-pipeline) | Operate the Teams meeting summary pipeline via Hermes CLI — summarize meetings, inspect pipeline status, replay jobs, manage Microsoft Graph subscriptions. | `productivity/teams-meeting-pipeline` |
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
---
|
---
|
||||||
title: "Notion — Notion API via curl: pages, databases, blocks, search"
|
title: "Notion — Notion API + ntn CLI: pages, databases, markdown, Workers"
|
||||||
sidebar_label: "Notion"
|
sidebar_label: "Notion"
|
||||||
description: "Notion API via curl: pages, databases, blocks, search"
|
description: "Notion API + ntn CLI: pages, databases, markdown, Workers"
|
||||||
---
|
---
|
||||||
|
|
||||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||||
|
|
||||||
# Notion
|
# Notion
|
||||||
|
|
||||||
Notion API via curl: pages, databases, blocks, search.
|
Notion API + ntn CLI: pages, databases, markdown, Workers.
|
||||||
|
|
||||||
## Skill metadata
|
## Skill metadata
|
||||||
|
|
||||||
|
|
@ -16,11 +16,11 @@ Notion API via curl: pages, databases, blocks, search.
|
||||||
|---|---|
|
|---|---|
|
||||||
| Source | Bundled (installed by default) |
|
| Source | Bundled (installed by default) |
|
||||||
| Path | `skills/productivity/notion` |
|
| Path | `skills/productivity/notion` |
|
||||||
| Version | `1.0.0` |
|
| Version | `2.0.0` |
|
||||||
| Author | community |
|
| Author | community |
|
||||||
| License | MIT |
|
| License | MIT |
|
||||||
| Platforms | linux, macos, windows |
|
| Platforms | linux, macos, windows |
|
||||||
| Tags | `Notion`, `Productivity`, `Notes`, `Database`, `API` |
|
| Tags | `Notion`, `Productivity`, `Notes`, `Database`, `API`, `CLI`, `Workers` |
|
||||||
|
|
||||||
## Reference: full SKILL.md
|
## Reference: full SKILL.md
|
||||||
|
|
||||||
|
|
@ -28,23 +28,146 @@ Notion API via curl: pages, databases, blocks, search.
|
||||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
# Notion API
|
# Notion
|
||||||
|
|
||||||
Use the Notion API via curl to create, read, update pages, databases (data sources), and blocks. No extra tools needed — just curl and a Notion API key.
|
Talk to Notion two ways. Same integration token works for both — pick by what's available.
|
||||||
|
|
||||||
## Prerequisites
|
◆ **`ntn` CLI** — Notion's official CLI. Shorter syntax, one-line file uploads, required for Workers. macOS + Linux only as of May 2026 (Windows support "coming soon"). **Default when installed.**
|
||||||
|
◆ **HTTP + curl** — works everywhere including Windows. **Default fallback** when `ntn` isn't installed.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### 1. Get an integration token (required for both paths)
|
||||||
|
|
||||||
1. Create an integration at https://notion.so/my-integrations
|
1. Create an integration at https://notion.so/my-integrations
|
||||||
2. Copy the API key (starts with `ntn_` or `secret_`)
|
2. Copy the API key (starts with `ntn_` or `secret_`)
|
||||||
3. Store it in `~/.hermes/.env`:
|
3. Store in `~/.hermes/.env`:
|
||||||
```
|
```
|
||||||
NOTION_API_KEY=ntn_your_key_here
|
NOTION_API_KEY=ntn_your_key_here
|
||||||
```
|
```
|
||||||
4. **Important:** Share target pages/databases with your integration in Notion (click "..." → "Connect to" → your integration name)
|
4. **Share target pages/databases with the integration** in Notion: page menu `...` → `Connect to` → your integration name. Without this, the API returns 404 for that page even though it exists.
|
||||||
|
|
||||||
|
### 2. Install `ntn` (preferred path on macOS / Linux)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Recommended
|
||||||
|
curl -fsSL https://ntn.dev | bash
|
||||||
|
|
||||||
|
# Or via npm (needs Node 22+, npm 10+)
|
||||||
|
npm install --global ntn
|
||||||
|
|
||||||
|
ntn --version # verify
|
||||||
|
```
|
||||||
|
|
||||||
|
**Skip `ntn login` — use the integration token instead.** This works headlessly, no browser needed:
|
||||||
|
```bash
|
||||||
|
export NOTION_API_TOKEN=$NOTION_API_KEY # ntn reads NOTION_API_TOKEN
|
||||||
|
export NOTION_KEYRING=0 # don't try to use the OS keychain
|
||||||
|
```
|
||||||
|
|
||||||
|
Add those exports to your shell profile (or to `~/.hermes/.env`) so every session inherits them.
|
||||||
|
|
||||||
|
### 3. Choose path at runtime
|
||||||
|
|
||||||
|
```bash
|
||||||
|
if command -v ntn >/dev/null 2>&1; then
|
||||||
|
# use ntn
|
||||||
|
else
|
||||||
|
# fall back to curl
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows users: skip step 2 entirely until native `ntn` ships — Path B works fine. If you want CLI ergonomics now, install `ntn` inside WSL2.
|
||||||
|
|
||||||
## API Basics
|
## API Basics
|
||||||
|
|
||||||
All requests use this pattern:
|
`Notion-Version: 2025-09-03` is required on all HTTP requests. `ntn` handles this for you. In this version, what users call "databases" are called **data sources** in the API.
|
||||||
|
|
||||||
|
## Path A — `ntn` CLI (preferred, macOS / Linux)
|
||||||
|
|
||||||
|
### Raw API calls (shorthand for curl)
|
||||||
|
```bash
|
||||||
|
ntn api v1/users # GET
|
||||||
|
ntn api v1/pages parent[page_id]=abc123 \ # POST with inline body
|
||||||
|
properties[title][0][text][content]="Notes"
|
||||||
|
ntn api v1/pages/abc123 -X PATCH archived:=true # PATCH; := is non-string (bool/num/null)
|
||||||
|
```
|
||||||
|
|
||||||
|
Syntax notes:
|
||||||
|
- `key=value` — string fields
|
||||||
|
- `key[nested]=value` — nested object fields
|
||||||
|
- `key:=value` — typed assignment (booleans, numbers, null, arrays)
|
||||||
|
|
||||||
|
### Search
|
||||||
|
```bash
|
||||||
|
ntn api v1/search query="page title"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page metadata
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages/{page_id}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page as Markdown (agent-friendly)
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages/{page_id}/markdown
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page content as blocks
|
||||||
|
```bash
|
||||||
|
ntn api v1/blocks/{page_id}/children
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create page from Markdown
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages \
|
||||||
|
parent[page_id]=xxx \
|
||||||
|
properties[title][0][text][content]="Notes from meeting" \
|
||||||
|
markdown="# Agenda
|
||||||
|
|
||||||
|
- Q3 roadmap
|
||||||
|
- Hiring"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Patch a page with Markdown
|
||||||
|
```bash
|
||||||
|
ntn api v1/pages/{page_id}/markdown -X PATCH \
|
||||||
|
markdown="## Update
|
||||||
|
|
||||||
|
Shipped the prototype."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Query a database (data source)
|
||||||
|
```bash
|
||||||
|
ntn api v1/data_sources/{data_source_id}/query -X POST \
|
||||||
|
filter[property]=Status filter[select][equals]=Active
|
||||||
|
```
|
||||||
|
|
||||||
|
For complex queries with `sorts`, multiple filter clauses, or compound logic, pipe JSON in:
|
||||||
|
```bash
|
||||||
|
echo '{"filter": {"property": "Status", "select": {"equals": "Active"}}, "sorts": [{"property": "Date", "direction": "descending"}]}' | \
|
||||||
|
ntn api v1/data_sources/{data_source_id}/query -X POST --json -
|
||||||
|
```
|
||||||
|
|
||||||
|
### File uploads (one-liner — biggest CLI win)
|
||||||
|
```bash
|
||||||
|
ntn files create < photo.png
|
||||||
|
ntn files create --external-url https://example.com/photo.png
|
||||||
|
ntn files list
|
||||||
|
```
|
||||||
|
|
||||||
|
Compare to the 3-step HTTP flow (create upload → PUT bytes → reference).
|
||||||
|
|
||||||
|
### Useful env vars
|
||||||
|
| Var | Effect |
|
||||||
|
|---|---|
|
||||||
|
| `NOTION_API_TOKEN` | Auth token (overrides keychain) — set this to your integration token |
|
||||||
|
| `NOTION_KEYRING=0` | File-based creds at `~/.config/notion/auth.json` instead of OS keychain |
|
||||||
|
| `NOTION_WORKSPACE_ID` | Skip the workspace picker prompt |
|
||||||
|
|
||||||
|
## Path B — HTTP + curl (cross-platform, default on Windows)
|
||||||
|
|
||||||
|
All requests share this pattern:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X GET "https://api.notion.com/v1/..." \
|
curl -s -X GET "https://api.notion.com/v1/..." \
|
||||||
|
|
@ -53,12 +176,9 @@ curl -s -X GET "https://api.notion.com/v1/..." \
|
||||||
-H "Content-Type: application/json"
|
-H "Content-Type: application/json"
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Notion-Version` header is required. This skill uses `2025-09-03` (latest). In this version, databases are called "data sources" in the API.
|
On Windows the `curl` shipped with Windows 10+ works as-is. PowerShell users can also use `Invoke-RestMethod`.
|
||||||
|
|
||||||
## Common Operations
|
|
||||||
|
|
||||||
### Search
|
### Search
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/search" \
|
curl -s -X POST "https://api.notion.com/v1/search" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -67,24 +187,56 @@ curl -s -X POST "https://api.notion.com/v1/search" \
|
||||||
-d '{"query": "page title"}'
|
-d '{"query": "page title"}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Get Page
|
### Read page metadata
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s "https://api.notion.com/v1/pages/{page_id}" \
|
curl -s "https://api.notion.com/v1/pages/{page_id}" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
-H "Notion-Version: 2025-09-03"
|
-H "Notion-Version: 2025-09-03"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Get Page Content (blocks)
|
### Read page as Markdown (agent-friendly)
|
||||||
|
|
||||||
|
Easier to feed to a model than block JSON.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s "https://api.notion.com/v1/pages/{page_id}/markdown" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read page content as blocks (when you need structure)
|
||||||
```bash
|
```bash
|
||||||
curl -s "https://api.notion.com/v1/blocks/{page_id}/children" \
|
curl -s "https://api.notion.com/v1/blocks/{page_id}/children" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
-H "Notion-Version: 2025-09-03"
|
-H "Notion-Version: 2025-09-03"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create Page in a Database
|
### Create page from Markdown
|
||||||
|
|
||||||
|
`POST /v1/pages` accepts a `markdown` body param.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST "https://api.notion.com/v1/pages" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"parent": {"page_id": "xxx"},
|
||||||
|
"properties": {"title": [{"text": {"content": "Notes from meeting"}}]},
|
||||||
|
"markdown": "# Agenda\n\n- Q3 roadmap\n- Hiring\n\n## Decisions\n- Ship MVP Friday"
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Patch a page with Markdown
|
||||||
|
```bash
|
||||||
|
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}/markdown" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"markdown": "## Update\n\nShipped the prototype."}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create page in a database (typed properties)
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/pages" \
|
curl -s -X POST "https://api.notion.com/v1/pages" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -99,8 +251,7 @@ curl -s -X POST "https://api.notion.com/v1/pages" \
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Query a Database
|
### Query a database (data source)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \
|
curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -112,8 +263,7 @@ curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query"
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create a Database
|
### Create a database
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X POST "https://api.notion.com/v1/data_sources" \
|
curl -s -X POST "https://api.notion.com/v1/data_sources" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -130,8 +280,7 @@ curl -s -X POST "https://api.notion.com/v1/data_sources" \
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Update Page Properties
|
### Update page properties
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
|
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -140,8 +289,7 @@ curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
|
||||||
-d '{"properties": {"Status": {"select": {"name": "Done"}}}}'
|
-d '{"properties": {"Status": {"select": {"name": "Done"}}}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Add Content to a Page
|
### Append blocks to a page
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
|
curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
|
||||||
-H "Authorization: Bearer $NOTION_API_KEY" \
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
|
@ -154,6 +302,21 @@ curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### File uploads (3-step flow)
|
||||||
|
```bash
|
||||||
|
# 1. Create upload
|
||||||
|
curl -s -X POST "https://api.notion.com/v1/file_uploads" \
|
||||||
|
-H "Authorization: Bearer $NOTION_API_KEY" \
|
||||||
|
-H "Notion-Version: 2025-09-03" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"filename": "photo.png", "content_type": "image/png"}'
|
||||||
|
|
||||||
|
# 2. PUT bytes to the upload_url returned above
|
||||||
|
curl -s -X PUT "{upload_url}" --data-binary @photo.png
|
||||||
|
|
||||||
|
# 3. Reference {file_upload_id} in a page/block payload
|
||||||
|
```
|
||||||
|
|
||||||
## Property Types
|
## Property Types
|
||||||
|
|
||||||
Common property formats for database items:
|
Common property formats for database items:
|
||||||
|
|
@ -169,19 +332,132 @@ Common property formats for database items:
|
||||||
- **Email:** `{"email": "user@example.com"}`
|
- **Email:** `{"email": "user@example.com"}`
|
||||||
- **Relation:** `{"relation": [{"id": "page_id"}]}`
|
- **Relation:** `{"relation": [{"id": "page_id"}]}`
|
||||||
|
|
||||||
## Key Differences in API Version 2025-09-03
|
## API Version 2025-09-03 — Databases vs Data Sources
|
||||||
|
|
||||||
- **Databases → Data Sources:** Use `/data_sources/` endpoints for queries and retrieval
|
- **Databases became data sources.** Use `/data_sources/` endpoints for queries and retrieval.
|
||||||
- **Two IDs:** Each database has both a `database_id` and a `data_source_id`
|
- **Two IDs per database:** `database_id` and `data_source_id`.
|
||||||
- Use `database_id` when creating pages (`parent: {"database_id": "..."}`)
|
- `database_id` when creating pages: `parent: {"database_id": "..."}`
|
||||||
- Use `data_source_id` when querying (`POST /v1/data_sources/{id}/query`)
|
- `data_source_id` when querying: `POST /v1/data_sources/{id}/query`
|
||||||
- **Search results:** Databases return as `"object": "data_source"` with their `data_source_id`
|
- Search returns databases as `"object": "data_source"` with the `data_source_id` field.
|
||||||
|
|
||||||
|
## Notion Workers (advanced, requires `ntn`)
|
||||||
|
|
||||||
|
Workers are TypeScript programs Notion hosts for you. One worker can expose any combination of:
|
||||||
|
- **Syncs** — pull data from external APIs into a Notion database on a schedule (default 30 min).
|
||||||
|
- **Tools** — appear as callable tools inside Notion's Custom Agents.
|
||||||
|
- **Webhooks** — receive HTTP events from external services (GitHub, Stripe, etc.) and act in Notion.
|
||||||
|
|
||||||
|
**Plan / platform gating:**
|
||||||
|
- CLI works on all plans. **Deploying Workers requires Business or Enterprise.**
|
||||||
|
- `ntn` is macOS/Linux only as of May 2026. Windows users need WSL2 or to wait for native support.
|
||||||
|
- Free through August 11, 2026; metered on Notion credits after.
|
||||||
|
|
||||||
|
### Minimal Worker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ntn workers new my-worker # scaffold
|
||||||
|
cd my-worker
|
||||||
|
# Edit src/index.ts
|
||||||
|
ntn workers deploy --name my-worker
|
||||||
|
```
|
||||||
|
|
||||||
|
`src/index.ts`:
|
||||||
|
```typescript
|
||||||
|
import { Worker } from "@notionhq/workers";
|
||||||
|
|
||||||
|
const worker = new Worker();
|
||||||
|
export default worker;
|
||||||
|
|
||||||
|
worker.tool("greet", {
|
||||||
|
title: "Greet a User",
|
||||||
|
description: "Returns a friendly greeting",
|
||||||
|
inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] },
|
||||||
|
execute: async ({ name }) => `Hello, ${name}!`,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Webhook capability
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
worker.webhook("onGithubPush", {
|
||||||
|
title: "GitHub Push Handler",
|
||||||
|
execute: async (events, { notion }) => {
|
||||||
|
for (const event of events) {
|
||||||
|
// event.body, event.rawBody (for signature verification), event.headers
|
||||||
|
console.log("got delivery", event.deliveryId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
After deploy: `ntn workers webhooks list` shows the URL Notion generates. Treat that URL as a secret — anyone with it can POST events unless you add signature verification.
|
||||||
|
|
||||||
|
### Worker lifecycle commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ntn workers deploy
|
||||||
|
ntn workers list
|
||||||
|
ntn workers exec <capability-key> -d '{"name": "world"}'
|
||||||
|
ntn workers sync trigger <key> # run a sync now
|
||||||
|
ntn workers sync pause <key>
|
||||||
|
ntn workers env set GITHUB_WEBHOOK_SECRET=...
|
||||||
|
ntn workers runs list # recent invocations
|
||||||
|
ntn workers runs logs <run-id>
|
||||||
|
ntn workers webhooks list
|
||||||
|
```
|
||||||
|
|
||||||
|
When asked to build a Worker, scaffold with `ntn workers new`, write the code in `src/index.ts`, set any secrets with `ntn workers env set`, and deploy. Notion's docs at https://developers.notion.com/workers cover the full API surface.
|
||||||
|
|
||||||
|
## Notion-Flavored Markdown (used by `/markdown` endpoints)
|
||||||
|
|
||||||
|
Standard CommonMark plus XML-like tags for Notion-specific blocks. Use **tabs** for indentation.
|
||||||
|
|
||||||
|
**Blocks beyond CommonMark:**
|
||||||
|
```
|
||||||
|
<callout icon="🎯" color="blue_bg">
|
||||||
|
Ship the MVP by **Friday**.
|
||||||
|
</callout>
|
||||||
|
|
||||||
|
<details color="gray">
|
||||||
|
<summary>Toggle title</summary>
|
||||||
|
Children indented one tab
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<columns>
|
||||||
|
<column>Left side</column>
|
||||||
|
<column>Right side</column>
|
||||||
|
</columns>
|
||||||
|
|
||||||
|
<table_of_contents color="gray"/>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Inline:**
|
||||||
|
- Mentions: `<mention-user url="..."/>`, `<mention-page url="...">Title</mention-page>`, `<mention-date start="2026-05-15"/>`
|
||||||
|
- Underline: `<span underline="true">text</span>`
|
||||||
|
- Color: `<span color="blue">text</span>` or block-level `{color="blue"}` on the first line
|
||||||
|
- Math: inline `$x^2$`, block `$$ ... $$`
|
||||||
|
- Citations: `[^https://example.com]`
|
||||||
|
|
||||||
|
**Colors:** `gray brown orange yellow green blue purple pink red`, plus `*_bg` variants for backgrounds.
|
||||||
|
|
||||||
|
Headings 5/6 collapse to H4. Multiple `>` lines render as separate quote blocks — use `<br>` inside a single `>` for multi-line quotes.
|
||||||
|
|
||||||
|
## Choosing the Right Path
|
||||||
|
|
||||||
|
| Task | mac / Linux | Windows |
|
||||||
|
|---|---|---|
|
||||||
|
| Read/write pages, search, query databases | `ntn api ...` | curl |
|
||||||
|
| Read a page for an agent to summarize | `ntn api v1/pages/{id}/markdown` | curl `/markdown` endpoint |
|
||||||
|
| Upload a file | `ntn files create < file` | 3-step HTTP flow |
|
||||||
|
| One-off API exploration | `ntn api ...` | curl |
|
||||||
|
| Build a sync / webhook / agent tool hosted by Notion | `ntn workers ...` | WSL2 + `ntn workers ...` |
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- Page/database IDs are UUIDs (with or without dashes)
|
- Page/database IDs are UUIDs (with or without dashes — both accepted).
|
||||||
- Rate limit: ~3 requests/second average
|
- Rate limit: ~3 requests/second average. The CLI doesn't bypass this.
|
||||||
- The API cannot set database view filters — that's UI-only
|
- The API cannot set database **view** filters — that's UI-only.
|
||||||
- Use `is_inline: true` when creating data sources to embed them in pages
|
- Use `"is_inline": true` when creating data sources to embed them in a page.
|
||||||
- Add `-s` flag to curl to suppress progress bars (cleaner output for Hermes)
|
- Always pass `-s` to curl to suppress progress bars (cleaner agent output).
|
||||||
- Pipe output through `jq` for readable JSON: `... | jq '.results[0].properties'`
|
- Pipe JSON through `jq` when reading: `... | jq '.results[0].properties'`.
|
||||||
|
- Notion also ships an MCP server now (`Notion MCP`, ~91% more token-efficient on DB ops than the previous version) — wire it via Hermes' MCP support if you want streaming Notion access from inside a session, but the paths above are enough for most one-shot tasks.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue