Skip to main content

Notion

Notion Integration

Notion Adapter Architecture

NotionService → NotionAdapter → Notion API v1

OAuth 2.0
Public Integration
or
Internal Token
secret_...
NotionService
service.py
@service_method
delegates
NotionAdapter
notion_service.py
httpx · auth · cache
HTTPS
Notion API v1
api.notion.com/v1
Notion-Version: 2022-06-28
↓ auto-generated
HTTP Routes
CLI Commands
MCP Tools

What & Why

Notion is an all-in-one knowledge base and project management tool. With Octopus you can:

  • Create and update pages programmatically — generate meeting notes, reports, or documentation from your workflows
  • Query databases with filters and sorts — pull structured project data, task lists, or CRM rows into your agents
  • Search across your workspace by title — find pages and databases without knowing their IDs
  • Append blocks to existing pages — add content, checklists, or logs to living documents

Auth modes

ModeCredentialWhen to use
OAuth 2.0Obtained via OAuth flow (/v1/oauth/notion/authorize)Public integrations; multi-tenant
Internal Tokensecret_... from Notion integration settingsSingle-workspace automations; server-side scripts

The adapter reads the token from the JWT bearer at request time. For OAuth the NotionOAuthService subclass retrieves the stored OAuth access token from the credential store.


Notion Data Model

Notion Block Hierarchy

Workspace → Pages / Databases → Blocks / Properties

Workspace

📄 Page

object: "page"

🗃️ Database

object: "database"
Page contains Blocks
paragraph
heading_1 / heading_2 / heading_3
to_do (checkbox)
bulleted_list_item
numbered_list_item
toggle
quote
callout
code
image / video / file
child_page / child_database
All blocks share: id, type, created_time, last_edited_time
Database contains Page rows
Each row is a page with typed Properties:
title (text)
rich_text
number
select / multi_select
status
date
people
checkbox
url / email / phone
relation / rollup
query_database filters work on property type + operator
query_database filter example
{
"property": "Status",
"status": { "equals": "Done" }
}
Simplified format also accepted: {"property": "Name", "contains": "John"} — auto-normalized by the adapter.

Methods Reference

MethodDescriptionKey Parameters
list_databasesList all databases the integration can accesspage_size
get_databaseRetrieve a database by IDdatabase_id
query_databaseQuery database rows with filters and sortsdatabase_id, filter, sorts, page_size
create_database_itemCreate a new row (page) in a databasedatabase_id, properties, children
update_database_itemUpdate properties of a database rowpage_id, properties
list_pagesSearch for pages (alias: search with page filter)query, page_size
get_pageRetrieve a page by ID with simplified propertiespage_id
create_pageCreate a new page under a parent page or databaseparent, properties, children, icon, cover
update_pageUpdate page properties, icon, cover, or archive statuspage_id, properties, archived
archive_pageArchive (soft-delete) a pagepage_id
get_blocksGet child blocks of a page or blockblock_id, page_size
append_blocksAppend block children to a page or blockblock_id, children, after
searchSearch pages and databases by title across the workspacequery, page_size
list_usersList all workspace memberspage_size
get_userRetrieve a specific user by IDuser_id

Note on parent: When creating a page inside a database, use {"database_id": "<id>"}. For a sub-page under another page, use {"page_id": "<id>"}.

Note on properties: For database rows, properties must match the database schema. Use get_database to inspect the schema first. The adapter auto-flattens complex Notion property objects to plain values on read.


CLI Examples

# Search pages and databases by title
constellation notion search --query "Q1 Planning"

# List all databases
constellation notion list-databases

# Get a specific database (inspect schema)
constellation notion get-database --database-id abc123

# Query a database with a status filter
constellation notion query-database \
--database-id abc123 \
--filter '{"property": "Status", "status": {"equals": "Done"}}'

# Query with compound filter (and)
constellation notion query-database \
--database-id abc123 \
--filter '{"and": [{"property": "Status", "status": {"equals": "In Progress"}}, {"property": "Assignee", "people": {"contains": "user-id-here"}}]}'

# Get a page
constellation notion get-page --page-id page123

# Create a page under another page
constellation notion create-page \
--parent-id page123 \
--title "New Meeting Notes" \
--content "Hello Notion"

# Create a database row (page) with properties
constellation notion create-database-item \
--database-id abc123 \
--properties '{"Name": {"title": [{"text": {"content": "Sprint 42 Retro"}}]}, "Status": {"status": {"name": "Not started"}}}'

# Update page properties
constellation notion update-page \
--page-id page123 \
--properties '{"Status": {"status": {"name": "Done"}}}'

# Archive a page
constellation notion archive-page --page-id page123

# Get page content (blocks)
constellation notion get-blocks --block-id page123

# Append blocks to a page
constellation notion append-blocks \
--block-id page123 \
--children '[{"type": "paragraph", "paragraph": {"rich_text": [{"type": "text", "text": {"content": "Added via Octopus"}}]}}]'

# List workspace users
constellation notion list-users

# Get a specific user
constellation notion get-user --user-id user123

HTTP API

# Search workspace via HTTP
curl -X POST https://api.yourdomain.com/notion/search \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query": "Q1 Planning"}'

# Response
# {
# "results": [
# {"id": "page123", "object": "page", "properties": {"title": {"title": [{"plain_text": "Q1 Planning"}]}}}
# ]
# }

# Query database via HTTP
curl -X POST https://api.yourdomain.com/notion/query-database \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"database_id": "abc123", "filter": {"property": "Status", "status": {"equals": "Done"}}}'

# Append blocks via HTTP
curl -X POST https://api.yourdomain.com/notion/append-blocks \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"block_id": "page123",
"children": [{"type": "paragraph", "paragraph": {"rich_text": [{"type": "text", "text": {"content": "Added via Octopus"}}]}}]
}'

Notes

  • Notion-Version header: The adapter pins 2022-06-28 for public docs compatibility. The internal adapter uses 2025-09-03 for template support.
  • Pagination: All list methods use Notion's cursor-based pagination automatically. Pass page_size (max 100) to control batch size.
  • Response trimming: All methods return simplified objects by default (plain property values, not raw Notion rich-text arrays). Pass --raw in CLI or raw=True in service calls to get full Notion objects.
  • Block validation: append_blocks validates block structure before sending to the API — helpful error messages indicate which block index is malformed and what the expected structure is.
  • Filter normalization: Simplified filter format {"property": "Name", "contains": "John"} is automatically converted to the full Notion format by the adapter.