---
name: "Notion"
description: Read and write Notion pages, databases, blocks, and files through the official `ntn` CLI.
version: 2
situations: notion, wiki, docs, database, notes
requires-secrets:
requires-packages:
requires-connector: notion
---

# Notion (`ntn`)

Runs through Notion's official CLI in your **bash** tool. The operator connected the workspace from
00's skill store, so the token is in the OS keychain — you never handle it.

## First, know what you can see

```
ntn doctor
```

That inspects the session. If it reports no login, tell the operator to open **Skill store → Notion →
Connect**.

## The thing that trips everyone up

The operator chose **which pages and databases** to share while authorizing. Anything they didn't
select is invisible to this CLI. If a search comes back empty, the connection is probably fine and the
page simply wasn't shared — say that, rather than concluding the content doesn't exist. The fix is for
the operator to re-run Connect and select it.

## Read

`ntn api` is authenticated `curl` for the Notion API — same endpoints, no token handling:

```
ntn api v1/users/me
ntn api v1/search --method POST --data '{"query":"roadmap","page_size":20}'
ntn api v1/databases/DB_ID
ntn api v1/databases/DB_ID/query --method POST --data '{"filter":{"property":"Status","status":{"equals":"In progress"}},"page_size":50}'
ntn api v1/pages/PAGE_ID
ntn api "v1/blocks/PAGE_ID/children?page_size=100"
```

Page content is a *block tree*: `blocks/:id/children` returns one level, and any block with
`has_children: true` needs its own call. Don't report a page as empty after reading only the top level.

## Write

```
# New page in a database
ntn api v1/pages --method POST --data '{"parent":{"database_id":"DB_ID"},"properties":{"Name":{"title":[{"text":{"content":"…"}}]}}}'

# Append content
ntn api v1/blocks/PAGE_ID/children --method PATCH --data '{"children":[{"paragraph":{"rich_text":[{"text":{"content":"…"}}]}}]}'

# Upload a file
ntn files create ./diagram.png
```

Property names and types must match the database exactly — read the schema
(`ntn api v1/databases/DB_ID`) before writing into it. Put long JSON in a file and pass `--data @body.json`.

## Never without being asked in this turn

Archiving pages (`"archived": true` is Notion's delete), overwriting an existing page's blocks,
deploying Notion Workers (`ntn workers deploy`), or editing a page in a shared team space that the
operator didn't name.
