Airflow provider for Notion API integration
Project description
Airflow Notion Provider
This provider enables Apache Airflow to integrate with Notion API, allowing you to automate workflows involving Notion databases, pages, and other content.
API Version: This provider uses Notion API version 2025-09-03, which supports multi-source databases. See Migration Guide for upgrading from older versions.
Installation
pip install airflow-provider-notion
Configuration
- Get your Notion API token from Notion Integrations
- New tokens use
ntn_prefix (after Sept 2024) - Legacy tokens with
secret_prefix still work
- New tokens use
- Set the connection in Airflow:
- Connection ID:
notion_default - Connection Type:
notion(custom type registered by this provider) - Password:
YOUR_NOTION_API_TOKEN(format:ntn_xxxxx...orsecret_xxxxx...) - Extra (optional):
{"headers": {"Notion-Version": "2025-09-03"}}
- Connection ID:
Configuration Methods
Method 1: Airflow UI
Admin → Connections → Add Connection
- Connection Id: notion_default
- Connection Type: notion
- Password: ntn_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Method 2: Environment Variable
export AIRFLOW_CONN_NOTION_DEFAULT='{"conn_type": "notion", "password": "ntn_YOUR_TOKEN"}'
Method 3: Airflow CLI
airflow connections add notion_default \
--conn-type notion \
--conn-password ntn_YOUR_NOTION_TOKEN
Operators
NotionQueryDatabaseOperator
Query a Notion database or data source and return the results.
Note: For API 2025-09-03+, prefer using data_source_id. If only database_id is provided, the operator will automatically discover the first data source.
from airflow.providers.notion.operators import NotionQueryDatabaseOperator
# Recommended: Use data_source_id
query_database = NotionQueryDatabaseOperator(
task_id='query_notion_datasource',
data_source_id='your-data-source-id', # Preferred
filter_params={
'property': 'Status',
'select': {
'equals': 'Done'
}
},
sorts=[
{
'property': 'Created',
'direction': 'descending'
}
],
page_size=50,
dag=dag
)
# Legacy: Auto-discover from database_id (backward compatible)
query_database_legacy = NotionQueryDatabaseOperator(
task_id='query_notion_database',
database_id='your-database-id', # Auto-discovers first data source
filter_params={
'property': 'Status',
'select': {
'equals': 'Done'
}
},
dag=dag
)
NotionCreatePageOperator
Create a new page in a Notion data source.
Note: For API 2025-09-03+, prefer using data_source_id. If only database_id is provided, the operator will automatically discover the first data source.
from airflow.providers.notion.operators import NotionCreatePageOperator
# Recommended: Use data_source_id
create_page = NotionCreatePageOperator(
task_id='create_notion_page',
data_source_id='your-data-source-id', # Preferred
properties={
'Title': {
'title': [
{
'text': {
'content': 'New Task'
}
}
]
},
'Status': {
'select': {
'name': 'In Progress'
}
}
},
children=[ # Optional page content
{
'object': 'block',
'type': 'paragraph',
'paragraph': {
'rich_text': [{'type': 'text', 'text': {'content': 'Page content here'}}]
}
}
],
dag=dag
)
# Legacy: Auto-discover from database_id (backward compatible)
create_page_legacy = NotionCreatePageOperator(
task_id='create_notion_page_legacy',
database_id='your-database-id', # Auto-discovers first data source
properties={...},
dag=dag
)
NotionUpdatePageOperator
Update an existing Notion page.
from airflow.providers.nion.operators import NotionUpdatePageOperator
update_page = NotionUpdatePageOperator(
task_id='update_notion_page',
page_id='your-page-id',
properties={
'Status': {
'select': {
'name': 'Completed'
}
}
},
dag=dag
)
Hooks
NotionHook
The base hook for interacting with Notion API (version 2025-09-03).
from airflow.providers.notion.hooks import NotionHook
hook = NotionHook(notion_conn_id='notion_default')
# Get data sources for a database
db_info = hook.get_data_sources('database-id')
data_sources = db_info.get('data_sources', [])
data_source_id = data_sources[0]['id']
# Query data source (recommended)
results = hook.query_data_source(
data_source_id='data-source-id',
filter_params={...},
sorts=[...],
page_size=50
)
# Query database (legacy, auto-discovers first data source)
results = hook.query_database(database_id='database-id', filter_params={...})
# Create page with data_source_id (recommended)
page = hook.create_page(
data_source_id='data-source-id',
properties={...}
)
# Create page with database_id (legacy, auto-discovers first data source)
page = hook.create_page(database_id='database-id', properties={...})
# Update page (unchanged)
page = hook.update_page(page_id='page-id', properties={...})
# Get page
page = hook.get_page(page_id='page-id')
# Block operations
children = hook.get_block_children(block_id='block-id')
hook.append_block_children(block_id='block-id', children=[...])
Migration from Legacy API
This provider uses Notion API version 2025-09-03, which introduces multi-source databases. Key changes:
What Changed?
-
Database → Data Source paradigm:
- Old: One database = one data table
- New: One database can contain multiple data sources (tables)
- Each data source has its own ID and schema
-
API Endpoints:
- Old:
POST /v1/databases/{database_id}/query - New:
POST /v1/data_sources/{data_source_id}/query
- Old:
-
Parent Type for Pages:
- Old:
{"parent": {"database_id": "..."}} - New:
{"parent": {"data_source_id": "..."}}
- Old:
How to Migrate?
Option 1: Automatic Migration (Recommended)
- Keep using
database_idparameter - The provider automatically discovers the first data source
- Works for single-source databases (most common case)
# No changes needed - backward compatible
query = NotionQueryDatabaseOperator(
task_id='query',
database_id='your-database-id', # Auto-discovers data_source_id
...
)
Option 2: Explicit Data Source IDs
- Get data source ID from database
- Use
data_source_idparameter explicitly - Required for multi-source databases
# Step 1: Get data source ID (one-time setup)
hook = NotionHook()
db_info = hook.get_data_sources('your-database-id')
data_source_id = db_info['data_sources'][0]['id'] # First data source
# Step 2: Use data_source_id in operators
query = NotionQueryDatabaseOperator(
task_id='query',
data_source_id=data_source_id, # Explicit data source
...
)
Finding Your Data Source ID:
- In Notion app: Database Settings → Manage data sources → Copy data source ID
- Via API:
GET /v1/databases/{database_id}returnsdata_sourcesarray - Via Hook:
hook.get_data_sources(database_id)
Breaking Changes
If users add a second data source to a database in Notion, integrations using database_id will:
- Still work with automatic discovery (uses first data source)
- May not query the intended data source if multiple exist
- Should be updated to use explicit
data_source_id
Development
Install development dependencies:
pip install -e ".[dev]"
Run tests:
pytest tests/
Format code:
black airflow/
Check types:
mypy airflow/
License
Apache License 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file airflow_provider_notion-0.0.1.1.tar.gz.
File metadata
- Download URL: airflow_provider_notion-0.0.1.1.tar.gz
- Upload date:
- Size: 45.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32daf694ba1855d470f3bc92ef6f080769d590286a75a97b4d4abde7e601c4f5
|
|
| MD5 |
bd1bf82447eed04d154315fe3bf9face
|
|
| BLAKE2b-256 |
a5a08a96a817f938be5eb8e7649cd505ddf09466c6de0132efd0b44dd27ed841
|
File details
Details for the file airflow_provider_notion-0.0.1.1-py3-none-any.whl.
File metadata
- Download URL: airflow_provider_notion-0.0.1.1-py3-none-any.whl
- Upload date:
- Size: 16.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3616ec807479989d7550f658d16512bd5893089d6c39d8c10bb5e2fbfcf03cb0
|
|
| MD5 |
e153057200e8c0cf147b9a72b8128a72
|
|
| BLAKE2b-256 |
d4d17a3ac55e33022bef2dc8d457bb0298c46a9b26d8f96af7822a2f770b0480
|