Give AlbumentationsX a star on GitHub — it powers this leaderboard

Star on GitHub

notion-client

Python client for the official Notion API

Rank: #2151Downloads: 3,253,333 (30 days)Stars: 2,147Forks: 167

Description

<!-- markdownlint-disable -->

notion-sdk-py

<div align="center"> <p> <a href="https://pypi.org/project/notion-client"><img src="https://img.shields.io/pypi/v/notion-client.svg" alt="PyPI"></a> <a href="tox.ini"><img src="https://img.shields.io/pypi/pyversions/notion-client" alt="Supported Python Versions"></a> <br/> <a href="LICENSE"><img src="https://img.shields.io/github/license/ramnes/notion-sdk-py" alt="License"></a> <a href="https://github.com/ambv/black"><img src="https://img.shields.io/badge/code%20style-black-black" alt="Code style"></a> <a href="https://codecov.io/github/ramnes/notion-sdk-py"><img src="https://codecov.io/gh/ramnes/notion-sdk-py/branch/main/graphs/badge.svg" alt="Coverage"></a> <a href="https://pypistats.org/packages/notion-client"><img src="https://img.shields.io/pypi/dm/notion-client" alt="Package downloads"></a> <br/> <a href="https://github.com/ramnes/notion-sdk-py/actions/workflows/quality.yml"><img src="https://github.com/ramnes/notion-sdk-py/actions/workflows/quality.yml/badge.svg" alt="Code Quality"></a> <a href="https://github.com/ramnes/notion-sdk-py/actions/workflows/test.yml"><img src="https://github.com/ramnes/notion-sdk-py/actions/workflows/test.yml/badge.svg" alt="Tests"></a> <a href="https://github.com/ramnes/notion-sdk-py/actions/workflows/docs.yml"><img src="https://github.com/ramnes/notion-sdk-py/actions/workflows/docs.yml/badge.svg" alt="Docs"></a> </p> </div> <!-- markdownlint-enable -->

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!)

<!-- markdownlint-disable -->

Installation

<!-- markdownlint-enable -->
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': 'avo@example.org'},
              '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.

<!-- markdownlint-disable -->
OptionDefault valueTypeDescription
authNonestringBearer token for authentication. If left undefined, the auth parameter should be set on each request.
log_levellogging.WARNINGintVerbosity of logs the instance will produce. By default, logs are written to stdout.
timeout_ms60_000intNumber of milliseconds to wait before emitting a RequestTimeoutError
base_url"https://api.notion.com"stringThe root URL for sending API requests. This can be changed to test with a mock server.
loggerLog to consolelogging.LoggerA custom logger.
<!-- markdownlint-enable -->

Full API responses

The following functions can distinguish between full and partial API responses.

<!-- markdownlint-disable -->
FunctionPurpose
is_full_pageDetermine whether an object is a full Page object
is_full_blockDetermine whether an object is a full Block object
is_full_data_sourceDetermine whether an object is a full Data source object
is_full_page_or_data_sourceDetermine whether an object is a full Page object or Data source object
is_full_userDetermine whether an object is a full User object
is_full_commentDetermine whether an object is a full Comment object
<!-- markdownlint-enable -->
from notion_client.helpers import is_full_page

full_or_partial_pages = notion.data_sources.query(
    data_source_id="897e5a76-ae52-4b48-9fdf-e71f5945d1af"
)

for page in full_or_partial_pages["results"]:
    if not is_full_page_or_data_source(page):
        continue
    print(f"Created at: {page['created_time']}")

Utility functions

This package also exports a few utility functions that are helpful for dealing with any of the paginated APIs.

iterate_paginated_api(function, **kwargs)

This utility turns any paginated API into a generator.

Parameters:

  • function: Any function on the Notion client that represents a paginated API (i.e. accepts start_cursor.) Example: notion.blocks.children.list.
  • **kwargs: Arguments that should be passed to the API on the first and subsequent calls to the API, for example a block_id.

Returns:

A generator over results from the API.

Example:

from notion_client.helpers import iterate_paginated_api

for block in iterate_paginated_api(
    notion.blocks.children.list, block_id=parent_block_id
):