home / skills / openclaw / skills / notion

notion skill

/skills/steipete/notion

This skill helps you manage Notion pages, databases, and blocks via the API, enabling creation, querying, and updates.

npx playbooks add skill openclaw/skills --skill notion

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
4.9 KB
---
name: notion
description: Notion API for creating and managing pages, databases, and blocks.
homepage: https://developers.notion.com
metadata: {"clawdbot":{"emoji":"📝"}}
---

# notion

Use the Notion API to create/read/update pages, data sources (databases), and blocks.

## Setup

1. Create an integration at https://notion.so/my-integrations
2. Copy the API key (starts with `ntn_` or `secret_`)
3. Store it:
```bash
mkdir -p ~/.config/notion
echo "ntn_your_key_here" > ~/.config/notion/api_key
```
4. Share target pages/databases with your integration (click "..." → "Connect to" → your integration name)

## API Basics

All requests need:
```bash
NOTION_KEY=$(cat ~/.config/notion/api_key)
curl -X GET "https://api.notion.com/v1/..." \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json"
```

> **Note:** The `Notion-Version` header is required. This skill uses `2025-09-03` (latest). In this version, databases are called "data sources" in the API.

## Common Operations

**Search for pages and data sources:**
```bash
curl -X POST "https://api.notion.com/v1/search" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \
  -d '{"query": "page title"}'
```

**Get page:**
```bash
curl "https://api.notion.com/v1/pages/{page_id}" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03"
```

**Get page content (blocks):**
```bash
curl "https://api.notion.com/v1/blocks/{page_id}/children" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03"
```

**Create page in a data source:**
```bash
curl -X POST "https://api.notion.com/v1/pages" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \
  -d '{
    "parent": {"database_id": "xxx"},
    "properties": {
      "Name": {"title": [{"text": {"content": "New Item"}}]},
      "Status": {"select": {"name": "Todo"}}
    }
  }'
```

**Query a data source (database):**
```bash
curl -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {"property": "Status", "select": {"equals": "Active"}},
    "sorts": [{"property": "Date", "direction": "descending"}]
  }'
```

**Create a data source (database):**
```bash
curl -X POST "https://api.notion.com/v1/data_sources" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \
  -d '{
    "parent": {"page_id": "xxx"},
    "title": [{"text": {"content": "My Database"}}],
    "properties": {
      "Name": {"title": {}},
      "Status": {"select": {"options": [{"name": "Todo"}, {"name": "Done"}]}},
      "Date": {"date": {}}
    }
  }'
```

**Update page properties:**
```bash
curl -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \
  -d '{"properties": {"Status": {"select": {"name": "Done"}}}}'
```

**Add blocks to page:**
```bash
curl -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
  -H "Authorization: Bearer $NOTION_KEY" \
  -H "Notion-Version: 2025-09-03" \
  -H "Content-Type: application/json" \
  -d '{
    "children": [
      {"object": "block", "type": "paragraph", "paragraph": {"rich_text": [{"text": {"content": "Hello"}}]}}
    ]
  }'
```

## Property Types

Common property formats for database items:
- **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": "[email protected]"}`
- **Relation:** `{"relation": [{"id": "page_id"}]}`

## Key Differences in 2025-09-03

- **Databases → Data Sources:** Use `/data_sources/` endpoints for queries and retrieval
- **Two IDs:** Each database now has both a `database_id` and a `data_source_id`
  - Use `database_id` when creating pages (`parent: {"database_id": "..."}`)
  - Use `data_source_id` when querying (`POST /v1/data_sources/{id}/query`)
- **Search results:** Databases return as `"object": "data_source"` with their `data_source_id`
- **Parent in responses:** Pages show `parent.data_source_id` alongside `parent.database_id`
- **Finding the data_source_id:** Search for the database, or call `GET /v1/data_sources/{data_source_id}`

## Notes

- Page/database IDs are UUIDs (with or without dashes)
- The API cannot set database view filters — that's UI-only
- Rate limit: ~3 requests/second average
- Use `is_inline: true` when creating data sources to embed them in pages

Overview

This skill provides a concise wrapper and reference for the Notion API to create, read, update, and manage pages, data sources (databases), and blocks. It targets the Notion API behavior as of the 2025-09-03 version and documents key differences such as data source endpoints and dual IDs. Use it to automate content creation, query database items, and manipulate page blocks programmatically.

How this skill works

The skill demonstrates authenticated HTTP calls to Notion using an integration API key and the required Notion-Version header. It shows how to search workspaces, retrieve pages and block children, create pages inside a data source, query data sources, create data sources, update page properties, and append blocks. Examples use curl but the same request shapes apply to any HTTP client or SDK that includes the Authorization and Notion-Version headers.

When to use it

  • Automate creation of project or CRM items in Notion databases.
  • Backup or archive Notion pages and block content programmatically.
  • Query and filter database items for reporting or integrations.
  • Bulk-update page properties or add content to many pages.
  • Create embedded data sources inside pages for templated content.

Best practices

  • Store the integration key securely (e.g., ~/.config/notion/api_key) and never hard-code it in source control.
  • Always include the Notion-Version header (2025-09-03) to avoid breaking changes.
  • Share pages or data sources with your integration before trying API calls; missing permissions cause 403 errors.
  • Respect rate limits (~3 requests/second); batch updates where possible and add retry/backoff logic.
  • Use the appropriate ID type: database_id when creating pages and data_source_id when querying data sources.

Example use cases

  • Create a new task in a project data source with title, status, and due date via API.
  • Query a data source to fetch all items where Status equals Active, then generate a weekly report.
  • Add a standard introductory paragraph to a collection of pages by appending paragraph blocks.
  • Create a new data source programmatically as part of a template setup workflow and mark it is_inline to embed it in a page.
  • Update many pages to mark a Status property as Done after a bulk operation completes.

FAQ

How do data_source_id and database_id differ?

A database has two IDs: use database_id when creating pages (parent), and use data_source_id when querying using /v1/data_sources/{id}/query. Search returns data sources with data_source_id in results.

What headers are required for every request?

Include Authorization: Bearer <key>, Notion-Version: 2025-09-03, and Content-Type: application/json for requests with bodies.