Notion

Notion page and database CRUD via API — create, read, update, and query Notion pages, data sources (databases), and blocks directly from CLI-JAW using the Notion API.

Default Active: Yes Category: Productivity Requires: NOTION_API_KEY

Quick Reference

Skill namenotion
StatusActive (auto-injected into every session)
CategoryProductivity
SKILL.md path~/.cli-jaw/skills/notion/SKILL.md
Homepagedevelopers.notion.com
API version2025-09-03 (latest)
RequiresNOTION_API_KEY environment variable (key with ntn_ prefix)
Key location~/.config/notion/api_key
OAuth config~/.config/notion/oauth.env
Rate limit~3 requests/sec (use time.sleep(0.35) for batch operations)
InstallPre-installed (ships with CLI-JAW)

Overview

The notion skill provides full CRUD access to Notion workspaces through the Notion API. It enables CLI-JAW to search for pages, create and update content, query databases (data sources), manage blocks, and apply visual design patterns — all without leaving the terminal.

Key capabilities:

Setup

Before using the Notion skill, you need an API integration key and the correct permissions.

StepAction
1. Create integrationGo to notion.so/my-integrations and create a new internal integration
2. Copy the API keyThe key starts with ntn_
3. Store the keySave to ~/.config/notion/api_key
4. Share pagesIn Notion, share each target page/database with your integration
# Store your API key
mkdir -p ~/.config/notion
echo "ntn_your_api_key_here" > ~/.config/notion/api_key
chmod 600 ~/.config/notion/api_key
Important: Target pages and databases must be explicitly shared with your integration in Notion. Unshared pages will return 404 errors even if the API key is valid.

API Helper Function

The skill defines a reusable shell helper that all operations are built on. CLI-JAW uses this internally when executing Notion commands:

NOTION_KEY=$(cat ~/.config/notion/api_key)

# Helper function used by all API calls
notion_api() {
  local method=$1 endpoint=$2 data=$3
  curl -s -X "$method" "https://api.notion.com/v1$endpoint" \
    -H "Authorization: Bearer $NOTION_KEY" \
    -H "Notion-Version: 2025-09-03" \
    -H "Content-Type: application/json" \
    ${data:+-d "$data"}
}

Common Operations

Search

Find pages and data sources by title. Returns matching objects with their IDs.

# Search for pages by title
notion_api POST /search '{"query": "page title"}'

# Discover workspace page IDs
notion_api POST /search '{"query": "Meeting Notes"}'

Read Pages and Blocks

Retrieve page properties and their block-level content.

# Get page properties
notion_api GET /pages/{page_id}

# Get page content (all child blocks)
notion_api GET /blocks/{page_id}/children

Create Pages

Create a new page inside a data source (database) with properties, or as a child of an existing page.

# Create a page in a data source
notion_api POST /pages '{
  "parent": {"database_id": "xxx"},
  "properties": {
    "Name": {"title": [{"text": {"content": "New Item"}}]},
    "Status": {"select": {"name": "Todo"}}
  }
}'

Update Pages

Modify page properties without affecting the page content (blocks).

# Update a status property
notion_api PATCH /pages/{page_id} \
  '{"properties": {"Status": {"select": {"name": "Done"}}}}'

Append Blocks

Add new content blocks to an existing page.

# Add a paragraph block
notion_api PATCH /blocks/{page_id}/children '{
  "children": [
    {
      "object": "block",
      "type": "paragraph",
      "paragraph": {
        "rich_text": [{"text": {"content": "Hello, world!"}}]
      }
    }
  ]
}'

Query Data Sources

Filter and sort database entries with structured queries.

# Query with filter and sort
notion_api POST /data_sources/{data_source_id}/query '{
  "filter": {
    "property": "Status",
    "select": {"equals": "Active"}
  },
  "sorts": [
    {"property": "Date", "direction": "descending"}
  ]
}'

Create Data Sources

Create a new database (data source) with a defined schema.

# Create a new data source with properties
notion_api POST /data_sources '{
  "parent": {"page_id": "xxx"},
  "title": [{"text": {"content": "My Database"}}],
  "properties": {
    "Name": {"title": {}},
    "Status": {"select": {"options": [{"name": "Todo"}, {"name": "Done"}]}},
    "Date": {"date": {}}
  }
}'

Property Types Reference

Each property type has a specific JSON structure. Use the correct format when creating or updating page properties.

Title

{"title": [{"text": {"content": "..."}}]}

Rich Text

{"rich_text": [{"text": {"content": "..."}}]}

Select

{"select": {"name": "Option"}}

Multi-select

{"multi_select": [{"name": "A"}, {"name": "B"}]}

Date

{"date": {"start": "2024-01-15", "end": "2024-01-16"}}

Checkbox

{"checkbox": true}

Number

{"number": 42}

URL

{"url": "https://..."}

Email

{"email": "user@example.com"}

Relation

