A Python client for Notion API
Project description
notion-py-client
A type-safe Python client library for the Notion API, built with Pydantic v2.
Features
- Type-Safe: Complete type definitions using Pydantic v2
- Async-First: Built on httpx for async/await support
- API 2025-09-03: Latest Notion API with DataSources support
- Comprehensive: All blocks, properties, filters, and request types
- Domain Mapping: Built-in mapper for converting to domain models
Installation
pip install notion-py-client
Quick Start
import asyncio
from notion_py_client import NotionAsyncClient
async def main():
client = NotionAsyncClient(auth="your_NOTION_API_TOKEN")
# Query a database (API 2025-09-03)
response = await client.dataSources.query(
data_source_id="your_database_id"
)
for page in response.results:
print(page.id, page.properties)
asyncio.run(main())
Notion API 2025-09-03
This library supports the latest Notion API version 2025-09-03, which introduces:
- DataSources: New paradigm replacing the legacy databases endpoint
- Backward Compatibility: Legacy
databasesendpoint still supported - Migration Path: Seamless transition from databases to dataSources
DataSources vs Databases
# New DataSources API (recommended)
await client.dataSources.query(data_source_id="...")
# Legacy Databases API (still supported)
await client.databases.query(database_id="...")
Both endpoints work identically, but dataSources is the future-proof choice.
Documentation
Full documentation is available at: https://higashi-masafumi.github.io/notion-py/
Core Capabilities
Pages
# Create a page
from notion_py_client.requests import CreatePageParameters, TitlePropertyRequest
await client.pages.create(
parameters=CreatePageParameters(
parent={"database_id": "your_database_id"},
properties={
"Name": TitlePropertyRequest(
title=[{"type": "text", "text": {"content": "New Page"}}]
)
}
)
)
Filters
from notion_py_client import NotionAsyncClient
from notion_py_client.filters import create_and_filter, create_or_filter
client = NotionAsyncClient(auth="your_NOTION_API_TOKEN")
# Simple filter (直接辞書 - IDE補完が効く)
response = await client.dataSources.query(
data_source_id="your_database_id",
filter={"property": "Status", "status": {"equals": "Active"}}
)
# AND filter with helper function (型安全 - IDE補完が効く)
filter = create_and_filter(
{"property": "Name", "rich_text": {"contains": "urgent"}},
{"property": "Status", "status": {"equals": "In Progress"}}
)
# OR filter with helper function
filter = create_or_filter(
{"property": "Priority", "select": {"equals": "High"}},
{"property": "Priority", "select": {"equals": "Medium"}}
)
# Nested filters (AND + OR)
filter = create_and_filter(
{"property": "Team", "select": {"equals": "Engineering"}},
create_or_filter(
{"property": "Status", "status": {"equals": "Active"}},
{"property": "Status", "status": {"equals": "Pending"}}
)
)
await client.dataSources.query(
data_source_id="your_database_id",
filter=filter
)
Key Benefits:
- IDE Completion: Type hints work correctly with dictionary literals
- Type Safety: TypedDict definitions match official TypeScript SDK
- No
.model_dump(): Use filters directly without conversion - Public API Compatible: Follows official Notion API specification
Domain Mapping
from notion_py_client.helper import NotionMapper, NotionPropertyDescriptor, Field
from notion_py_client.requests.property_requests import (
TitlePropertyRequest,
StatusPropertyRequest,
)
from notion_py_client.responses.property_types import TitleProperty, StatusProperty
from pydantic import BaseModel
class Task(BaseModel):
id: str
name: str
status: str
class TaskMapper(NotionMapper[Task]):
# Define field descriptors with type annotations
name_field: NotionPropertyDescriptor[TitleProperty, TitlePropertyRequest, str] = Field(
notion_name="Name",
parser=lambda p: p.title[0].plain_text if p.title else "",
request_builder=lambda v: TitlePropertyRequest(
title=[{"type": "text", "text": {"content": v}}]
)
)
status_field: NotionPropertyDescriptor[StatusProperty, StatusPropertyRequest, str] = Field(
notion_name="Status",
parser=lambda p: p.status.name if p.status else "",
request_builder=lambda v: StatusPropertyRequest(
status={"name": v}
)
)
def to_domain(self, notion_page):
"""Convert Notion page to domain model."""
props = notion_page.properties
return Task(
id=notion_page.id,
name=self.name_field.parse(props["Name"]),
status=self.status_field.parse(props["Status"]),
)
# Use the mapper
mapper = TaskMapper()
tasks = [mapper.to_domain(page) for page in response.results]
Requirements
- Python >= 3.10
- Pydantic >= 2.11.10
License
MIT License - see LICENSE for details.
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 notion_py_client-0.1.15.tar.gz.
File metadata
- Download URL: notion_py_client-0.1.15.tar.gz
- Upload date:
- Size: 153.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cec629523d3e7fcd2e483803cd449cdba04b69cb7fbcdc3707a9ea40948080bb
|
|
| MD5 |
0cbb63eb53d42bfee670e67888a348d8
|
|
| BLAKE2b-256 |
2c2cafdef3d688e560054610ba7de9605255fdfb43435a5d210b1c93db05458b
|
Provenance
The following attestation bundles were made for notion_py_client-0.1.15.tar.gz:
Publisher:
publish-to-pypi.yml on Higashi-Masafumi/notion-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notion_py_client-0.1.15.tar.gz -
Subject digest:
cec629523d3e7fcd2e483803cd449cdba04b69cb7fbcdc3707a9ea40948080bb - Sigstore transparency entry: 645221405
- Sigstore integration time:
-
Permalink:
Higashi-Masafumi/notion-py@9ef4817f8f1b8da1aad948fe85dbb0a44d363be2 -
Branch / Tag:
refs/tags/v0.1.15 - Owner: https://github.com/Higashi-Masafumi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@9ef4817f8f1b8da1aad948fe85dbb0a44d363be2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file notion_py_client-0.1.15-py3-none-any.whl.
File metadata
- Download URL: notion_py_client-0.1.15-py3-none-any.whl
- Upload date:
- Size: 110.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8dead84bdfa25afd61120efed52b96774b49395974dcd5c6dcecfd5412c3a9f
|
|
| MD5 |
e25ef52ba6a41b2f8a70c8f04448ae50
|
|
| BLAKE2b-256 |
573308484d81e9733c10925ae4b71484e747cd9bc94fb57ad3fd83a1801c3a1d
|
Provenance
The following attestation bundles were made for notion_py_client-0.1.15-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on Higashi-Masafumi/notion-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notion_py_client-0.1.15-py3-none-any.whl -
Subject digest:
b8dead84bdfa25afd61120efed52b96774b49395974dcd5c6dcecfd5412c3a9f - Sigstore transparency entry: 645221410
- Sigstore integration time:
-
Permalink:
Higashi-Masafumi/notion-py@9ef4817f8f1b8da1aad948fe85dbb0a44d363be2 -
Branch / Tag:
refs/tags/v0.1.15 - Owner: https://github.com/Higashi-Masafumi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@9ef4817f8f1b8da1aad948fe85dbb0a44d363be2 -
Trigger Event:
push
-
Statement type: