notion-sdk-py is a free, open source api development & testing project written in Python and released under MIT. It has 2,183 GitHub stars, 173 forks and 27 open issues, and was last pushed 4 days ago. On this registry it ranks #76 of 103 tracked projects in API Development & Testing, with 5 head-to-head comparisons available. It gained 1 stars over the last 3 tracked days.

What is notion-sdk-py?

What it is

notion-sdk-py is a Python client library for the official Notion API, positioned as a Python version of the reference JavaScript SDK. The project lives in the Python developer-tools ecosystem, where applications call Notion endpoints without low-level HTTP handling.

It solves predictable access to Notion data and operations from Python programs. Instead of manually choosing paths, query strings, request bodies, headers, and response parsing, a developer can initialize a client with an integration or OAuth token and call endpoint methods directly. The library supports synchronous and asynchronous use, fitting ordinary scripts and asyncio applications.

Key capabilities

  • It provides synchronous and asynchronous clients, Client and AsyncClient, for calling the official Notion API from Python.
  • It exposes all Notion API endpoints in both client modes, according to the README, so users are not limited to a subset.
  • It groups endpoint parameters into a single object, so callers need not remember whether a value belongs in the path, query, or body.
  • It raises APIResponseError for unsuccessful API responses and exposes a code property that can be compared with APIErrorCode.
  • It emits log information through a logger, with warnings and errors by default and request and response bodies at logging.DEBUG.
  • It allows a custom logger to send client diagnostics to another destination.

Who uses it and how

  • Python developers use it to build integrations that read or modify Notion pages, users, data sources, and other resources through the official API.
  • Application authors use it in scripts and services where a token-based client object makes API calls without hand-written request construction.
  • Async application developers use AsyncClient so Notion API calls can be awaited inside existing asyncio workflows.
  • Teams use the error-handling behavior to distinguish API failures, such as an object not being found, and choose a recovery path in their logic.

Getting started

The README shows installation with pip install notion-client, then importing Client or AsyncClient and passing an authentication token from the environment. It also points users to Notion's Getting Started Guide for setting up API access before using the client.

When to use it — and when not to

It is useful when a Python application needs a direct Notion API client with synchronous and asynchronous access, grouped parameters, and structured error handling. It is not a hosted service or infrastructure product, so it does not reduce infrastructure work beyond the client library itself. The developer still must manage Notion API setup, token handling, endpoint choice, and response interpretation, and the provided metadata lists 27 open issues and no contributor count.

project readme (upstream, from github) — read inline

notion-sdk-py

PyPI Supported Python Versions
License Code style Coverage Package downloads
Code Quality Tests Docs

notion-sdk-py is a simple and easy to use client library for the official Notion API.

It is meant to be a Python version of the reference JavaScript SDK, so usage should be very similar between both. 😊 (If not, please open an issue or PR!)

Installation

pip install notion-client

Usage

Use Notion's Getting Started Guide to get set up to use Notion's API.

Import and initialize a client using an integration token or an OAuth access token.

import os
from notion_client import Client

notion = Client(auth=os.environ["NOTION_TOKEN"])

In an asyncio environment, use the asynchronous client instead:

from notion_client import AsyncClient

notion = AsyncClient(auth=os.environ["NOTION_TOKEN"])

Make a request to any Notion API endpoint.

from pprint import pprint

list_users_response = notion.users.list()
pprint(list_users_response)

[!NOTE] See the complete list of endpoints in the API reference.

or with the asynchronous client:

list_users_response = await notion.users.list()
pprint(list_users_response)

This would output something like:

{'results': [{'avatar_url': 'https://secure.notion-static.com/e6a352a8-8381-44d0-a1dc-9ed80e62b53d.jpg',
              'id': 'd40e767c-d7af-4b18-a86d-55c61f1e39a4',
              'name': 'Avocado Lovelace',
              'object': 'user',
              'person': {'email': '[email protected]'},
              'type': 'person'},
             ...]}

All API endpoints are available in both the synchronous and asynchronous clients.

Endpoint parameters are grouped into a single object. You don't need to remember which parameters go in the path, query, or body.

my_page = notion.data_sources.query(
    **{
        "data_source_id": "897e5a76-ae52-4b48-9fdf-e71f5945d1af",
        "filter": {
            "property": "Landmark",
            "rich_text": {
                "contains": "Bridge",
            },
        },
    }
)

Handling errors

If the API returns an unsuccessful response, an APIResponseError will be raised.

The error contains properties from the response, and the most helpful is code. You can compare code to the values in the APIErrorCode object to avoid misspelling error codes.

import logging
from notion_client import APIErrorCode, APIResponseError, Client

try:
    notion = Client(auth=os.environ["NOTION_TOKEN"])
    my_page = notion.data_sources.query(
        **{
            "data_source_id": "897e5a76-ae52-4b48-9fdf-e71f5945d1af",
            "filter": {
                "property": "Landmark",
                "rich_text": {
                    "contains": "Bridge",
                },
            },
        }
    )
except APIResponseError as error:
    if error.code == APIErrorCode.ObjectNotFound:
        #
        # For example: handle by asking the user to select a different data source
        #
        ...
    else:
        # Other error handling code
        print(error)

Logging

The client emits useful information to a logger. By default, it only emits warnings and errors.

If you're debugging an application, and would like the client to log request & response bodies, set the log_level option to logging.DEBUG.

import logging
from notion_client import Client

notion = Client(
    auth=os.environ["NOTION_TOKEN"],
    log_level=logging.DEBUG,
)

You may also set a custom logger to emit logs to a destination other than stdout. Have a look at Python's logging cookbook if you want to create your own logger.

Client options

Client and AsyncClient both support the following options on initialization. These options are all keys in the single constructor parameter.

Option Default value Type Description
auth None string Bearer token for authentication. If left undefined, the auth parameter should be set on each request.
log_level logging.WARNING int Verbosity of logs the instance will produce. By default, logs are written to stdout.
timeout_ms DEFAULT_TIMEOUT_MS int Number of milliseconds to wait before emitting a RequestTimeoutError
base_url DEFAULT_BASE_URL string The root URL for sending API requests. This can be changed to test with a mock server.
logger Log to console logging.Logger A custom logger.
retry See constants RetryOptions Configuration for automatic retries on rate limits (429), service overloads (529), and server errors (500, 503). See Automatic retries below.

Automatic retries

The client automatically retries requests that fail due to rate limiting or transient server errors. By default, it will retry up to 2 times using exponential back-off with jitter.

Retryable errors:

  • rate_limited (HTTP 429) - Too many requests; retried for all HTTP methods
  • service_overload (HTTP 529) - Service overloaded; retried for all HTTP methods
  • internal_server_error (HTTP 500) - Server error; retried only for GET and DELETE
  • service_unavailable (HTTP 503) - Service temporarily unavailable; retried only for GET and DELETE

Server errors (500, 503) are only retried for idempotent HTTP methods (GET, DELETE) to avoid duplicate side effects. Rate limits (429) and service overloads (529) are retried for all methods since the server explicitly asks clients to retry.

Configuration:

from notion_client import Client, RetryOptions

notion = Client(
    auth="secret_...",
    retry=RetryOptions(
        max_retries=5,          # Maximum retry attempts (default: 2)
        initial_retry_delay_ms=500,  # Initial delay in ms (default: 1000)
        max_retry_delay_ms=60000,    # Maximum delay in ms (default: 60000)
    ),
)

To disable automatic retries:

notion = Client(auth="secret_...", retry=False)

Constants

The SDK exports named constants for all default values used by the client, as well as useful Notion-specific values. You can import them directly:

from notion_client 

readme truncated — read the full docs on github

Frequently asked questions

Is notion-sdk-py free to use?

notion-sdk-py is open source under the MIT licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does notion-sdk-py do?

Notion API client SDK, rewritten in Python! (sync + async)

What is notion-sdk-py written in?

notion-sdk-py is primarily written in Python. Its source is publicly available at https://github.com/ramnes/notion-sdk-py, and it has 2,183 GitHub stars.