{"relation": [{"id": "page_id"}]}

2025-09-03 API Changes

The latest Notion API version introduces significant changes to how databases are handled. The skill is built on this version.

Renamed Databases → Data Sources: Use /data_sources/ endpoints for queries. The term "database" is replaced by "data source" in the API.
New Two IDs per database: database_id is used for creating pages inside a database, while data_source_id is used for querying. Both are present in API responses.
Changed Search results: Databases now return as "object": "data_source" instead of "object": "database".
Changed Page responses: Include both parent.data_source_id and parent.database_id when the parent is a database.
Dual ID pattern: When working with databases, use database_id for POST /pages (creating entries) and data_source_id for POST /data_sources/{id}/query (querying entries). Mixing them up will cause 404 errors.

Visual Design Rules

The skill includes a set of visual design rules (referred to as the "aesthetics guide") that ensure Notion pages created by CLI-JAW look polished and follow Notion-native patterns.

1. Use mention links for page references

Mention links create automatic backlinks and display the referenced page's icon. Always prefer mentions over plain-text page names.

// Correct: mention link (creates backlink, shows icon)
{"type": "mention", "mention": {"type": "page", "page": {"id": "page-UUID"}}}

// Incorrect: plain text (no backlink, no icon)
{"type": "text", "text": {"content": "Page Name"}}

2. Skip emoji in text when using mentions

Mentions automatically display the page's icon. Adding emoji text alongside a mention creates visual duplication. Let the mention handle the icon.

3. Use callout + mention for navigation hubs

For pages that serve as hubs or dashboards, use a callout block with mention links separated by a dot separator for clean navigation.

{"object": "block", "type": "callout", "callout": {
    "rich_text": [
        {"type": "mention", "mention": {"type": "page", "page": {"id": "dashboard-UUID"}}},
        {"type": "text", "text": {"content": " · "}},
        {"type": "mention", "mention": {"type": "page", "page": {"id": "operations-UUID"}}}
    ],
    "icon": {"type": "emoji", "emoji": "🏠"},
    "color": "gray_background"
}}

4. Preserve child_page blocks

Deleting a child_page block permanently archives its subpage. When clearing or rebuilding page content, always filter out child_page blocks before deletion.

# Python: safely clear blocks without archiving subpages
for block in children:
    if block["type"] != "child_page":
        delete_block(block["id"])

5. Standard page structure pattern

Follow this layout for well-structured Notion pages:

callout (intro/slogan) + color_background
divider
heading_2 (section title)
callout (mention links) + gray_background ← navigation
divider
heading_2 (Quick Links)
bulleted_list_item (mention → description)

6. Icons and covers

Set a meaningful emoji icon on every page. For key pages (dashboards, project hubs), add an Unsplash cover image at w=1500 resolution for visual polish.

7. Mention caveats

  • Archived pages render mentions as plain text (no icon, no link)
  • The integration must have access to the target page for mentions to resolve
  • Rate limit: ~3 requests/sec — use time.sleep(0.35) in batch operations to avoid throttling

Environment and Configuration

FilePurpose
~/.config/notion/api_keyPrimary API key storage (also checked as access_token)
~/.config/notion/oauth.envOAuth configuration for public integrations
NOTION_API_KEY env varEnvironment variable override (takes precedence)

To discover workspace page IDs for use in scripts and commands:

# Search by name to find page/database UUIDs
notion_api POST /search '{"query": "page name"}'

Usage Examples (~해줌)

Real-world usage patterns in the natural Korean style that CLI-JAW understands.

"노션에 새 페이지 만들어줌 — 제목 '주간 회의록', 상태는 '진행 중'으로"
Creates a new page in the specified Notion data source with the title set to "weekly meeting notes" and the Status property set to "In Progress". The skill uses POST /pages with the correct property types.
"프로젝트 데이터베이스에서 상태가 'Todo'인 항목들 전부 찾아줌"
Queries a Notion data source using POST /data_sources/{id}/query with a filter on the Status select property equaling "Todo", sorted by date descending. Returns all matching entries.
"이 노션 페이지 내용 읽어와서 요약해줌"
Fetches the page content using GET /blocks/{page_id}/children, reads all block content recursively, and generates a summary. Handles nested blocks like toggles and callouts.
"노션 대시보드 페이지 예쁘게 꾸멀줌 — 네비게이션 허브로"
Applies the visual design rules: creates a callout block with mention links as a navigation hub, adds a divider, sets up heading/section structure, adds an emoji icon, and applies an Unsplash cover image. Follows rule 3 (callout + mention) and rule 5 (page structure pattern).
"노션에 새 데이터베이스 만들어줌 — 이름, 상태(Todo/Done), 날짜 컬럼으로"
Creates a new data source using POST /data_sources with three properties: a title property for Name, a select property with "Todo" and "Done" options for Status, and a date property. Sets the parent to the specified page.

Important Notes

Related