Python client for the official Notion API
—
Client classes and configuration options for the Notion API client library, supporting both synchronous and asynchronous operations with comprehensive configuration capabilities.
The main synchronous client for Notion API operations.
class Client:
"""Synchronous client for Notion's API."""
def __init__(self, options=None, client=None, **kwargs):
"""
Initialize the synchronous client.
Parameters:
- options: ClientOptions or dict with configuration options
- client: Optional custom httpx.Client instance
- **kwargs: Configuration options passed directly (alternative to options dict)
"""
def __enter__(self):
"""Context manager entry."""
def __exit__(self, exc_type, exc_value, traceback):
"""Context manager exit."""
def close(self):
"""Close the connection pool of the current inner client."""
def request(self, path, method, query=None, body=None, form_data=None, auth=None):
"""
Send an HTTP request.
Parameters:
- path: str, API endpoint path
- method: str, HTTP method (GET, POST, PATCH, DELETE)
- query: dict, query parameters
- body: dict, request body for JSON requests
- form_data: dict, form data for multipart requests
- auth: str, optional auth token for this request
Returns:
Response data as dict
Raises:
- RequestTimeoutError: If request times out
- APIResponseError: If API returns an error
- HTTPResponseError: If HTTP request fails
"""The asynchronous client for use in async/await environments.
class AsyncClient:
"""Asynchronous client for Notion's API."""
def __init__(self, options=None, client=None, **kwargs):
"""
Initialize the asynchronous client.
Parameters:
- options: ClientOptions or dict with configuration options
- client: Optional custom httpx.AsyncClient instance
- **kwargs: Configuration options passed directly (alternative to options dict)
"""
async def __aenter__(self):
"""Async context manager entry."""
async def __aexit__(self, exc_type, exc_value, traceback):
"""Async context manager exit."""
async def aclose(self):
"""Close the connection pool of the current inner client."""
async def request(self, path, method, query=None, body=None, form_data=None, auth=None):
"""
Send an HTTP request asynchronously.
Parameters:
- path: str, API endpoint path
- method: str, HTTP method (GET, POST, PATCH, DELETE)
- query: dict, query parameters
- body: dict, request body for JSON requests
- form_data: dict, form data for multipart requests
- auth: str, optional auth token for this request
Returns:
Response data as dict
Raises:
- RequestTimeoutError: If request times out
- APIResponseError: If API returns an error
- HTTPResponseError: If HTTP request fails
"""Configuration options for customizing client behavior.
@dataclass
class ClientOptions:
"""Options to configure the client."""
auth: Optional[str] = None
"""Bearer token for authentication. If left undefined, the auth parameter should be set on each request."""
timeout_ms: int = 60_000
"""Number of milliseconds to wait before emitting a RequestTimeoutError."""
base_url: str = "https://api.notion.com"
"""The root URL for sending API requests. This can be changed to test with a mock server."""
log_level: int = logging.WARNING
"""Verbosity of logs the instance will produce. By default, logs are written to stdout."""
logger: Optional[logging.Logger] = None
"""A custom logger."""
notion_version: str = "2022-06-28"
"""Notion version to use."""The shared base implementation for both sync and async clients.
class BaseClient:
"""Base client with shared functionality."""
def __init__(self, client, options=None, **kwargs):
"""
Initialize the base client.
Parameters:
- client: httpx.Client or httpx.AsyncClient instance
- options: ClientOptions or dict with configuration options
- **kwargs: Configuration options passed directly
"""
# Endpoint instances
blocks: BlocksEndpoint
databases: DatabasesEndpoint
users: UsersEndpoint
pages: PagesEndpoint
search: SearchEndpoint
comments: CommentsEndpoint
file_uploads: FileUploadsEndpoint
# Properties
client: Union[httpx.Client, httpx.AsyncClient]
logger: logging.Logger
options: ClientOptionsfrom notion_client import Client, AsyncClient
import os
# Synchronous client with environment variable
notion = Client(auth=os.environ["NOTION_TOKEN"])
# Asynchronous client with environment variable
async_notion = AsyncClient(auth=os.environ["NOTION_TOKEN"])import logging
from notion_client import Client, ClientOptions
# Using ClientOptions dataclass
options = ClientOptions(
auth="your_token_here",
timeout_ms=30_000, # 30 seconds
log_level=logging.DEBUG,
base_url="https://api.notion.com" # Default, shown for example
)
notion = Client(options=options)
# Using keyword arguments
notion = Client(
auth="your_token_here",
timeout_ms=30_000,
log_level=logging.DEBUG
)
# Using options dictionary
notion = Client(options={
"auth": "your_token_here",
"timeout_ms": 30_000,
"log_level": logging.DEBUG
})import logging
from notion_client import Client
# Create custom logger
logger = logging.getLogger("my_notion_client")
handler = logging.FileHandler("notion_api.log")
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
# Use custom logger
notion = Client(
auth=os.environ["NOTION_TOKEN"],
logger=logger,
log_level=logging.DEBUG
)# Synchronous context manager
with Client(auth=os.environ["NOTION_TOKEN"]) as notion:
users = notion.users.list()
# Connection automatically closed
# Asynchronous context manager
async with AsyncClient(auth=os.environ["NOTION_TOKEN"]) as notion:
users = await notion.users.list()
# Connection automatically closedimport httpx
from notion_client import Client, AsyncClient
# Custom synchronous HTTP client
custom_client = httpx.Client(
timeout=30.0,
limits=httpx.Limits(max_keepalive_connections=5, max_connections=10)
)
notion = Client(client=custom_client, auth="your_token")
# Custom asynchronous HTTP client
custom_async_client = httpx.AsyncClient(
timeout=30.0,
limits=httpx.Limits(max_keepalive_connections=5, max_connections=10)
)
async_notion = AsyncClient(client=custom_async_client, auth="your_token")# Initialize client without default auth
notion = Client()
# Provide auth per request
users = notion.users.list(auth="token_for_this_request")
databases = notion.databases.query(
database_id="xxx",
auth="different_token_for_this_request"
)from notion_client import Client
# Point to mock server for testing
notion = Client(
auth="test_token",
base_url="http://localhost:3000" # Your mock server
)# Create client
notion = Client(auth="your_token")
# Use client
users = notion.users.list()
# Manually close when done
notion.close()
# For async client
async_notion = AsyncClient(auth="your_token")
users = await async_notion.users.list()
await async_notion.aclose()# Context managers handle cleanup automatically
with Client(auth="your_token") as notion:
users = notion.users.list()
# Automatically closed on exit
async with AsyncClient(auth="your_token") as notion:
users = await notion.users.list()
# Automatically closed on exitInstall with Tessl CLI
npx tessl i tessl/pypi-notion-client