Notion API for managing pages, databases, and blocks. Use this skill to create pages, query databases, search content, and build integrations with Notion workspaces.
Install
npx skillscat add vm0-ai/vm0-skills/notion Install via the SkillsCat registry.
This skill provides an interface to the Notion API for managing pages, databases, and content blocks. It enables agents to automate workspace tasks such as querying database entries, searching content, and updating page properties. Developers should use this skill to build integrations that programmatically interact with Notion workspaces.
Notion API
Manage pages, databases, and content blocks in Notion workspaces.
When to Use
- Create and update Notion pages
- Query and filter database entries
- Search across workspace content
- Append content blocks to pages
- Manage database schemas and properties
Prerequisites
export NOTION_TOKEN=ntn_your-integration-tokenGet API Key
- Go to https://www.notion.so/profile/integrations
- Click "New integration"
- Name your integration and select workspace
- Copy the "Internal Integration Secret" (
ntn_...orsecret_...) - Important: Share pages/databases with the integration via "Add connections" in Notion
Page ID Format
Notion URLs contain page IDs. Extract and normalize them:
URL: https://www.notion.so/My-Page-2b70e96f0134807d8450c8793839c659
Page ID: 2b70e96f0134807d8450c8793839c659 (remove hyphens if present)# Normalize page ID (remove hyphens)
PAGE_ID=$(echo "2b70e96f-0134-807d-8450-c8793839c659" | tr -d '-')Important: When using
$VARin a command that pipes to another command, wrap the command containing$VARinbash -c '...'. Due to a Claude Code bug, environment variables are silently cleared when pipes are used directly.bash -c 'curl -s "https://api.example.com" -H "Authorization: Bearer $API_KEY"'
Core APIs
Read Page with Content
Replace <your-page-id> with your actual Notion page ID:
# Get page metadata
bash -c 'curl -s -X GET "https://api.notion.com/v1/pages/<your-page-id>" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" | jq '"'"'{title: .properties.title.title[0].plain_text, url, last_edited_time}'"'"
# Get page content blocks
bash -c 'curl -s -X GET "https://api.notion.com/v1/blocks/<your-page-id>/children?page_size=100" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" | jq '"'"'.results[] | {type, text: (.[.type].rich_text // [] | map(.plain_text) | join("")), has_children}'"'"Read Nested Blocks (Toggle, etc.)
Blocks with has_children: true contain nested content. Replace <your-block-id> with your actual block ID:
bash -c 'curl -s -X GET "https://api.notion.com/v1/blocks/<your-block-id>/children" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" | jq '"'"'.results[] | {type, text: (.[.type].rich_text // [] | map(.plain_text) | join(""))}'"'"Search Workspace
Write to /tmp/notion_request.json:
{
"query": "Meeting Notes",
"page_size": 10
}Then run:
bash -c 'curl -s -X POST "https://api.notion.com/v1/search" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" --header "Content-Type: application/json" -d @/tmp/notion_request.json | jq '"'"'.results[] | {id, object, title: .properties.title.title[0].plain_text // .title[0].plain_text}'"'"Docs: https://developers.notion.com/reference/post-search
List Database Entries
Write to /tmp/notion_request.json:
{
"page_size": 100
}Replace <your-database-id> with your actual database ID and run:
bash -c 'curl -s -X POST "https://api.notion.com/v1/databases/<your-database-id>/query" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" --header "Content-Type: application/json" -d @/tmp/notion_request.json | jq '"'"'.results[] | {id, properties}'"'"Docs: https://developers.notion.com/reference/post-database-query
Query with Filter
Replace <your-database-id> with your actual database ID:
curl -s -X POST "https://api.notion.com/v1/databases/<your-database-id>/query" --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28' --header 'Content-Type: application/json' -d @- << 'EOF'
{
"filter": {
"property": "Status",
"select": {"equals": "Done"}
},
"sorts": [{"property": "Date", "direction": "descending"}],
"page_size": 50
}
EOFQuery with Multiple Filters
Replace <your-database-id> with your actual database ID:
curl -s -X POST "https://api.notion.com/v1/databases/<your-database-id>/query" --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28' --header 'Content-Type: application/json' -d @- << 'EOF'
{
"filter": {
"and": [
{"property": "Status", "select": {"does_not_equal": "Archived"}},
{"property": "Due", "date": {"on_or_before": "2024-12-31"}}
]
}
}
EOFGet Database Schema
Replace <your-database-id> with your actual database ID:
bash -c 'curl -s "https://api.notion.com/v1/databases/<your-database-id>" --header "Authorization: Bearer $NOTION_TOKEN" --header '"'"'Notion-Version: 2022-06-28'"'"' | jq '"'"'{title: .title[0].plain_text, properties: .properties | keys}'"'"Docs: https://developers.notion.com/reference/retrieve-a-database
Get Page
Replace <your-page-id> with your actual page ID:
bash -c 'curl -s "https://api.notion.com/v1/pages/<your-page-id>" --header "Authorization: Bearer $NOTION_TOKEN" --header '"'"'Notion-Version: 2022-06-28'"'"' | jq '"'"'{id, url, properties}'"'"Docs: https://developers.notion.com/reference/retrieve-a-page
Create Page in Database
curl -s -X POST 'https://api.notion.com/v1/pages' --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28' --header 'Content-Type: application/json' -d @- << 'EOF'
{
"parent": {"database_id": "your-database-id"},
"properties": {
"Name": {"title": [{"text": {"content": "New Task"}}]},
"Status": {"select": {"name": "To Do"}},
"Due": {"date": {"start": "2024-12-31"}}
}
}
EOFDocs: https://developers.notion.com/reference/post-page
Create Page with Content
curl -s -X POST 'https://api.notion.com/v1/pages' --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28' --header 'Content-Type: application/json' -d @- << 'EOF'
{
"parent": {"page_id": "parent-page-id"},
"properties": {
"title": {"title": [{"text": {"content": "My New Page"}}]}
},
"children": [
{
"object": "block",
"type": "heading_2",
"heading_2": {"rich_text": [{"text": {"content": "Introduction"}}]}
},
{
"object": "block",
"type": "paragraph",
"paragraph": {"rich_text": [{"text": {"content": "This is the content."}}]}
}
]
}
EOFUpdate Page Properties
Replace <your-page-id> with your actual page ID:
curl -s -X PATCH "https://api.notion.com/v1/pages/<your-page-id>" --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28' --header 'Content-Type: application/json' -d @- << 'EOF'
{
"properties": {
"Status": {"select": {"name": "In Progress"}}
}
}
EOFDocs: https://developers.notion.com/reference/patch-page
Archive Page
Write to /tmp/notion_request.json:
{
"archived": true
}Replace <your-page-id> with your actual page ID and run:
bash -c 'curl -s -X PATCH "https://api.notion.com/v1/pages/<your-page-id>" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" --header "Content-Type: application/json" -d @/tmp/notion_request.json'Get Block Children
Replace <your-block-id> with your actual block ID:
bash -c 'curl -s "https://api.notion.com/v1/blocks/<your-block-id>/children?page_size=100" --header "Authorization: Bearer $NOTION_TOKEN" --header '"'"'Notion-Version: 2022-06-28'"'"' | jq '"'"'.results[] | {type, id}'"'"Docs: https://developers.notion.com/reference/get-block-children
Append Blocks to Page
Replace <your-page-id> with your actual page ID:
curl -s -X PATCH "https://api.notion.com/v1/blocks/<your-page-id>/children" --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28' --header 'Content-Type: application/json' -d @- << 'EOF'
{
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {"rich_text": [{"text": {"content": "New paragraph added."}}]}
},
{
"object": "block",
"type": "to_do",
"to_do": {
"rich_text": [{"text": {"content": "Task item"}}],
"checked": false
}
}
]
}
EOFDocs: https://developers.notion.com/reference/patch-block-children
Delete Block
Replace <your-block-id> with your actual block ID:
curl -s -X DELETE "https://api.notion.com/v1/blocks/<your-block-id>" --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28'List Users
bash -c 'curl -s '"'"'https://api.notion.com/v1/users'"'"' --header "Authorization: Bearer $NOTION_TOKEN" --header '"'"'Notion-Version: 2022-06-28'"'"' | jq '"'"'.results[] | {id, name, type}'"'"Docs: https://developers.notion.com/reference/get-users
Get Current Bot
curl -s 'https://api.notion.com/v1/users/me' --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28'Create Database
curl -s -X POST 'https://api.notion.com/v1/databases' --header "Authorization: Bearer $NOTION_TOKEN" --header 'Notion-Version: 2022-06-28' --header 'Content-Type: application/json' -d @- << 'EOF'
{
"parent": {"page_id": "parent-page-id"},
"title": [{"text": {"content": "Task Tracker"}}],
"properties": {
"Name": {"title": {}},
"Status": {"select": {"options": [
{"name": "To Do", "color": "gray"},
{"name": "In Progress", "color": "blue"},
{"name": "Done", "color": "green"}
]}},
"Due Date": {"date": {}},
"Assignee": {"people": {}},
"Priority": {"select": {"options": [
{"name": "High", "color": "red"},
{"name": "Medium", "color": "yellow"},
{"name": "Low", "color": "green"}
]}}
}
}
EOFDocs: https://developers.notion.com/reference/create-a-database
Property Types
Setting Properties (Create/Update)
| Type | Format |
|---|---|
| Title | {"title": [{"text": {"content": "value"}}]} |
| Rich Text | {"rich_text": [{"text": {"content": "value"}}]} |
| Number | {"number": 42} |
| Select | {"select": {"name": "Option"}} |
| Multi-select | {"multi_select": [{"name": "Tag1"}, {"name": "Tag2"}]} |
| Date | {"date": {"start": "2024-01-01", "end": "2024-01-31"}} |
| Checkbox | {"checkbox": true} |
| URL | {"url": "https://example.com"} |
{"email": "user@example.com"} |
|
| Phone | {"phone_number": "+1234567890"} |
| People | {"people": [{"id": "user-id"}]} |
| Relation | {"relation": [{"id": "page-id"}]} |
Block Types
Text Blocks
{"type": "paragraph", "paragraph": {"rich_text": [{"text": {"content": "Text"}}]}}
{"type": "heading_1", "heading_1": {"rich_text": [{"text": {"content": "H1"}}]}}
{"type": "heading_2", "heading_2": {"rich_text": [{"text": {"content": "H2"}}]}}
{"type": "heading_3", "heading_3": {"rich_text": [{"text": {"content": "H3"}}]}}
{"type": "quote", "quote": {"rich_text": [{"text": {"content": "Quote"}}]}}
{"type": "callout", "callout": {"rich_text": [{"text": {"content": "Note"}}], "icon": {"emoji": "💡"}}}List Blocks
{"type": "bulleted_list_item", "bulleted_list_item": {"rich_text": [{"text": {"content": "Item"}}]}}
{"type": "numbered_list_item", "numbered_list_item": {"rich_text": [{"text": {"content": "Item"}}]}}
{"type": "to_do", "to_do": {"rich_text": [{"text": {"content": "Task"}}], "checked": false}}
{"type": "toggle", "toggle": {"rich_text": [{"text": {"content": "Toggle"}}]}}Code Block
{"type": "code", "code": {"rich_text": [{"text": {"content": "console.log('Hello')"}}], "language": "javascript"}}Divider
{"type": "divider", "divider": {}}Filter Operators
Text/Title/Rich Text
equals, does_not_equal, contains, does_not_contain, starts_with, ends_with, is_empty, is_not_empty
Number
equals, does_not_equal, greater_than, less_than, greater_than_or_equal_to, less_than_or_equal_to, is_empty, is_not_empty
Date
equals, before, after, on_or_before, on_or_after, is_empty, is_not_empty, past_week, past_month, past_year, next_week, next_month, next_year
Select/Multi-select
equals, does_not_equal, is_empty, is_not_empty, contains (multi-select), does_not_contain (multi-select)
Checkbox
equals, does_not_equal
Rich Text Annotations
{
"text": {"content": "Styled text", "link": {"url": "https://example.com"}},
"annotations": {
"bold": true,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "red"
}
}Colors: default, gray, brown, orange, yellow, green, blue, purple, pink, red, gray_background, brown_background, etc.
Pagination
All list endpoints support cursor-based pagination:
Write to /tmp/notion_request.json:
{
"page_size": 100
}# First request
bash -c 'curl -s -X POST "https://api.notion.com/v1/databases/<your-database-id>/query" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" --header "Content-Type: application/json" -d @/tmp/notion_request.json'
# Response includes: {"next_cursor": "abc123", "has_more": true}Write to /tmp/notion_request.json:
{
"page_size": 100,
"start_cursor": "<your-cursor>"
}# Next page
bash -c 'curl -s -X POST "https://api.notion.com/v1/databases/<your-database-id>/query" --header "Authorization: Bearer $NOTION_TOKEN" --header "Notion-Version: 2022-06-28" --header "Content-Type: application/json" -d @/tmp/notion_request.json'Rate Limits
- Average: 3 requests/second
- Burst: Higher for short periods
- 429 response = retry with exponential backoff
API Reference
- Main Docs: https://developers.notion.com
- API Reference: https://developers.notion.com/reference
- Integration Settings: https://www.notion.so/profile/integrations