Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ramnes/notion-sdk-py
The official Notion API client library, but rewritten in Python! (sync + async)
https://github.com/ramnes/notion-sdk-py
api-client async dataclasses httpx notion notion-api python python-client
Last synced: 4 days ago
JSON representation
The official Notion API client library, but rewritten in Python! (sync + async)
- Host: GitHub
- URL: https://github.com/ramnes/notion-sdk-py
- Owner: ramnes
- License: mit
- Created: 2021-05-13T20:17:52.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-07-13T22:22:20.000Z (5 months ago)
- Last Synced: 2024-12-10T01:14:59.049Z (11 days ago)
- Topics: api-client, async, dataclasses, httpx, notion, notion-api, python, python-client
- Language: Python
- Homepage: https://ramnes.github.io/notion-sdk-py
- Size: 3.8 MB
- Stars: 1,828
- Watchers: 26
- Forks: 141
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
- best-of-web-python - GitHub - 6% open ยท โฑ๏ธ 22.02.2024): (Third-party Web APIs)
README
![notion-sdk-py](https://socialify.git.ci/ramnes/notion-sdk-py/image?font=Bitter&language=1&logo=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2F4%2F45%2FNotion_app_logo.png&owner=1&pattern=Circuit%20Board&theme=Light)
**_notion-sdk-py_ is a simple and easy to use client library for the official
[Notion API](https://developers.notion.com/).**It is meant to be a Python version of the reference [JavaScript SDK](https://github.com/makenotion/notion-sdk-js),
so usage should be very similar between both. ๐ (If not, please open an issue
or PR!)> ๐ข **Announcement** (28-12-2023) โ Release 2.2.1 is out and fixes iteration helpers.
>
> What's new in 2.2.0 (26-12-2023):
>
> * Icons and covers can now be removed from pages.
> * `filter_properties` has been added to `notion.pages.retrieve`.
> * You can now pass your own `start_cursor` in the iteration helpers.## Installation
```shell
pip install notion-client
```## Usage
> Use Notion's [Getting Started Guide](https://developers.notion.com/docs/getting-started)
> to get set up to use Notion's API.Import and initialize a client using an **integration token** or an
OAuth **access token**.```python
import os
from notion_client import Clientnotion = Client(auth=os.environ["NOTION_TOKEN"])
```In an asyncio environment, use the asynchronous client instead:
```python
from notion_client import AsyncClientnotion = AsyncClient(auth=os.environ["NOTION_TOKEN"])
```Make a request to any Notion API endpoint.
> See the complete list of endpoints in the [API reference](https://developers.notion.com/reference).
```python
from pprint import pprintlist_users_response = notion.users.list()
pprint(list_users_response)
```or with the asynchronous client:
```python
list_users_response = await notion.users.list()
pprint(list_users_response)
```This would output something like:
```text
{'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.```python
my_page = notion.databases.query(
**{
"database_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.```python
import logging
from notion_client import APIErrorCode, APIResponseErrortry:
my_page = notion.databases.query(
**{
"database_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 database
else:
# Other error handling code
logging.error(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`.```python
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](https://docs.python.org/3/howto/logging-cookbook.html)
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` | `60_000` | `int` | Number of milliseconds to wait before emitting a `RequestTimeoutError` |
| `base_url` | `"https://api.notion.com"` | `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. |### Full API responses
The following functions can distinguish between full and partial API responses.
| Function | Purpose |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `is_full_page` | Determine whether an object is a full [Page object](https://developers.notion.com/reference/page) |
| `is_full_block` | Determine whether an object is a full [Block object](https://developers.notion.com/reference/block) |
| `is_full_database` | Determine whether an object is a full [Database object](https://developers.notion.com/reference/database) |
| `is_full_page_or_database` | Determine whether an object is a full [Page object](https://developers.notion.com/reference/page) or [Database object](https://developers.notion.com/reference/database) |
| `is_full_user` | Determine whether an object is a full [User object](https://developers.notion.com/reference/user) |
| `is_full_comment` | Determine whether an object is a full [Comment object](https://developers.notion.com/reference/comment-object) |```python
from notion_client.helpers import is_full_pagefull_or_partial_pages = await notion.databases.query(
database_id="897e5a76-ae52-4b48-9fdf-e71f5945d1af"
)for page in full_or_partial_pages["results"]:
if not is_full_page_or_database(page):
continue
print(f"Created at: {page['created_time']}")
```### Utility functions
These functions can be helpful for dealing with any of the paginated APIs.
`iterate_paginated_api(function, **kwargs)` and its async version
`async_iterate_paginated_api(function, **kwargs)` turn any paginated API into a generator.The `function` parameter must accept a `start_cursor` argument. Example: `notion.blocks.children.list`.
```python
from notion_client.helpers import iterate_paginated_apifor block in iterate_paginated_api(
notion.databases.query, database_id="897e5a76-ae52-4b48-9fdf-e71f5945d1af"
):
# Do something with block.
...
```If you don't need a generator, `collect_paginated_api(function, **kwargs)` and
its async version `async_collect_paginated_api(function, **kwargs)` have the
same behavior than the previous functions, but return a list of all results
from the paginated API.```python
from notion_client.helpers import collect_paginated_apiall_results = collect_paginated_api(
notion.databases.query, database_id="897e5a76-ae52-4b48-9fdf-e71f5945d1af"
)
```## Testing
Run the tests with the `pytest` command. If you want to test against all Python
versions, you can run `tox` instead.The tests are using `pytest-vcr`'s cassettes for simulating requests to the
Notion API. To create new tests or run them without cassettes, you need to set
up the environment variables `NOTION_TOKEN` and `NOTION_TEST_PAGE_ID` (a page
where your integration has all the capabilities enabled).The code will use the page at `NOTION_TEST_PAGE_ID` to generate a temporary
environment with the Notion objects to be tested, which will be deleted
at the end of the session.## Requirements
This package supports the following minimum versions:
* Python >= 3.7
* httpx >= 0.15.0Earlier versions may still work, but we encourage people building new applications
to upgrade to the current stable.## Getting help
If you want to submit a feature request for Notion's API, or are experiencing
any issues with the API platform, please email `[email protected]`.If you found a bug with the library, please [submit an issue](https://github.com/ramnes/notion-sdk-py/issues).