$npx -y skills add SafeAI-Lab-X/ClawKeeper --skill notionNotion API for creating and managing pages, databases, and blocks.
| 1 | # notion |
| 2 | |
| 3 | Use the Notion API to create/read/update pages, data sources (databases), and blocks. |
| 4 | |
| 5 | ## Setup |
| 6 | |
| 7 | 1. Create an integration at https://notion.so/my-integrations |
| 8 | 2. Copy the API key (starts with `ntn_` or `secret_`) |
| 9 | 3. Store it: |
| 10 | |
| 11 | ```bash |
| 12 | mkdir -p ~/.config/notion |
| 13 | echo "ntn_your_key_here" > ~/.config/notion/api_key |
| 14 | ``` |
| 15 | |
| 16 | 4. Share target pages/databases with your integration (click "..." → "Connect to" → your integration name) |
| 17 | |
| 18 | ## API Basics |
| 19 | |
| 20 | All requests need: |
| 21 | |
| 22 | ```bash |
| 23 | NOTION_KEY=$(cat ~/.config/notion/api_key) |
| 24 | curl -X GET "https://api.notion.com/v1/..." \ |
| 25 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 26 | -H "Notion-Version: 2025-09-03" \ |
| 27 | -H "Content-Type: application/json" |
| 28 | ``` |
| 29 | |
| 30 | > **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. |
| 31 | |
| 32 | ## Common Operations |
| 33 | |
| 34 | **Search for pages and data sources:** |
| 35 | |
| 36 | ```bash |
| 37 | curl -X POST "https://api.notion.com/v1/search" \ |
| 38 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 39 | -H "Notion-Version: 2025-09-03" \ |
| 40 | -H "Content-Type: application/json" \ |
| 41 | -d '{"query": "page title"}' |
| 42 | ``` |
| 43 | |
| 44 | **Get page:** |
| 45 | |
| 46 | ```bash |
| 47 | curl "https://api.notion.com/v1/pages/{page_id}" \ |
| 48 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 49 | -H "Notion-Version: 2025-09-03" |
| 50 | ``` |
| 51 | |
| 52 | **Get page content (blocks):** |
| 53 | |
| 54 | ```bash |
| 55 | curl "https://api.notion.com/v1/blocks/{page_id}/children" \ |
| 56 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 57 | -H "Notion-Version: 2025-09-03" |
| 58 | ``` |
| 59 | |
| 60 | **Create page in a data source:** |
| 61 | |
| 62 | ```bash |
| 63 | curl -X POST "https://api.notion.com/v1/pages" \ |
| 64 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 65 | -H "Notion-Version: 2025-09-03" \ |
| 66 | -H "Content-Type: application/json" \ |
| 67 | -d '{ |
| 68 | "parent": {"database_id": "xxx"}, |
| 69 | "properties": { |
| 70 | "Name": {"title": [{"text": {"content": "New Item"}}]}, |
| 71 | "Status": {"select": {"name": "Todo"}} |
| 72 | } |
| 73 | }' |
| 74 | ``` |
| 75 | |
| 76 | **Query a data source (database):** |
| 77 | |
| 78 | ```bash |
| 79 | curl -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \ |
| 80 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 81 | -H "Notion-Version: 2025-09-03" \ |
| 82 | -H "Content-Type: application/json" \ |
| 83 | -d '{ |
| 84 | "filter": {"property": "Status", "select": {"equals": "Active"}}, |
| 85 | "sorts": [{"property": "Date", "direction": "descending"}] |
| 86 | }' |
| 87 | ``` |
| 88 | |
| 89 | **Create a data source (database):** |
| 90 | |
| 91 | ```bash |
| 92 | curl -X POST "https://api.notion.com/v1/data_sources" \ |
| 93 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 94 | -H "Notion-Version: 2025-09-03" \ |
| 95 | -H "Content-Type: application/json" \ |
| 96 | -d '{ |
| 97 | "parent": {"page_id": "xxx"}, |
| 98 | "title": [{"text": {"content": "My Database"}}], |
| 99 | "properties": { |
| 100 | "Name": {"title": {}}, |
| 101 | "Status": {"select": {"options": [{"name": "Todo"}, {"name": "Done"}]}}, |
| 102 | "Date": {"date": {}} |
| 103 | } |
| 104 | }' |
| 105 | ``` |
| 106 | |
| 107 | **Update page properties:** |
| 108 | |
| 109 | ```bash |
| 110 | curl -X PATCH "https://api.notion.com/v1/pages/{page_id}" \ |
| 111 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 112 | -H "Notion-Version: 2025-09-03" \ |
| 113 | -H "Content-Type: application/json" \ |
| 114 | -d '{"properties": {"Status": {"select": {"name": "Done"}}}}' |
| 115 | ``` |
| 116 | |
| 117 | **Add blocks to page:** |
| 118 | |
| 119 | ```bash |
| 120 | curl -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \ |
| 121 | -H "Authorization: Bearer $NOTION_KEY" \ |
| 122 | -H "Notion-Version: 2025-09-03" \ |
| 123 | -H "Content-Type: application/json" \ |
| 124 | -d '{ |
| 125 | "children": [ |
| 126 | {"object": "block", "type": "paragraph", "paragraph": {"rich_text": [{"text": {"content": "Hello"}}]}} |
| 127 | ] |
| 128 | }' |
| 129 | ``` |
| 130 | |
| 131 | ## Property Types |
| 132 | |
| 133 | Common property formats for database items: |
| 134 | |
| 135 | - **Title:** `{"title": [{"text": {"content": "..."}}]}` |
| 136 | - **Rich text:** `{"rich_text": [{"text": {"content": "..."}}]}` |
| 137 | - **Select:** `{"select": {"name": "Option"}}` |
| 138 | - **Multi-select:** `{"multi_select": [{"name": "A"}, {"name": "B"}]}` |
| 139 | - **Date:** `{"date": {"start": "2024-01-15", "end": "2024-01-16"}}` |
| 140 | - **Checkbox:** `{"checkbox": true}` |
| 141 | - **Number:** `{"number": 42}` |
| 142 | - **URL:** `{"url": "https://..."}` |
| 143 | - **Email:** `{"email": "a@b.com"}` |
| 144 | - **Relation:** `{"relation": [{"id": "page_id"}]}` |
| 145 | |
| 146 | ## Key Differences in 2025-09-03 |
| 147 | |
| 148 | - **Databases → Data Sources:** Use `/data_sources/` endpoints for queries and retrieval |
| 149 | - **Two IDs:** Each database now has both a `database_id` and a `data_source_id` |
| 150 | - Use `database_id` when creating pages (`parent: {"database_id": "..."}`) |
| 151 | - Use `data_source_id` when querying (`POST /v1/data_sources/{id}/query`) |
| 152 | - **Search results:** Databases return as `"object": "data_source"` with their `data_source_id` |
| 153 | - **Parent in responses:** Pages show `parent.data_source_id` alongside `parent.database_id` |
| 154 | - **Finding the data_source_id:** Search for the database, or call `GET /v1/data_sources/{data_source_id}` |
| 155 | |
| 156 | ## Notes |
| 157 | |
| 158 | - Page/database IDs are UUIDs (with or without dashes) |
| 159 | - The API cannot set database view fil |