├── .coveragerc ├── .ecrc ├── .editorconfig ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── scripts │ ├── known_entries.json │ └── monitor_notion_changelog.py └── workflows │ ├── docs.yml │ ├── notion-changelog-monitor.yml │ ├── quality.yml │ └── test.yml ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── README.md ├── SECURITY.md ├── docs ├── SUMMARY.md ├── extra.css ├── generate.py ├── index.md └── user_guides │ ├── quick_start.md │ └── structured_logging.md ├── examples ├── README.md ├── databases │ ├── README.md │ └── create_database.py └── first_project │ ├── README.md │ └── script.py ├── mkdocs.yml ├── notion_client ├── __init__.py ├── api_endpoints.py ├── client.py ├── errors.py ├── helpers.py ├── logging.py ├── py.typed └── typing.py ├── requirements ├── base.txt ├── dev.txt ├── docs.txt ├── quality.txt └── tests.txt ├── setup.cfg ├── setup.py ├── tests ├── __init__.py ├── cassettes │ ├── test_api_async_request_bad_request_error.yaml │ ├── test_api_response_error.yaml │ ├── test_async_api_response_error.yaml │ ├── test_async_client_request.yaml │ ├── test_async_client_request_auth.yaml │ ├── test_async_collect_paginated_api.yaml │ ├── test_async_iterate_paginated_api.yaml │ ├── test_blocks_children_create.yaml │ ├── test_blocks_children_list.yaml │ ├── test_blocks_delete.yaml │ ├── test_blocks_retrieve.yaml │ ├── test_blocks_update.yaml │ ├── test_client_request.yaml │ ├── test_client_request_auth.yaml │ ├── test_collect_paginated_api.yaml │ ├── test_comments_create.yaml │ ├── test_comments_list.yaml │ ├── test_databases_create.yaml │ ├── test_databases_query.yaml │ ├── test_databases_retrieve.yaml │ ├── test_databases_update.yaml │ ├── test_is_equation_rich_text_item_response.yaml │ ├── test_is_full_block.yaml │ ├── test_is_full_comment.yaml │ ├── test_is_full_database.yaml │ ├── test_is_full_page.yaml │ ├── test_is_full_page_or_database.yaml │ ├── test_is_full_user.yaml │ ├── test_is_mention_rich_text_item_response.yaml │ ├── test_is_text_rich_text_item_response.yaml │ ├── test_iterate_paginated_api.yaml │ ├── test_pages_create.yaml │ ├── test_pages_delete.yaml │ ├── test_pages_properties_retrieve.yaml │ ├── test_pages_retrieve.yaml │ ├── test_pages_update.yaml │ ├── test_search.yaml │ ├── test_users_list.yaml │ ├── test_users_me.yaml │ └── test_users_retrieve.yaml ├── conftest.py ├── test_client.py ├── test_endpoints.py ├── test_errors.py └── test_helpers.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | exclude_lines = 3 | pragma: no cover 4 | @abstract 5 | -------------------------------------------------------------------------------- /.ecrc: -------------------------------------------------------------------------------- 1 | { 2 | "Disable": { 3 | "MaxLineLength": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | indent_style = space 8 | 9 | [*.py] 10 | max_line_length = 89 11 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines 2 | 3 | !!! tip 4 | If you are a first time contributor, please start by reading 5 | [this fantastic guide](https://opensource.guide/how-to-contribute/). 6 | 7 | Any serious contribution to notion-sdk-py is always welcome, regardless of your 8 | experience. 9 | 10 | If you want to contribute on the code specifically: 11 | 12 | 1. Install Git and Python on your system. 13 | 2. Fork the repository and clone it. 14 | 3. Checkout a new feature branch from `main`: 15 | 16 | ```shell 17 | git checkout my-feature 18 | ``` 19 | 20 | 4. Install dependencies inside a virtual environment: 21 | 22 | ```shell 23 | python -m venv .venv 24 | source .venv/bin/activate 25 | pip install -r requirements/dev.txt 26 | ``` 27 | 28 | 5. Install [pre-commit](https://pre-commit.com/) hooks: 29 | 30 | ```shell 31 | pre-commit install 32 | ``` 33 | 34 | You should now be ready to hack! 35 | 36 | You can run the tests with `pytest` in the main directory. Please make 37 | sure the tests (and pre-commit hooks) pass before opening a pull 38 | request. 39 | 40 | Coverage must stay at 100%. Write tests if you add new features. 41 | 42 | Thanks for your help! 43 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ["https://paypal.me/ramnes"] 2 | -------------------------------------------------------------------------------- /.github/scripts/monitor_notion_changelog.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import hashlib 3 | import json 4 | import logging 5 | import os 6 | from typing import Dict 7 | 8 | from bs4 import BeautifulSoup 9 | from github import Github 10 | import httpx 11 | from markdownify import markdownify as md 12 | 13 | logger = logging.getLogger(__name__) 14 | logger.addHandler(logging.StreamHandler()) 15 | logger.setLevel(logging.INFO) 16 | 17 | # Constants 18 | NOTION_CHANGELOG_URL = "https://developers.notion.com/page/changelog" 19 | DATA_FILE = ".github/scripts/known_entries.json" 20 | GITHUB_REPOSITORY = "ramnes/notion-sdk-py" 21 | 22 | 23 | async def fetch_changelog() -> str: 24 | async with httpx.AsyncClient() as client: 25 | response = await client.get(NOTION_CHANGELOG_URL) 26 | response.raise_for_status() 27 | return response.text 28 | 29 | 30 | def extract_entries(html) -> Dict[str, Dict[str, str]]: 31 | soup = BeautifulSoup(html, "html.parser") 32 | 33 | # Extract all h2 headings with a specific class 34 | headings = soup.find_all("h2", class_="heading heading-2 header-scroll") 35 | parsed_data = {} 36 | 37 | for heading in headings: 38 | # Extract section id from the heading anchor 39 | section_id = ( 40 | heading.find("div", class_="heading-anchor").get("id", None) 41 | if heading.find("div", class_="heading-anchor") 42 | else None 43 | ) 44 | if section_id is None: 45 | continue 46 | 47 | # Extract date_text that will be used as title 48 | date_text = heading.text.strip() 49 | 50 | next_element = heading.find_next_sibling() 51 | content = "" # It will be used as md5 and saved among known entries 52 | content_md = [] # It will be written ONLY on the issue 53 | while next_element and next_element.name not in {"h2"}: 54 | content += next_element.text.strip() 55 | content_md.append(md(repr(next_element))) 56 | next_element = next_element.find_next_sibling() 57 | 58 | # Update to dictionary, 59 | # keys are the md5 string of the content of each section 60 | md5_hash = hashlib.md5(content.encode()).hexdigest() 61 | parsed_data.update( 62 | { 63 | md5_hash: { 64 | "section_id": section_id, 65 | "title": date_text, 66 | "content_md": content_md, 67 | } 68 | } 69 | ) 70 | return parsed_data 71 | 72 | 73 | def read_known_entries() -> Dict[str, Dict[str, str]]: 74 | if not os.path.exists(DATA_FILE): 75 | return dict() 76 | with open(DATA_FILE, "r", encoding="utf-8") as f: 77 | return json.load(f) 78 | 79 | 80 | def save_known_entries(entries: Dict[str, Dict[str, str]]): 81 | with open(DATA_FILE, "w", encoding="utf-8") as f: 82 | json.dump(entries, f, indent=2) 83 | f.write("\n") 84 | 85 | 86 | # Open a GitHub issue 87 | def open_issue( 88 | title: str, 89 | body: str, 90 | repo_name: str, 91 | labels: tuple[str] = ("investigate", "changelog"), 92 | ): 93 | g = Github(os.getenv("GITHUB_TOKEN")) 94 | repo = g.get_repo(repo_name) 95 | # Check if an issue with same title exists 96 | for issue in repo.get_issues(): 97 | if issue.title == title: 98 | logger.info(f"Issue with title '{title}' already exists. Skipping...") 99 | return 100 | repo.create_issue(title=title, body=body, labels=list(labels)) 101 | logger.info(f"Opened issue with title '{title}'") 102 | 103 | 104 | async def main(): 105 | try: 106 | html = await fetch_changelog() 107 | except Exception as e: 108 | logger.error(f"Error while fetching changelog: {e}") 109 | raise ConnectionError("Error while fetching changelog") 110 | 111 | try: 112 | entries = extract_entries(html) 113 | except Exception as e: 114 | logger.error(f"Error while extracting entries from changelog: {e}") 115 | raise ValueError("Error while extracting entries changelog") 116 | 117 | logger.info(f"Found {len(entries)} entries in changelog") 118 | known_entries = read_known_entries() 119 | logger.info(f"Found {len(known_entries)} already known entries") 120 | 121 | new_entries_keys = set(entries) - set(known_entries) 122 | new_entries = {entry: entries[entry] for entry in new_entries_keys} 123 | 124 | if new_entries: 125 | if len(new_entries_keys) == 1: 126 | logger.info("Found 1 new entry. Opening issue for it...") 127 | else: 128 | logger.info( 129 | f"Found {len(new_entries_keys)} new entries. " 130 | f"Opening issues for them..." 131 | ) 132 | for entry in new_entries: 133 | title = f"New Notion API Changelog Entry: {new_entries[entry]['title']}" 134 | blog_post_url = f"{NOTION_CHANGELOG_URL}#{new_entries[entry]['section_id']}" 135 | body = f"**{entries[entry]['title']}**\n\n" 136 | # Pop the md content to avoid saving it on file 137 | entry_content_md = new_entries[entry].pop("content_md") 138 | for content in entry_content_md: 139 | body += f"{content}\n" 140 | body += "\n------------\n\n" 141 | body += f"Original blog post: [View here]({blog_post_url})\n" 142 | try: 143 | open_issue(title, body, GITHUB_REPOSITORY) 144 | # pass 145 | except Exception as e: 146 | logger.error(f"Error while opening issue: {e}") 147 | raise ConnectionError("Error while opening issue") 148 | logger.info("Done!") 149 | 150 | # Save updated known entries 151 | logger.info("Saving updated known entries...") 152 | known_entries.update(new_entries) 153 | save_known_entries(known_entries) 154 | logger.info("Done!") 155 | 156 | 157 | if __name__ == "__main__": 158 | asyncio.run(main()) 159 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | jobs: 8 | docs: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | fetch-depth: 0 14 | - uses: actions/setup-python@v2 15 | - run: pip install -r requirements/docs.txt 16 | - run: pytest 17 | env: 18 | NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }} 19 | - run: git config user.name 'github-actions[bot]' && git config user.email 'github-actions[bot]@users.noreply.github.com' 20 | - name: Publish docs 21 | run: mkdocs gh-deploy 22 | -------------------------------------------------------------------------------- /.github/workflows/notion-changelog-monitor.yml: -------------------------------------------------------------------------------- 1 | name: Monitor Notion API Changelog 2 | 3 | on: 4 | schedule: 5 | # Runs every day at midnight (UTC) 6 | - cron: '0 0 * * *' 7 | workflow_dispatch: # Enable manual trigger 8 | 9 | jobs: 10 | monitor-changelog: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout repository 15 | uses: actions/checkout@v3 16 | 17 | - name: Set up Python 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: '3.13' 21 | 22 | - name: Install dependencies 23 | run: | 24 | python -m pip install --upgrade pip 25 | pip install httpx PyGithub beautifulsoup4 markdownify 26 | 27 | - name: Monitor Notion API Changelog 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | run: python .github/scripts/monitor_notion_changelog.py 31 | 32 | - name: Commit and push changes 33 | run: | 34 | git config user.name "github-actions[bot]" 35 | git config user.email "github-actions[bot]@users.noreply.github.com" 36 | git add .github/scripts/known_entries.json 37 | git commit -m "Update known entries file [skip ci]" || echo "No changes to commit" 38 | git push 39 | -------------------------------------------------------------------------------- /.github/workflows/quality.yml: -------------------------------------------------------------------------------- 1 | name: Code Quality 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | check: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-python@v2 15 | - uses: pre-commit/action@v3.0.1 16 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build-and-test: 11 | 12 | runs-on: ubuntu-22.04 13 | 14 | strategy: 15 | matrix: 16 | python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] 17 | 18 | steps: 19 | 20 | - uses: actions/checkout@v3 21 | - name: Use Python ${{ matrix.python-version }} 22 | uses: actions/setup-python@v4 23 | with: 24 | python-version: ${{ matrix.python-version }} 25 | - run: pip install -r requirements/tests.txt 26 | - run: pytest 27 | env: 28 | NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }} 29 | - uses: codecov/codecov-action@v5 30 | with: 31 | env_vars: PYTHON 32 | fail_ci_if_error: true 33 | verbose: true 34 | env: 35 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Configuration for code editors 2 | .vscode 3 | .idea 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | cover/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | local_settings.py 65 | db.sqlite3 66 | db.sqlite3-journal 67 | 68 | # Flask stuff: 69 | instance/ 70 | .webassets-cache 71 | 72 | # Scrapy stuff: 73 | .scrapy 74 | 75 | # Sphinx documentation 76 | docs/_build/ 77 | 78 | # PyBuilder 79 | .pybuilder/ 80 | target/ 81 | 82 | # Jupyter Notebook 83 | .ipynb_checkpoints 84 | 85 | # IPython 86 | profile_default/ 87 | ipython_config.py 88 | 89 | # pyenv 90 | # For a library or package, you might want to ignore these files since the code is 91 | # intended to run in multiple environments; otherwise, check them in: 92 | # .python-version 93 | 94 | # pipenv 95 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 96 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 97 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 98 | # install all needed dependencies. 99 | #Pipfile.lock 100 | 101 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 102 | __pypackages__/ 103 | 104 | # Celery stuff 105 | celerybeat-schedule 106 | celerybeat.pid 107 | 108 | # SageMath parsed files 109 | *.sage.py 110 | 111 | # Environments 112 | .env 113 | .venv 114 | env/ 115 | venv/ 116 | ENV/ 117 | env.bak/ 118 | venv.bak/ 119 | .envrc 120 | 121 | # Spyder project settings 122 | .spyderproject 123 | .spyproject 124 | 125 | # Rope project settings 126 | .ropeproject 127 | 128 | # mkdocs documentation 129 | /site 130 | 131 | # mypy 132 | .mypy_cache/ 133 | .dmypy.json 134 | dmypy.json 135 | 136 | # Pyre type checker 137 | .pyre/ 138 | 139 | # pytype static type analyzer 140 | .pytype/ 141 | 142 | # Cython debug symbols 143 | cython_debug/ 144 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/igorshubovych/markdownlint-cli 3 | rev: v0.27.1 4 | hooks: 5 | - id: markdownlint 6 | 7 | - repo: https://github.com/pre-commit/mirrors-mypy 8 | rev: v0.900 9 | hooks: 10 | - id: mypy 11 | additional_dependencies: ["httpx"] 12 | args: [] 13 | files: "^notion_client\/.*" 14 | 15 | - repo: https://github.com/editorconfig-checker/editorconfig-checker.python 16 | rev: 2.3.5 17 | hooks: 18 | - id: editorconfig-checker 19 | 20 | - repo: https://github.com/astral-sh/ruff-pre-commit 21 | rev: v0.1.11 22 | hooks: 23 | - id: ruff 24 | - id: ruff-format 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021-2025 Guillaume Gelin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | **Do not report security vulnerabilities through public GitHub issues.** 4 | 5 | If you believe you've found a security issue, please send an email to 6 | github+security@ramnes.eu with the following information: 7 | 8 | * Affected versions 9 | * Step-by-step instructions to reproduce the issue 10 | * Impact of the issue, including how an attacker might exploit the issue 11 | * Possible mitigations for the issue 12 | * Proof-of-concept or exploit code (if possible) 13 | 14 | You should receive a response within 2 days. If for some reason you do not, 15 | please follow up. 16 | 17 | Thank you for your willingness to make the internet safer. 18 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | 2 | * [Home](index.md) 3 | * User guides 4 | * [Quick start](user_guides/quick_start.md) 5 | * [Structured logging](user_guides/structured_logging.md) 6 | * [More examples](https://github.com/ramnes/notion-sdk-py/tree/main/examples) 7 | * Reference 8 | * [Client](reference/client.md) 9 | * [API endpoints](reference/api_endpoints.md) 10 | * [Errors](reference/errors.md) 11 | * [Helpers](reference/helpers.md) 12 | * Development 13 | * [Coverage report](coverage.md) 14 | * [Contributing guidelines](contributing/contributing.md) 15 | * [License](license.md) 16 | -------------------------------------------------------------------------------- /docs/extra.css: -------------------------------------------------------------------------------- 1 | .md-nav__link[href^="http"]::after { 2 | content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==); 3 | margin: 0 3px 0 5px; 4 | } 5 | -------------------------------------------------------------------------------- /docs/generate.py: -------------------------------------------------------------------------------- 1 | """Generate virtual files for mkdocs.""" 2 | 3 | import mkdocs_gen_files 4 | 5 | 6 | def docs_stub(module_name): 7 | return f"::: notion_client.{module_name}\ 8 | \n\trendering:\n\t\tshow_root_heading: true\n\t\tshow_source: false" 9 | 10 | 11 | virtual_files = { 12 | "license.md": "```text\n--8<-- 'LICENSE'\n```", 13 | "reference/api_endpoints.md": docs_stub("api_endpoints"), 14 | "reference/client.md": docs_stub("client"), 15 | "reference/errors.md": docs_stub("errors"), 16 | "reference/helpers.md": docs_stub("helpers"), 17 | "contributing/contributing.md": "--8<-- '.github/CONTRIBUTING.md'", 18 | } 19 | 20 | for file_name, content in virtual_files.items(): 21 | with mkdocs_gen_files.open(file_name, "w") as file: 22 | print(content, file=file) 23 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | 2 | --8<-- 3 | README.md 4 | --8<-- 5 | # 6 | -------------------------------------------------------------------------------- /docs/user_guides/quick_start.md: -------------------------------------------------------------------------------- 1 | # Quick start 2 | 3 | Get started with notion-sdk-py in just 5 minutes! 4 | 5 | ## Setup 6 | 7 | ### Prerequisites 8 | 9 | - Make sure you have `python` and `pip` properly installed in your system. 10 | 11 | ```shell 12 | python --version 13 | pip --version 14 | ``` 15 | 16 | - Create a new directory and move into it to follow along with this tutorial. 17 | 18 | ```shell 19 | mkdir learn-notion-sdk-py && cd learn-notion-sdk-py 20 | ``` 21 | 22 | ### Installation 23 | 24 | - Create a virtual environment and activate it. 25 | 26 | ```shell 27 | python -m venv .venv && source .venv/bin/activate 28 | ``` 29 | 30 | - Install `notion-sdk-py` using `pip` 31 | 32 | ```shell 33 | pip install --upgrade notion-client 34 | ``` 35 | 36 | ### Integration 37 | 38 | - Go to [notion.so/my-integrations](https://www.notion.so/my-integrations) 39 | to create an integration. Copy the token given by Notion. 40 | 41 | - Make it available in your environment: 42 | 43 | ```shell 44 | export NOTION_TOKEN=ntn_abcd12345 45 | ``` 46 | 47 | !!! tip 48 | Don't forget that `export` only puts the variable in the environment of the 49 | current shell. 50 | If you don't want to redo this step for every new shell, 51 | add the line in your shell configuration 52 | or use a configuration library like [dotenv](https://github.com/theskumar/python-dotenv). 53 | 54 | ## Play 55 | 56 | Copy paste the code, and have fun tweaking it! 57 | 58 | Let's start by initializing the client: 59 | 60 | ```python 61 | import os 62 | from notion_client import Client 63 | 64 | notion = Client(auth=os.environ["NOTION_TOKEN"]) 65 | ``` 66 | 67 | Let's now fetch the list of users in the scope of our integration: 68 | 69 | ```python 70 | users = notion.users.list() 71 | 72 | for user in users.get("results"): 73 | name, user_type = user["name"], user["type"] 74 | emoji = "😅" if user["type"] == "bot" else "🙋‍♂️" 75 | print(f"{name} is a {user_type} {emoji}") 76 | ``` 77 | 78 | It should output something in those lines: 79 | 80 | ```shell 81 | Aahnik Daw is a person 🙋‍♂️ 82 | TestIntegation is a bot 😅 83 | ``` 84 | 85 | Do you see your name and the name of your integration? 86 | 87 | 🎉 Congratulations, you are now ready to use notion-sdk-py! 88 | -------------------------------------------------------------------------------- /docs/user_guides/structured_logging.md: -------------------------------------------------------------------------------- 1 | # Structured logging 2 | 3 | You can easily get structured logging with notion-sdk-py by using 4 | [structlog](https://www.structlog.org/en/stable/index.html): 5 | 6 | ```python 7 | logger = structlog.wrap_logger( 8 | logging.getLogger("notion-client"), 9 | logger_factory=structlog.stdlib.LoggerFactory(), 10 | wrapper_class=structlog.stdlib.BoundLogger, 11 | ) 12 | 13 | notion = Client(auth=token, logger=logger, log_level=logging.DEBUG) 14 | ``` 15 | 16 | Don't forget to add the dependency to your project! 17 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | This section contains several single-file examples using [notion-sdk-py]. 4 | 5 | Read the [Quick Start](/docs/user_guides/quick_start.md) before you come here. 6 | 7 | ## Downloading 8 | 9 | You may download all. 10 | 11 | ```shell 12 | git clone https://github.com/ramnes/notion-sdk-py 13 | cd notion-sdk-py/examples 14 | ls # list all examples 15 | ``` 16 | 17 | All examples are licensed under the [CC0 License](https://creativecommons.org/choose/zero/), 18 | so you can use them as the base for your own code without worrying about copyright. 19 | -------------------------------------------------------------------------------- /examples/databases/README.md: -------------------------------------------------------------------------------- 1 | # Create a database 2 | 3 | This example shows how to create a new database inside an existing Notion page. 4 | 5 | ## Content of the example 6 | 7 | The `manual_inputs` function is used to collect the page ID and 8 | the name of the target database. 9 | 10 | *Enter the ID or the URL of the page in which you want to create the database:* 11 | 12 | The URL of the parent page or its ID can be entered here. 13 | 14 | *Name of the database that you want to create:* 15 | 16 | Provide the name of the newly created database. 17 | 18 | The `create_database`function defines the property of the database. 19 | 20 | *Note*: when creating a database, a property of type *title* is always required. 21 | 22 | ## Execute test 23 | 24 | Your NOTION_TOKEN must be defined in as an environment variable. 25 | If not, a prompt will ask you for it. 26 | 27 | ### Install notion-client 28 | 29 | 30 | ```shell 31 | pip install notion-client 32 | ``` 33 | 34 | ### Run the test 35 | 36 | 37 | ```shell 38 | python create_database.py 39 | ``` 40 | -------------------------------------------------------------------------------- /examples/databases/create_database.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from notion_client import Client 4 | from notion_client.helpers import get_id 5 | 6 | NOTION_TOKEN = os.getenv("NOTION_TOKEN", "") 7 | 8 | while NOTION_TOKEN == "": 9 | print("NOTION_TOKEN not found.") 10 | NOTION_TOKEN = input("Enter your integration token: ").strip() 11 | 12 | # Initialize the client 13 | notion = Client(auth=NOTION_TOKEN) 14 | 15 | 16 | def manual_inputs(parent_id="", db_name="") -> tuple: 17 | """ 18 | Get values from user input 19 | """ 20 | if parent_id == "": 21 | is_page_ok = False 22 | while not is_page_ok: 23 | input_text = input("\nEnter the parent page ID or URL: ").strip() 24 | # Checking if the page exists 25 | try: 26 | if input_text[:4] == "http": 27 | parent_id = get_id(input_text) 28 | print(f"\nThe ID of the target page is: {parent_id}") 29 | else: 30 | parent_id = input_text 31 | notion.pages.retrieve(parent_id) 32 | is_page_ok = True 33 | print("Page found") 34 | except Exception as e: 35 | print(e) 36 | continue 37 | while db_name == "": 38 | db_name = input("\n\nName of the database that you want to create: ") 39 | 40 | return (parent_id, db_name) 41 | 42 | 43 | def create_database(parent_id: str, db_name: str) -> dict: 44 | """ 45 | parent_id(str): ID of the parent page 46 | db_name(str): Title of the database 47 | """ 48 | print(f"\n\nCreate database '{db_name}' in page {parent_id}...") 49 | properties = { 50 | "Name": {"title": {}}, # This is a required property 51 | "Description": {"rich_text": {}}, 52 | "In stock": {"checkbox": {}}, 53 | "Food group": { 54 | "select": { 55 | "options": [ 56 | {"name": "🥦 Vegetable", "color": "green"}, 57 | {"name": "🍎 Fruit", "color": "red"}, 58 | {"name": "💪 Protein", "color": "yellow"}, 59 | ] 60 | } 61 | }, 62 | "Price": {"number": {"format": "dollar"}}, 63 | "Last ordered": {"date": {}}, 64 | "Store availability": { 65 | "type": "multi_select", 66 | "multi_select": { 67 | "options": [ 68 | {"name": "Duc Loi Market", "color": "blue"}, 69 | {"name": "Rainbow Grocery", "color": "gray"}, 70 | {"name": "Nijiya Market", "color": "purple"}, 71 | {"name": "Gus's Community Market", "color": "yellow"}, 72 | ] 73 | }, 74 | }, 75 | "+1": {"people": {}}, 76 | "Photo": {"files": {}}, 77 | } 78 | title = [{"type": "text", "text": {"content": db_name}}] 79 | icon = {"type": "emoji", "emoji": "🎉"} 80 | parent = {"type": "page_id", "page_id": parent_id} 81 | return notion.databases.create( 82 | parent=parent, title=title, properties=properties, icon=icon 83 | ) 84 | 85 | 86 | if __name__ == "__main__": 87 | parent_id, db_name = manual_inputs() 88 | newdb = create_database(parent_id=parent_id, db_name=db_name) 89 | print(f"\n\nDatabase {db_name} created at {newdb['url']}\n") 90 | -------------------------------------------------------------------------------- /examples/first_project/README.md: -------------------------------------------------------------------------------- 1 | # First Project 2 | 3 | A simple project for beginners to get started with. 4 | 5 | ## Objectives 6 | 7 | This project will show you how to: 8 | 9 | - Search for an item 10 | - Create a new page 11 | - Query a database 12 | 13 | ## Create a demo page 14 | 15 | Lastly we need a notion page to experiment with. 16 | Duplicate [this page](https://www.notion.so/notion-sdk-py-540f8e2b79914654ba103c5d8a03e10e) 17 | in your workspace. 18 | 19 | After [creating an integration](https://www.notion.com/my-integrations), 20 | [share](https://developers.notion.com/docs/authorization) the page with the 21 | integration. To do so, visit the page in your Notion workspace, click the ••• 22 | menu at the top right of a page, scroll down to `Add connections`, and use the 23 | search bar to find and select the integration from the dropdown list. 24 | 25 | ## Run the script 26 | 27 | Make sure your have `notion-sdk-py` installed. 28 | 29 | You may optionally install `python-dotenv` 30 | if you want the script to load your `.env` file. 31 | 32 | ```shell 33 | python script.py 34 | ``` 35 | 36 | ![notion_first_project](https://user-images.githubusercontent.com/66209958/119083985-a67e1c80-ba1e-11eb-9221-bea43f3c7b6e.gif) 37 | -------------------------------------------------------------------------------- /examples/first_project/script.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from pprint import pprint 4 | 5 | from notion_client import Client 6 | 7 | try: 8 | from dotenv import load_dotenv 9 | except ModuleNotFoundError: 10 | print("Could not load .env because python-dotenv not found.") 11 | else: 12 | load_dotenv() 13 | 14 | NOTION_TOKEN = os.getenv("NOTION_TOKEN", "") 15 | 16 | while NOTION_TOKEN == "": 17 | print("NOTION_TOKEN not found.") 18 | NOTION_TOKEN = input("Enter your integration token: ").strip() 19 | 20 | # Initialize the client 21 | notion = Client(auth=NOTION_TOKEN) 22 | 23 | 24 | # Search for an item 25 | print("\nSearching for the word 'People' ") 26 | results = notion.search(query="People").get("results") 27 | print(len(results)) 28 | result = results[0] 29 | print("The result is a", result["object"]) 30 | pprint(result["properties"]) 31 | 32 | database_id = result["id"] # store the database id in a variable for future use 33 | 34 | # Create a new page 35 | your_name = input("\n\nEnter your name: ") 36 | gh_uname = input("Enter your github username: ") 37 | new_page = { 38 | "Name": {"title": [{"text": {"content": your_name}}]}, 39 | "Tags": {"type": "multi_select", "multi_select": [{"name": "python"}]}, 40 | # Properties like this must exist in the database columns 41 | "GitHub": { 42 | "type": "rich_text", 43 | "rich_text": [ 44 | { 45 | "type": "text", 46 | "text": {"content": gh_uname}, 47 | }, 48 | ], 49 | }, 50 | } 51 | 52 | content = [ 53 | { 54 | "object": "block", 55 | "type": "paragraph", 56 | "paragraph": { 57 | "rich_text": [ 58 | { 59 | "type": "text", 60 | "text": { 61 | "content": ( 62 | "The content of your page goes here. See https://developers.notion.com/reference/post-page" 63 | ) 64 | }, 65 | } 66 | ] 67 | }, 68 | } 69 | ] 70 | notion.pages.create( 71 | parent={"database_id": database_id}, properties=new_page, children=content 72 | ) 73 | print("You were added to the People database!") 74 | 75 | 76 | # Query a database 77 | name = input("\n\nEnter the name of the person to search in People: ") 78 | results = notion.databases.query( 79 | **{ 80 | "database_id": database_id, 81 | "filter": {"property": "Name", "rich_text": {"contains": name}}, 82 | } 83 | ).get("results") 84 | 85 | no_of_results = len(results) 86 | 87 | if no_of_results == 0: 88 | print("No results found.") 89 | sys.exit() 90 | 91 | print(f"No of results found: {len(results)}") 92 | 93 | result = results[0] 94 | 95 | print(f"The first result is a {result['object']} with id {result['id']}.") 96 | print(f"This was created on {result['created_time']}") 97 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: notion-sdk-py 2 | 3 | repo_url: https://github.com/ramnes/notion-sdk-py 4 | 5 | edit_uri: "" 6 | 7 | extra_css: [extra.css] 8 | 9 | theme: 10 | name: material 11 | navigation_depth: 4 12 | features: 13 | - naviagation.sections 14 | - navigation.indexes 15 | icon: 16 | repo: fontawesome/brands/github 17 | font: 18 | text: Tahoma 19 | code: Source Code Pro 20 | palette: 21 | - media: "(prefers-color-scheme: light)" 22 | scheme: default 23 | primary: deep orange 24 | accent: orange 25 | toggle: 26 | icon: material/lightbulb-outline 27 | name: Switch to dark mode 28 | - media: "(prefers-color-scheme: dark)" 29 | scheme: slate 30 | primary: orange 31 | accent: deep orange 32 | toggle: 33 | icon: material/lightbulb 34 | name: Switch to light mode 35 | 36 | plugins: 37 | - search 38 | - gen-files: 39 | scripts: 40 | - docs/generate.py 41 | - literate-nav: 42 | nav_file: SUMMARY.md 43 | - section-index 44 | - mkdocstrings 45 | - coverage 46 | 47 | markdown_extensions: 48 | - admonition 49 | - pymdownx.highlight 50 | - pymdownx.superfences 51 | - pymdownx.snippets: 52 | check_paths: true 53 | 54 | extra: 55 | social: 56 | - icon: fontawesome/brands/github 57 | link: https://github.com/ramnes/notion-sdk-py 58 | -------------------------------------------------------------------------------- /notion_client/__init__.py: -------------------------------------------------------------------------------- 1 | """Package notion-sdk-py. 2 | 3 | A sync + async python client for the official Notion API. 4 | Connect Notion pages and databases to the tools you use every day, 5 | creating powerful workflows. 6 | For more information visit https://github.com/ramnes/notion-sdk-py. 7 | """ 8 | 9 | from .client import AsyncClient, Client 10 | from .errors import APIErrorCode, APIResponseError 11 | 12 | __all__ = ["AsyncClient", "Client", "APIErrorCode", "APIResponseError"] 13 | -------------------------------------------------------------------------------- /notion_client/errors.py: -------------------------------------------------------------------------------- 1 | """Custom exceptions for notion-sdk-py. 2 | 3 | This module defines the exceptions that can be raised when an error occurs. 4 | """ 5 | from enum import Enum 6 | from typing import Optional 7 | 8 | import httpx 9 | 10 | 11 | class RequestTimeoutError(Exception): 12 | """Exception for requests that timeout. 13 | 14 | The request that we made waits for a specified period of time or maximum number of 15 | retries to get the response. But if no response comes within the limited time or 16 | retries, then this Exception is raised. 17 | """ 18 | 19 | code = "notionhq_client_request_timeout" 20 | 21 | def __init__(self, message: str = "Request to Notion API has timed out") -> None: 22 | super().__init__(message) 23 | 24 | 25 | class HTTPResponseError(Exception): 26 | """Exception for HTTP errors. 27 | 28 | Responses from the API use HTTP response codes that are used to indicate general 29 | classes of success and error. 30 | """ 31 | 32 | code: str = "notionhq_client_response_error" 33 | status: int 34 | headers: httpx.Headers 35 | body: str 36 | 37 | def __init__(self, response: httpx.Response, message: Optional[str] = None) -> None: 38 | if message is None: 39 | message = ( 40 | f"Request to Notion API failed with status: {response.status_code}" 41 | ) 42 | super().__init__(message) 43 | self.status = response.status_code 44 | self.headers = response.headers 45 | self.body = response.text 46 | 47 | 48 | class APIErrorCode(str, Enum): 49 | Unauthorized = "unauthorized" 50 | """The bearer token is not valid.""" 51 | 52 | RestrictedResource = "restricted_resource" 53 | """Given the bearer token used, the client doesn't have permission to 54 | perform this operation.""" 55 | 56 | ObjectNotFound = "object_not_found" 57 | """Given the bearer token used, the resource does not exist. 58 | This error can also indicate that the resource has not been shared with owner 59 | of the bearer token.""" 60 | 61 | RateLimited = "rate_limited" 62 | """This request exceeds the number of requests allowed. Slow down and try again.""" 63 | 64 | InvalidJSON = "invalid_json" 65 | """The request body could not be decoded as JSON.""" 66 | 67 | InvalidRequestURL = "invalid_request_url" 68 | """The request URL is not valid.""" 69 | 70 | InvalidRequest = "invalid_request" 71 | """This request is not supported.""" 72 | 73 | ValidationError = "validation_error" 74 | """The request body does not match the schema for the expected parameters.""" 75 | 76 | ConflictError = "conflict_error" 77 | """The transaction could not be completed, potentially due to a data collision. 78 | Make sure the parameters are up to date and try again.""" 79 | 80 | InternalServerError = "internal_server_error" 81 | """An unexpected error occurred. Reach out to Notion support.""" 82 | 83 | ServiceUnavailable = "service_unavailable" 84 | """Notion is unavailable. Try again later. 85 | This can occur when the time to respond to a request takes longer than 60 seconds, 86 | the maximum request timeout.""" 87 | 88 | 89 | class APIResponseError(HTTPResponseError): 90 | """An error raised by Notion API.""" 91 | 92 | code: APIErrorCode 93 | 94 | def __init__( 95 | self, response: httpx.Response, message: str, code: APIErrorCode 96 | ) -> None: 97 | super().__init__(response, message) 98 | self.code = code 99 | 100 | 101 | def is_api_error_code(code: str) -> bool: 102 | """Check if given code belongs to the list of valid API error codes.""" 103 | if isinstance(code, str): 104 | return code in (error_code.value for error_code in APIErrorCode) 105 | return False 106 | -------------------------------------------------------------------------------- /notion_client/helpers.py: -------------------------------------------------------------------------------- 1 | """Utility functions for notion-sdk-py.""" 2 | from typing import Any, AsyncGenerator, Awaitable, Callable, Dict, Generator, List 3 | from urllib.parse import urlparse 4 | from uuid import UUID 5 | 6 | 7 | def pick(base: Dict[Any, Any], *keys: str) -> Dict[Any, Any]: 8 | """Return a dict composed of key value pairs for keys passed as args.""" 9 | result = {} 10 | for key in keys: 11 | if key not in base: 12 | continue 13 | value = base.get(key) 14 | if value is None and key == "start_cursor": 15 | continue 16 | result[key] = value 17 | return result 18 | 19 | 20 | def get_url(object_id: str) -> str: 21 | """Return the URL for the object with the given id.""" 22 | return f"https://notion.so/{UUID(object_id).hex}" 23 | 24 | 25 | def get_id(url: str) -> str: 26 | """Return the id of the object behind the given URL.""" 27 | parsed = urlparse(url) 28 | if parsed.netloc not in ("notion.so", "www.notion.so"): 29 | raise ValueError("Not a valid Notion URL.") 30 | path = parsed.path 31 | if len(path) < 32: 32 | raise ValueError("The path in the URL seems to be incorrect.") 33 | raw_id = path[-32:] 34 | return str(UUID(raw_id)) 35 | 36 | 37 | def iterate_paginated_api( 38 | function: Callable[..., Any], **kwargs: Any 39 | ) -> Generator[Any, None, None]: 40 | """Return an iterator over the results of any paginated Notion API.""" 41 | next_cursor = kwargs.pop("start_cursor", None) 42 | 43 | while True: 44 | response = function(**kwargs, start_cursor=next_cursor) 45 | for result in response.get("results"): 46 | yield result 47 | 48 | next_cursor = response.get("next_cursor") 49 | if not response.get("has_more") or not next_cursor: 50 | return 51 | 52 | 53 | def collect_paginated_api(function: Callable[..., Any], **kwargs: Any) -> List[Any]: 54 | """Collect all the results of paginating an API into a list.""" 55 | return [result for result in iterate_paginated_api(function, **kwargs)] 56 | 57 | 58 | async def async_iterate_paginated_api( 59 | function: Callable[..., Awaitable[Any]], **kwargs: Any 60 | ) -> AsyncGenerator[Any, None]: 61 | """Return an async iterator over the results of any paginated Notion API.""" 62 | next_cursor = kwargs.pop("start_cursor", None) 63 | 64 | while True: 65 | response = await function(**kwargs, start_cursor=next_cursor) 66 | for result in response.get("results"): 67 | yield result 68 | 69 | next_cursor = response.get("next_cursor") 70 | if (not response["has_more"]) | (next_cursor is None): 71 | return 72 | 73 | 74 | async def async_collect_paginated_api( 75 | function: Callable[..., Awaitable[Any]], **kwargs: Any 76 | ) -> List[Any]: 77 | """Collect asynchronously all the results of paginating an API into a list.""" 78 | return [result async for result in async_iterate_paginated_api(function, **kwargs)] 79 | 80 | 81 | def is_full_block(response: Dict[Any, Any]) -> bool: 82 | """Return `True` if response is a full block.""" 83 | return response.get("object") == "block" and "type" in response 84 | 85 | 86 | def is_full_page(response: Dict[Any, Any]) -> bool: 87 | """Return `True` if response is a full page.""" 88 | return response.get("object") == "page" and "url" in response 89 | 90 | 91 | def is_full_database(response: Dict[Any, Any]) -> bool: 92 | """Return `True` if response is a full database.""" 93 | return response.get("object") == "database" and "title" in response 94 | 95 | 96 | def is_full_page_or_database(response: Dict[Any, Any]) -> bool: 97 | """Return `True` if `response` is a full database or a full page.""" 98 | if response.get("object") == "database": 99 | return is_full_database(response) 100 | return is_full_page(response) 101 | 102 | 103 | def is_full_user(response: Dict[Any, Any]) -> bool: 104 | """Return `True` if response is a full user.""" 105 | return "type" in response 106 | 107 | 108 | def is_full_comment(response: Dict[Any, Any]) -> bool: 109 | """Return `True` if response is a full comment.""" 110 | return "type" in response 111 | 112 | 113 | def is_text_rich_text_item_response(rich_text: Dict[Any, Any]) -> bool: 114 | """Return `True` if `rich_text` is a text.""" 115 | return rich_text.get("type") == "text" 116 | 117 | 118 | def is_equation_rich_text_item_response(rich_text: Dict[Any, Any]) -> bool: 119 | """Return `True` if `rich_text` is an equation.""" 120 | return rich_text.get("type") == "equation" 121 | 122 | 123 | def is_mention_rich_text_item_response(rich_text: Dict[Any, Any]) -> bool: 124 | """Return `True` if `rich_text` is a mention.""" 125 | return rich_text.get("type") == "mention" 126 | -------------------------------------------------------------------------------- /notion_client/logging.py: -------------------------------------------------------------------------------- 1 | """Custom logging for notion-sdk-py.""" 2 | 3 | import logging 4 | from logging import Logger 5 | 6 | 7 | def make_console_logger() -> Logger: 8 | """Return a custom logger.""" 9 | logger = logging.getLogger(__package__) 10 | handler = logging.StreamHandler() 11 | formatter = logging.Formatter(logging.BASIC_FORMAT) 12 | handler.setFormatter(formatter) 13 | logger.addHandler(handler) 14 | return logger 15 | -------------------------------------------------------------------------------- /notion_client/py.typed: -------------------------------------------------------------------------------- 1 | # Marker file for PEP 561. 2 | -------------------------------------------------------------------------------- /notion_client/typing.py: -------------------------------------------------------------------------------- 1 | """Custom type definitions for notion-sdk-py.""" 2 | from typing import Awaitable, TypeVar, Union 3 | 4 | T = TypeVar("T") 5 | SyncAsync = Union[T, Awaitable[T]] 6 | -------------------------------------------------------------------------------- /requirements/base.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | -------------------------------------------------------------------------------- /requirements/dev.txt: -------------------------------------------------------------------------------- 1 | -r tests.txt 2 | -r quality.txt 3 | tox 4 | -------------------------------------------------------------------------------- /requirements/docs.txt: -------------------------------------------------------------------------------- 1 | -r tests.txt 2 | mkdocs 3 | mkdocstrings 4 | mkdocstrings-python 5 | mkdocs-coverage 6 | mkdocs-gen-files 7 | mkdocs-literate-nav 8 | mkdocs-material 9 | mkdocs-section-index 10 | -------------------------------------------------------------------------------- /requirements/quality.txt: -------------------------------------------------------------------------------- 1 | pre-commit 2 | -------------------------------------------------------------------------------- /requirements/tests.txt: -------------------------------------------------------------------------------- 1 | -r base.txt 2 | pytest 3 | pytest-asyncio 4 | pytest-cov 5 | pytest-timeout 6 | pytest-vcr 7 | 8 | # I'm unable to use vcrpy 6.x cassettes (UnicodeDecodeError on JSON body), let's try again later 9 | vcrpy<6 10 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal=1 3 | 4 | [tool:pytest] 5 | minversion = 6.0 6 | addopts = --cov=./notion_client --cov-report=term-missing --cov-report=xml --cov-report=html 7 | asyncio_mode = auto 8 | asyncio_default_fixture_loop_scope = function 9 | 10 | [flake8] 11 | max-line-length = 89 12 | 13 | [mypy] 14 | files = notion_client 15 | # --strict 16 | disallow_any_generics = True 17 | disallow_subclassing_any = True 18 | disallow_untyped_calls = True 19 | disallow_untyped_defs = True 20 | disallow_incomplete_defs = True 21 | check_untyped_defs = True 22 | disallow_untyped_decorators = True 23 | no_implicit_optional = True 24 | warn_redundant_casts = True 25 | warn_unused_ignores = True 26 | warn_return_any = True 27 | implicit_reexport = False 28 | strict_equality = True 29 | # --strict end 30 | 31 | [pydocstyle] 32 | ignore = D101, D105, D107, D203, D212, D213, D214, D215, D404, D405, D406, D407, D408, D409, D410, D411, D413, D415, D416, D417 33 | ignore-decorators = property 34 | # D101: Missing docstring in public class 35 | # D105: Missing docstring in magic method 36 | # D107: Missing docstring in __init__ 37 | # rest of the ignored errors are pep257 defaults 38 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | def get_description(): 5 | with open("README.md") as file: 6 | return file.read() 7 | 8 | 9 | setup( 10 | name="notion-client", 11 | version="2.3.0", 12 | url="https://github.com/ramnes/notion-sdk-py", 13 | author="Guillaume Gelin", 14 | author_email="contact@ramnes.eu", 15 | description="Python client for the official Notion API", 16 | long_description=get_description(), 17 | long_description_content_type="text/markdown", 18 | packages=["notion_client"], 19 | python_requires=">=3.7, <4", 20 | install_requires=[ 21 | "httpx >= 0.23.0", 22 | ], 23 | classifiers=[ 24 | "Programming Language :: Python :: 3.7", 25 | "Programming Language :: Python :: 3.8", 26 | "Programming Language :: Python :: 3.9", 27 | "Programming Language :: Python :: 3.10", 28 | "Programming Language :: Python :: 3.11", 29 | "Programming Language :: Python :: 3.12", 30 | "Programming Language :: Python :: 3.13", 31 | "Development Status :: 5 - Production/Stable", 32 | "License :: OSI Approved :: MIT License", 33 | ], 34 | package_data={"notion_client": ["py.typed"]}, 35 | ) 36 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramnes/notion-sdk-py/72f8e28170a919e046c62a2b4c8ba3c771c0a10b/tests/__init__.py -------------------------------------------------------------------------------- /tests/cassettes/test_api_async_request_bad_request_error.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - mock.httpstatus.io 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://mock.httpstatus.io/400 19 | response: 20 | content: 400 Bad Request 21 | headers: {} 22 | http_version: HTTP/1.1 23 | status_code: 400 24 | version: 1 25 | -------------------------------------------------------------------------------- /tests/cassettes/test_api_response_error.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/invalid 19 | response: 20 | content: '{"object":"error","status":400,"code":"invalid_request_url","message":"Invalid 21 | request URL."}' 22 | headers: {} 23 | http_version: HTTP/1.1 24 | status_code: 400 25 | - request: 26 | body: '' 27 | headers: 28 | accept: 29 | - '*/*' 30 | accept-encoding: 31 | - gzip, deflate 32 | authorization: 33 | - ntn_... 34 | connection: 35 | - keep-alive 36 | host: 37 | - api.notion.com 38 | notion-version: 39 | - '2022-06-28' 40 | method: GET 41 | uri: https://api.notion.com/v1/users 42 | response: 43 | content: '{"object":"error","status":401,"code":"unauthorized","message":"API 44 | token is invalid.","request_id":"15ca8906-fcb1-4d90-b25a-ad03ba508350"}' 45 | headers: {} 46 | http_version: HTTP/1.1 47 | status_code: 401 48 | version: 1 49 | -------------------------------------------------------------------------------- /tests/cassettes/test_async_api_response_error.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/invalid 19 | response: 20 | content: '{"object":"error","status":400,"code":"invalid_request_url","message":"Invalid 21 | request URL."}' 22 | headers: {} 23 | http_version: HTTP/1.1 24 | status_code: 400 25 | - request: 26 | body: '' 27 | headers: 28 | accept: 29 | - '*/*' 30 | accept-encoding: 31 | - gzip, deflate 32 | authorization: 33 | - ntn_... 34 | connection: 35 | - keep-alive 36 | host: 37 | - api.notion.com 38 | notion-version: 39 | - '2022-06-28' 40 | method: GET 41 | uri: https://api.notion.com/v1/users 42 | response: 43 | content: '{"object":"error","status":401,"code":"unauthorized","message":"API 44 | token is invalid.","request_id":"d11a2027-fae9-4cad-a6ea-ab6e34136dc5"}' 45 | headers: {} 46 | http_version: HTTP/1.1 47 | status_code: 401 48 | version: 1 49 | -------------------------------------------------------------------------------- /tests/cassettes/test_async_client_request.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/invalid 19 | response: 20 | content: '{"object":"error","status":400,"code":"invalid_request_url","message":"Invalid 21 | request URL."}' 22 | headers: {} 23 | http_version: HTTP/1.1 24 | status_code: 400 25 | - request: 26 | body: '' 27 | headers: 28 | accept: 29 | - '*/*' 30 | accept-encoding: 31 | - gzip, deflate 32 | authorization: 33 | - ntn_... 34 | connection: 35 | - keep-alive 36 | host: 37 | - api.notion.com 38 | notion-version: 39 | - '2022-06-28' 40 | method: GET 41 | uri: https://api.notion.com/v1/users 42 | response: 43 | content: '{"object":"list","results":[{"object":"user","id":"a4f789cc-7bc8-4cf0-82b9-a8ba7d985ecf","name":"Guillaume 44 | Gelin","avatar_url":"https://s3-us-west-2.amazonaws.com/public.notion-static.com/01d7053d-e135-4f27-bba0-5de532d39296/ramnes3.jpeg","type":"person","person":{"email":"notion@ramnes.eu"}},{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"}}],"next_cursor":null,"has_more":false,"type":"user","user":{},"request_id":"9f260c07-a0cf-4dda-afa0-2c6e005301c5"}' 45 | headers: {} 46 | http_version: HTTP/1.1 47 | status_code: 200 48 | version: 1 49 | -------------------------------------------------------------------------------- /tests/cassettes/test_async_client_request_auth.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/users 19 | response: 20 | content: '{"object":"error","status":401,"code":"unauthorized","message":"API 21 | token is invalid.","request_id":"649c77c8-264f-4e74-a2c9-4a1c6adf08ec"}' 22 | headers: {} 23 | http_version: HTTP/1.1 24 | status_code: 401 25 | - request: 26 | body: '' 27 | headers: 28 | accept: 29 | - '*/*' 30 | accept-encoding: 31 | - gzip, deflate 32 | authorization: 33 | - ntn_... 34 | connection: 35 | - keep-alive 36 | host: 37 | - api.notion.com 38 | notion-version: 39 | - '2022-06-28' 40 | method: GET 41 | uri: https://api.notion.com/v1/users 42 | response: 43 | content: '{"object":"list","results":[{"object":"user","id":"a4f789cc-7bc8-4cf0-82b9-a8ba7d985ecf","name":"Guillaume 44 | Gelin","avatar_url":"https://s3-us-west-2.amazonaws.com/public.notion-static.com/01d7053d-e135-4f27-bba0-5de532d39296/ramnes3.jpeg","type":"person","person":{"email":"notion@ramnes.eu"}},{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"}}],"next_cursor":null,"has_more":false,"type":"user","user":{},"request_id":"a1e1dc6c-d7e2-4e5f-856b-cd1414e7c987"}' 45 | headers: {} 46 | http_version: HTTP/1.1 47 | status_code: 200 48 | version: 1 49 | -------------------------------------------------------------------------------- /tests/cassettes/test_async_collect_paginated_api.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{}' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | content-length: 14 | - '2' 15 | content-type: 16 | - application/json 17 | host: 18 | - api.notion.com 19 | notion-version: 20 | - '2022-06-28' 21 | method: POST 22 | uri: https://api.notion.com/v1/search 23 | response: 24 | content: '{"object":"list","results":[{"object":"page","id":"95ba0116-6776-4c19-9e45-54e77415f03b","created_time":"2023-06-29T12:47:00.000Z","last_edited_time":"2024-12-30T17:22:00.000Z","created_by":{"object":"user","id":"a4f789cc-7bc8-4cf0-82b9-a8ba7d985ecf"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"workspace","workspace":true},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[]}},"url":"https://www.notion.so/95ba011667764c199e4554e77415f03b","public_url":null}],"next_cursor":null,"has_more":false,"type":"page_or_database","page_or_database":{},"request_id":"42e3d551-2338-49d2-9d1b-705340893950"}' 25 | headers: {} 26 | http_version: HTTP/1.1 27 | status_code: 200 28 | - request: 29 | body: '{"query":"This should have no results"}' 30 | headers: 31 | accept: 32 | - '*/*' 33 | accept-encoding: 34 | - gzip, deflate 35 | authorization: 36 | - ntn_... 37 | connection: 38 | - keep-alive 39 | content-length: 40 | - '39' 41 | content-type: 42 | - application/json 43 | host: 44 | - api.notion.com 45 | notion-version: 46 | - '2022-06-28' 47 | method: POST 48 | uri: https://api.notion.com/v1/search 49 | response: 50 | content: '{"object":"list","results":[],"next_cursor":null,"has_more":false,"type":"page_or_database","page_or_database":{},"request_id":"d71d978b-b503-4577-9709-68365c8ddcfd"}' 51 | headers: {} 52 | http_version: HTTP/1.1 53 | status_code: 200 54 | version: 1 55 | -------------------------------------------------------------------------------- /tests/cassettes/test_blocks_children_create.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:00.309404"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8126-a13b-e29717b63c94","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:00.309404","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:00.309404","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-00-309404-16cabc1eedcd8126a13be29717b63c94","public_url":null,"request_id":"d187fb9d-8030-4941-a06e-78053f811785"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"children":[{"paragraph":{"rich_text":[{"text":{"content":"I''m a paragraph."}}]}}]}' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '84' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: PATCH 51 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8126-a13b-e29717b63c94/children 52 | response: 53 | content: '{"object":"list","results":[{"object":"block","id":"16cabc1e-edcd-8112-bae0-d5e6d8a0d77f","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8126-a13b-e29717b63c94"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 54 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 55 | a paragraph.","href":null}],"color":"default"}}],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"a433c39d-0913-4386-ac4d-fe79c8b41e11"}' 56 | headers: {} 57 | http_version: HTTP/1.1 58 | status_code: 200 59 | - request: 60 | body: '' 61 | headers: 62 | accept: 63 | - '*/*' 64 | accept-encoding: 65 | - gzip, deflate 66 | authorization: 67 | - ntn_... 68 | connection: 69 | - keep-alive 70 | host: 71 | - api.notion.com 72 | notion-version: 73 | - '2022-06-28' 74 | method: DELETE 75 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8126-a13b-e29717b63c94 76 | response: 77 | content: '{"object":"block","id":"16cabc1e-edcd-8126-a13b-e29717b63c94","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":true,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 78 | 2024-12-30 18:21:00.309404"},"request_id":"d01ce2d1-4feb-4b5f-bf80-0edacc3dfb1f"}' 79 | headers: {} 80 | http_version: HTTP/1.1 81 | status_code: 200 82 | version: 1 83 | -------------------------------------------------------------------------------- /tests/cassettes/test_blocks_children_list.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:02.726723"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-81a1-9982-e644ed7fa6a2","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:02.726723","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:02.726723","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-02-726723-16cabc1eedcd81a19982e644ed7fa6a2","public_url":null,"request_id":"29ed4c8e-44c8-4eb3-ae6d-18e97670562d"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | host: 43 | - api.notion.com 44 | notion-version: 45 | - '2022-06-28' 46 | method: GET 47 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81a1-9982-e644ed7fa6a2/children 48 | response: 49 | content: '{"object":"list","results":[],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"65de73d0-aa29-49ca-8cc9-edf6140d4a47"}' 50 | headers: {} 51 | http_version: HTTP/1.1 52 | status_code: 200 53 | - request: 54 | body: '' 55 | headers: 56 | accept: 57 | - '*/*' 58 | accept-encoding: 59 | - gzip, deflate 60 | authorization: 61 | - ntn_... 62 | connection: 63 | - keep-alive 64 | host: 65 | - api.notion.com 66 | notion-version: 67 | - '2022-06-28' 68 | method: DELETE 69 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81a1-9982-e644ed7fa6a2 70 | response: 71 | content: '{"object":"block","id":"16cabc1e-edcd-81a1-9982-e644ed7fa6a2","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 72 | 2024-12-30 18:21:02.726723"},"request_id":"e5caf3a7-b66c-45e7-b3d4-f34bb79dc072"}' 73 | headers: {} 74 | http_version: HTTP/1.1 75 | status_code: 200 76 | version: 1 77 | -------------------------------------------------------------------------------- /tests/cassettes/test_blocks_retrieve.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:05.602133"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-81f1-ae27-de4d47c5c0c2","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:05.602133","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:05.602133","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-05-602133-16cabc1eedcd81f1ae27de4d47c5c0c2","public_url":null,"request_id":"0eb35cb9-cda3-461c-aa1a-c47feb14c496"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"children":[{"paragraph":{"rich_text":[{"text":{"content":"I''m a paragraph."}}]}}]}' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '84' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: PATCH 51 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81f1-ae27-de4d47c5c0c2/children 52 | response: 53 | content: '{"object":"list","results":[{"object":"block","id":"16cabc1e-edcd-8165-9e47-ddcd77401df9","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81f1-ae27-de4d47c5c0c2"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 54 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 55 | a paragraph.","href":null}],"color":"default"}}],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"01c5f203-98bc-4bd2-adc7-3b64555ab7c2"}' 56 | headers: {} 57 | http_version: HTTP/1.1 58 | status_code: 200 59 | - request: 60 | body: '' 61 | headers: 62 | accept: 63 | - '*/*' 64 | accept-encoding: 65 | - gzip, deflate 66 | authorization: 67 | - ntn_... 68 | connection: 69 | - keep-alive 70 | host: 71 | - api.notion.com 72 | notion-version: 73 | - '2022-06-28' 74 | method: GET 75 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8165-9e47-ddcd77401df9 76 | response: 77 | content: '{"object":"block","id":"16cabc1e-edcd-8165-9e47-ddcd77401df9","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81f1-ae27-de4d47c5c0c2"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 78 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 79 | a paragraph.","href":null}],"color":"default"},"request_id":"d32f01da-9eb3-4506-a34d-5a56d1373ac0"}' 80 | headers: {} 81 | http_version: HTTP/1.1 82 | status_code: 200 83 | - request: 84 | body: '' 85 | headers: 86 | accept: 87 | - '*/*' 88 | accept-encoding: 89 | - gzip, deflate 90 | authorization: 91 | - ntn_... 92 | connection: 93 | - keep-alive 94 | host: 95 | - api.notion.com 96 | notion-version: 97 | - '2022-06-28' 98 | method: DELETE 99 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8165-9e47-ddcd77401df9 100 | response: 101 | content: '{"object":"block","id":"16cabc1e-edcd-8165-9e47-ddcd77401df9","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81f1-ae27-de4d47c5c0c2"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 102 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 103 | a paragraph.","href":null}],"color":"default"},"request_id":"2fe662d9-d825-45c2-8d61-f656025c3d2d"}' 104 | headers: {} 105 | http_version: HTTP/1.1 106 | status_code: 200 107 | - request: 108 | body: '' 109 | headers: 110 | accept: 111 | - '*/*' 112 | accept-encoding: 113 | - gzip, deflate 114 | authorization: 115 | - ntn_... 116 | connection: 117 | - keep-alive 118 | host: 119 | - api.notion.com 120 | notion-version: 121 | - '2022-06-28' 122 | method: DELETE 123 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81f1-ae27-de4d47c5c0c2 124 | response: 125 | content: '{"object":"block","id":"16cabc1e-edcd-81f1-ae27-de4d47c5c0c2","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 126 | 2024-12-30 18:21:05.602133"},"request_id":"9a99a507-03fd-4ae0-8ff7-03fd83a3308c"}' 127 | headers: {} 128 | http_version: HTTP/1.1 129 | status_code: 200 130 | version: 1 131 | -------------------------------------------------------------------------------- /tests/cassettes/test_blocks_update.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:09.273712"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-81eb-856e-ffa0fc3f59b8","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:09.273712","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:09.273712","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-09-273712-16cabc1eedcd81eb856effa0fc3f59b8","public_url":null,"request_id":"5d0dadc6-0222-4d66-8205-ffcde835ac3d"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"children":[{"paragraph":{"rich_text":[{"text":{"content":"I''m a paragraph."}}]}}]}' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '84' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: PATCH 51 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81eb-856e-ffa0fc3f59b8/children 52 | response: 53 | content: '{"object":"list","results":[{"object":"block","id":"16cabc1e-edcd-819c-bf82-c8fa3a922688","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81eb-856e-ffa0fc3f59b8"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 54 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 55 | a paragraph.","href":null}],"color":"default"}}],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"73d146ac-1a9e-4f14-a2b7-aaa6118c0068"}' 56 | headers: {} 57 | http_version: HTTP/1.1 58 | status_code: 200 59 | - request: 60 | body: '{"paragraph":{"rich_text":[{"text":{"content":"I''m an updated paragraph."},"annotations":{"bold":true,"color":"red_background"}}]}}' 61 | headers: 62 | accept: 63 | - '*/*' 64 | accept-encoding: 65 | - gzip, deflate 66 | authorization: 67 | - ntn_... 68 | connection: 69 | - keep-alive 70 | content-length: 71 | - '131' 72 | content-type: 73 | - application/json 74 | host: 75 | - api.notion.com 76 | notion-version: 77 | - '2022-06-28' 78 | method: PATCH 79 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-819c-bf82-c8fa3a922688 80 | response: 81 | content: '{"object":"block","id":"16cabc1e-edcd-819c-bf82-c8fa3a922688","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81eb-856e-ffa0fc3f59b8"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 82 | an updated paragraph.","link":null},"annotations":{"bold":true,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"red_background"},"plain_text":"I''m 83 | an updated paragraph.","href":null}],"color":"default"},"request_id":"ecd74570-c63e-484b-ae45-1936a2e71fe8"}' 84 | headers: {} 85 | http_version: HTTP/1.1 86 | status_code: 200 87 | - request: 88 | body: '' 89 | headers: 90 | accept: 91 | - '*/*' 92 | accept-encoding: 93 | - gzip, deflate 94 | authorization: 95 | - ntn_... 96 | connection: 97 | - keep-alive 98 | host: 99 | - api.notion.com 100 | notion-version: 101 | - '2022-06-28' 102 | method: DELETE 103 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-819c-bf82-c8fa3a922688 104 | response: 105 | content: '{"object":"block","id":"16cabc1e-edcd-819c-bf82-c8fa3a922688","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81eb-856e-ffa0fc3f59b8"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 106 | an updated paragraph.","link":null},"annotations":{"bold":true,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"red_background"},"plain_text":"I''m 107 | an updated paragraph.","href":null}],"color":"default"},"request_id":"d732c189-c056-4793-8df8-7f91f4078e30"}' 108 | headers: {} 109 | http_version: HTTP/1.1 110 | status_code: 200 111 | - request: 112 | body: '' 113 | headers: 114 | accept: 115 | - '*/*' 116 | accept-encoding: 117 | - gzip, deflate 118 | authorization: 119 | - ntn_... 120 | connection: 121 | - keep-alive 122 | host: 123 | - api.notion.com 124 | notion-version: 125 | - '2022-06-28' 126 | method: DELETE 127 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81eb-856e-ffa0fc3f59b8 128 | response: 129 | content: '{"object":"block","id":"16cabc1e-edcd-81eb-856e-ffa0fc3f59b8","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 130 | 2024-12-30 18:21:09.273712"},"request_id":"a724ed7e-c23b-4eae-8db7-e4fae8f86382"}' 131 | headers: {} 132 | http_version: HTTP/1.1 133 | status_code: 200 134 | version: 1 135 | -------------------------------------------------------------------------------- /tests/cassettes/test_client_request.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/invalid 19 | response: 20 | content: '{"object":"error","status":400,"code":"invalid_request_url","message":"Invalid 21 | request URL."}' 22 | headers: {} 23 | http_version: HTTP/1.1 24 | status_code: 400 25 | - request: 26 | body: '' 27 | headers: 28 | accept: 29 | - '*/*' 30 | accept-encoding: 31 | - gzip, deflate 32 | authorization: 33 | - ntn_... 34 | connection: 35 | - keep-alive 36 | host: 37 | - api.notion.com 38 | notion-version: 39 | - '2022-06-28' 40 | method: GET 41 | uri: https://api.notion.com/v1/users 42 | response: 43 | content: '{"object":"list","results":[{"object":"user","id":"a4f789cc-7bc8-4cf0-82b9-a8ba7d985ecf","name":"Guillaume 44 | Gelin","avatar_url":"https://s3-us-west-2.amazonaws.com/public.notion-static.com/01d7053d-e135-4f27-bba0-5de532d39296/ramnes3.jpeg","type":"person","person":{"email":"notion@ramnes.eu"}},{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"}}],"next_cursor":null,"has_more":false,"type":"user","user":{},"request_id":"e72aaaf8-9502-4f4a-9292-10101b94ace1"}' 45 | headers: {} 46 | http_version: HTTP/1.1 47 | status_code: 200 48 | version: 1 49 | -------------------------------------------------------------------------------- /tests/cassettes/test_client_request_auth.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/users 19 | response: 20 | content: '{"object":"error","status":401,"code":"unauthorized","message":"API 21 | token is invalid.","request_id":"9c9434f5-86eb-4167-8cf5-c408de6733d0"}' 22 | headers: {} 23 | http_version: HTTP/1.1 24 | status_code: 401 25 | - request: 26 | body: '' 27 | headers: 28 | accept: 29 | - '*/*' 30 | accept-encoding: 31 | - gzip, deflate 32 | authorization: 33 | - ntn_... 34 | connection: 35 | - keep-alive 36 | host: 37 | - api.notion.com 38 | notion-version: 39 | - '2022-06-28' 40 | method: GET 41 | uri: https://api.notion.com/v1/users 42 | response: 43 | content: '{"object":"list","results":[{"object":"user","id":"a4f789cc-7bc8-4cf0-82b9-a8ba7d985ecf","name":"Guillaume 44 | Gelin","avatar_url":"https://s3-us-west-2.amazonaws.com/public.notion-static.com/01d7053d-e135-4f27-bba0-5de532d39296/ramnes3.jpeg","type":"person","person":{"email":"notion@ramnes.eu"}},{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"}}],"next_cursor":null,"has_more":false,"type":"user","user":{},"request_id":"5e567f48-0a8d-4db2-9855-a187eec5d575"}' 45 | headers: {} 46 | http_version: HTTP/1.1 47 | status_code: 200 48 | version: 1 49 | -------------------------------------------------------------------------------- /tests/cassettes/test_collect_paginated_api.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{}' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | content-length: 14 | - '2' 15 | content-type: 16 | - application/json 17 | host: 18 | - api.notion.com 19 | notion-version: 20 | - '2022-06-28' 21 | method: POST 22 | uri: https://api.notion.com/v1/search 23 | response: 24 | content: '{"object":"list","results":[{"object":"page","id":"95ba0116-6776-4c19-9e45-54e77415f03b","created_time":"2023-06-29T12:47:00.000Z","last_edited_time":"2024-12-30T17:22:00.000Z","created_by":{"object":"user","id":"a4f789cc-7bc8-4cf0-82b9-a8ba7d985ecf"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"workspace","workspace":true},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[]}},"url":"https://www.notion.so/95ba011667764c199e4554e77415f03b","public_url":null}],"next_cursor":null,"has_more":false,"type":"page_or_database","page_or_database":{},"request_id":"a0917d70-3b27-402d-97b7-5eb9303f2eb8"}' 25 | headers: {} 26 | http_version: HTTP/1.1 27 | status_code: 200 28 | - request: 29 | body: '{"query":"This should have no results"}' 30 | headers: 31 | accept: 32 | - '*/*' 33 | accept-encoding: 34 | - gzip, deflate 35 | authorization: 36 | - ntn_... 37 | connection: 38 | - keep-alive 39 | content-length: 40 | - '39' 41 | content-type: 42 | - application/json 43 | host: 44 | - api.notion.com 45 | notion-version: 46 | - '2022-06-28' 47 | method: POST 48 | uri: https://api.notion.com/v1/search 49 | response: 50 | content: '{"object":"list","results":[],"next_cursor":null,"has_more":false,"type":"page_or_database","page_or_database":{},"request_id":"d4e7ed22-fd2a-47f9-a916-91216b7390fd"}' 51 | headers: {} 52 | http_version: HTTP/1.1 53 | status_code: 200 54 | version: 1 55 | -------------------------------------------------------------------------------- /tests/cassettes/test_comments_create.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:43.147215"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8123-b0a1-c5f643612dc2","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:43.147215","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:43.147215","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-43-147215-16cabc1eedcd8123b0a1c5f643612dc2","public_url":null,"request_id":"8953c1af-e35d-4a34-af22-6cc1ff9a5b8f"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"page_id":"16cabc1e-edcd-8123-b0a1-c5f643612dc2"},"rich_text":[{"text":{"content":"This 33 | is a test comment."}}]}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '122' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/comments 53 | response: 54 | content: '{"object":"comment","id":"16cabc1e-edcd-812a-806c-001d15aa7aca","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8123-b0a1-c5f643612dc2"},"discussion_id":"16cabc1e-edcd-81f3-8b5f-001cd05eb826","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"rich_text":[{"type":"text","text":{"content":"This 55 | is a test comment.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"This 56 | is a test comment.","href":null}],"request_id":"5c0b6281-9391-4c15-b74d-dde643394811"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | host: 72 | - api.notion.com 73 | notion-version: 74 | - '2022-06-28' 75 | method: DELETE 76 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8123-b0a1-c5f643612dc2 77 | response: 78 | content: '{"object":"block","id":"16cabc1e-edcd-8123-b0a1-c5f643612dc2","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 79 | 2024-12-30 18:21:43.147215"},"request_id":"e02cf3da-49fb-48cb-b8dd-5801a0f9814c"}' 80 | headers: {} 81 | http_version: HTTP/1.1 82 | status_code: 200 83 | version: 1 84 | -------------------------------------------------------------------------------- /tests/cassettes/test_comments_list.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:45.397148"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8109-b3ab-e943a964defd","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:45.397148","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:45.397148","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-45-397148-16cabc1eedcd8109b3abe943a964defd","public_url":null,"request_id":"68adbea4-d217-48af-a57d-498284ea1bee"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"page_id":"16cabc1e-edcd-8109-b3ab-e943a964defd"},"rich_text":[{"text":{"content":"This 33 | is a test comment."}}]}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '122' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/comments 53 | response: 54 | content: '{"object":"comment","id":"16cabc1e-edcd-8112-9e53-001df5bcc68a","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8109-b3ab-e943a964defd"},"discussion_id":"16cabc1e-edcd-81a2-b080-001ca9f17ab9","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"rich_text":[{"type":"text","text":{"content":"This 55 | is a test comment.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"This 56 | is a test comment.","href":null}],"request_id":"0ac9e00e-9937-4625-8432-c08a86147590"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | host: 72 | - api.notion.com 73 | notion-version: 74 | - '2022-06-28' 75 | method: GET 76 | uri: https://api.notion.com/v1/comments?block_id=16cabc1e-edcd-8109-b3ab-e943a964defd 77 | response: 78 | content: '{"object":"list","results":[{"object":"comment","id":"16cabc1e-edcd-8112-9e53-001df5bcc68a","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8109-b3ab-e943a964defd"},"discussion_id":"16cabc1e-edcd-81a2-b080-001ca9f17ab9","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"rich_text":[{"type":"text","text":{"content":"This 79 | is a test comment.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"This 80 | is a test comment.","href":null}]}],"next_cursor":null,"has_more":false,"type":"comment","comment":{},"request_id":"5997a632-5012-4e96-b1e0-48997172379b"}' 81 | headers: {} 82 | http_version: HTTP/1.1 83 | status_code: 200 84 | - request: 85 | body: '' 86 | headers: 87 | accept: 88 | - '*/*' 89 | accept-encoding: 90 | - gzip, deflate 91 | authorization: 92 | - ntn_... 93 | connection: 94 | - keep-alive 95 | host: 96 | - api.notion.com 97 | notion-version: 98 | - '2022-06-28' 99 | method: DELETE 100 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8109-b3ab-e943a964defd 101 | response: 102 | content: '{"object":"block","id":"16cabc1e-edcd-8109-b3ab-e943a964defd","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 103 | 2024-12-30 18:21:45.397148"},"request_id":"83095cb6-8e35-4dc5-bde5-bb8b6df65594"}' 104 | headers: {} 105 | http_version: HTTP/1.1 106 | status_code: 200 107 | version: 1 108 | -------------------------------------------------------------------------------- /tests/cassettes/test_databases_create.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:23.128345"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8109-ac7a-fd0eeb5bf4c2","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:23.128345","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:23.128345","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-23-128345-16cabc1eedcd8109ac7afd0eeb5bf4c2","public_url":null,"request_id":"9416d61e-ef18-4117-9cca-482556492696"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"type":"page_id","page_id":"16cabc1e-edcd-8109-ac7a-fd0eeb5bf4c2"},"title":[{"type":"text","text":{"content":"Test 33 | Database"}}],"properties":{"Name":{"title":{}}}}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '174' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/databases 53 | response: 54 | content: '{"object":"database","id":"16cabc1e-edcd-819b-afa1-eac238462cdc","cover":null,"icon":null,"created_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_time":"2024-12-30T17:21:00.000Z","title":[{"type":"text","text":{"content":"Test 55 | Database","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 56 | Database","href":null}],"description":[],"is_inline":false,"properties":{"Name":{"id":"title","name":"Name","type":"title","title":{}}},"parent":{"type":"page_id","page_id":"16cabc1e-edcd-8109-ac7a-fd0eeb5bf4c2"},"url":"https://www.notion.so/16cabc1eedcd819bafa1eac238462cdc","public_url":null,"archived":false,"in_trash":false,"request_id":"3099beb9-0751-445d-a37c-9fdfd57f026e"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | host: 72 | - api.notion.com 73 | notion-version: 74 | - '2022-06-28' 75 | method: DELETE 76 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8109-ac7a-fd0eeb5bf4c2 77 | response: 78 | content: '{"object":"block","id":"16cabc1e-edcd-8109-ac7a-fd0eeb5bf4c2","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":true,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 79 | 2024-12-30 18:21:23.128345"},"request_id":"cfe91fed-3f82-4314-91da-377371fbf018"}' 80 | headers: {} 81 | http_version: HTTP/1.1 82 | status_code: 200 83 | version: 1 84 | -------------------------------------------------------------------------------- /tests/cassettes/test_databases_query.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:26.692175"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-811a-a03b-c3f770e7caa8","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:26.692175","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:26.692175","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-26-692175-16cabc1eedcd811aa03bc3f770e7caa8","public_url":null,"request_id":"abcce442-633d-422b-b026-0cb880c26320"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"type":"page_id","page_id":"16cabc1e-edcd-811a-a03b-c3f770e7caa8"},"title":[{"type":"text","text":{"content":"Test 33 | Database - 2024-12-30 18:21:27.425666"}}],"properties":{"Name":{"title":{}}}}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '203' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/databases 53 | response: 54 | content: '{"object":"database","id":"16cabc1e-edcd-8162-9ab8-c71fc1e7ee93","cover":null,"icon":null,"created_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_time":"2024-12-30T17:21:00.000Z","title":[{"type":"text","text":{"content":"Test 55 | Database - 2024-12-30 18:21:27.425666","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 56 | Database - 2024-12-30 18:21:27.425666","href":null}],"description":[],"is_inline":false,"properties":{"Name":{"id":"title","name":"Name","type":"title","title":{}}},"parent":{"type":"page_id","page_id":"16cabc1e-edcd-811a-a03b-c3f770e7caa8"},"url":"https://www.notion.so/16cabc1eedcd81629ab8c71fc1e7ee93","public_url":null,"archived":false,"in_trash":false,"request_id":"bccbcfd2-9d05-4ba8-ba8a-262399550bdc"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '{"filter":{"timestamp":"created_time","created_time":{"past_week":{}}}}' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | content-length: 72 | - '71' 73 | content-type: 74 | - application/json 75 | host: 76 | - api.notion.com 77 | notion-version: 78 | - '2022-06-28' 79 | method: POST 80 | uri: https://api.notion.com/v1/databases/16cabc1e-edcd-8162-9ab8-c71fc1e7ee93/query 81 | response: 82 | content: '{"object":"list","results":[],"next_cursor":null,"has_more":false,"type":"page_or_database","page_or_database":{},"request_id":"dcba77ed-76bf-4a9c-bbf0-9550f62551ce"}' 83 | headers: {} 84 | http_version: HTTP/1.1 85 | status_code: 200 86 | - request: 87 | body: '' 88 | headers: 89 | accept: 90 | - '*/*' 91 | accept-encoding: 92 | - gzip, deflate 93 | authorization: 94 | - ntn_... 95 | connection: 96 | - keep-alive 97 | host: 98 | - api.notion.com 99 | notion-version: 100 | - '2022-06-28' 101 | method: DELETE 102 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8162-9ab8-c71fc1e7ee93 103 | response: 104 | content: '{"object":"block","id":"16cabc1e-edcd-8162-9ab8-c71fc1e7ee93","parent":{"type":"page_id","page_id":"16cabc1e-edcd-811a-a03b-c3f770e7caa8"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_database","child_database":{"title":"Test 105 | Database - 2024-12-30 18:21:27.425666"},"request_id":"64f4c580-28ef-405b-b55d-bcfdd4221c3e"}' 106 | headers: {} 107 | http_version: HTTP/1.1 108 | status_code: 200 109 | - request: 110 | body: '' 111 | headers: 112 | accept: 113 | - '*/*' 114 | accept-encoding: 115 | - gzip, deflate 116 | authorization: 117 | - ntn_... 118 | connection: 119 | - keep-alive 120 | host: 121 | - api.notion.com 122 | notion-version: 123 | - '2022-06-28' 124 | method: DELETE 125 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-811a-a03b-c3f770e7caa8 126 | response: 127 | content: '{"object":"block","id":"16cabc1e-edcd-811a-a03b-c3f770e7caa8","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 128 | 2024-12-30 18:21:26.692175"},"request_id":"7799db9c-32ba-438e-9a45-fe3626dd7a30"}' 129 | headers: {} 130 | http_version: HTTP/1.1 131 | status_code: 200 132 | version: 1 133 | -------------------------------------------------------------------------------- /tests/cassettes/test_databases_retrieve.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:29.524316"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8130-87d8-d12cecc2579e","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:29.524316","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:29.524316","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-29-524316-16cabc1eedcd813087d8d12cecc2579e","public_url":null,"request_id":"771b2d68-988a-40cd-8c16-8fd3a96adac1"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"type":"page_id","page_id":"16cabc1e-edcd-8130-87d8-d12cecc2579e"},"title":[{"type":"text","text":{"content":"Test 33 | Database - 2024-12-30 18:21:30.072949"}}],"properties":{"Name":{"title":{}}}}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '203' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/databases 53 | response: 54 | content: '{"object":"database","id":"16cabc1e-edcd-8157-b05e-e76668756101","cover":null,"icon":null,"created_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_time":"2024-12-30T17:21:00.000Z","title":[{"type":"text","text":{"content":"Test 55 | Database - 2024-12-30 18:21:30.072949","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 56 | Database - 2024-12-30 18:21:30.072949","href":null}],"description":[],"is_inline":false,"properties":{"Name":{"id":"title","name":"Name","type":"title","title":{}}},"parent":{"type":"page_id","page_id":"16cabc1e-edcd-8130-87d8-d12cecc2579e"},"url":"https://www.notion.so/16cabc1eedcd8157b05ee76668756101","public_url":null,"archived":false,"in_trash":false,"request_id":"03b2c822-5251-4c25-b715-1981969fbe53"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | host: 72 | - api.notion.com 73 | notion-version: 74 | - '2022-06-28' 75 | method: GET 76 | uri: https://api.notion.com/v1/databases/16cabc1e-edcd-8157-b05e-e76668756101 77 | response: 78 | content: '{"object":"database","id":"16cabc1e-edcd-8157-b05e-e76668756101","cover":null,"icon":null,"created_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_time":"2024-12-30T17:21:00.000Z","title":[{"type":"text","text":{"content":"Test 79 | Database - 2024-12-30 18:21:30.072949","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 80 | Database - 2024-12-30 18:21:30.072949","href":null}],"description":[],"is_inline":false,"properties":{"Name":{"id":"title","name":"Name","type":"title","title":{}}},"parent":{"type":"page_id","page_id":"16cabc1e-edcd-8130-87d8-d12cecc2579e"},"url":"https://www.notion.so/16cabc1eedcd8157b05ee76668756101","public_url":null,"archived":false,"in_trash":false,"request_id":"8f83aab3-a0af-436b-9261-26273e6160bf"}' 81 | headers: {} 82 | http_version: HTTP/1.1 83 | status_code: 200 84 | - request: 85 | body: '' 86 | headers: 87 | accept: 88 | - '*/*' 89 | accept-encoding: 90 | - gzip, deflate 91 | authorization: 92 | - ntn_... 93 | connection: 94 | - keep-alive 95 | host: 96 | - api.notion.com 97 | notion-version: 98 | - '2022-06-28' 99 | method: DELETE 100 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8157-b05e-e76668756101 101 | response: 102 | content: '{"object":"block","id":"16cabc1e-edcd-8157-b05e-e76668756101","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8130-87d8-d12cecc2579e"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_database","child_database":{"title":"Test 103 | Database - 2024-12-30 18:21:30.072949"},"request_id":"1d45191a-b46f-4b02-bb3e-2313b47d2508"}' 104 | headers: {} 105 | http_version: HTTP/1.1 106 | status_code: 200 107 | - request: 108 | body: '' 109 | headers: 110 | accept: 111 | - '*/*' 112 | accept-encoding: 113 | - gzip, deflate 114 | authorization: 115 | - ntn_... 116 | connection: 117 | - keep-alive 118 | host: 119 | - api.notion.com 120 | notion-version: 121 | - '2022-06-28' 122 | method: DELETE 123 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8130-87d8-d12cecc2579e 124 | response: 125 | content: '{"object":"block","id":"16cabc1e-edcd-8130-87d8-d12cecc2579e","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 126 | 2024-12-30 18:21:29.524316"},"request_id":"b3123a16-856b-408b-9c27-3ba9674ae711"}' 127 | headers: {} 128 | http_version: HTTP/1.1 129 | status_code: 200 130 | version: 1 131 | -------------------------------------------------------------------------------- /tests/cassettes/test_databases_update.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:36.964085"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-815e-91d2-dab5bc6ec4b1","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:36.964085","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:36.964085","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-36-964085-16cabc1eedcd815e91d2dab5bc6ec4b1","public_url":null,"request_id":"9d1c732d-a9b5-4f62-ba07-9b1e846bb657"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"type":"page_id","page_id":"16cabc1e-edcd-815e-91d2-dab5bc6ec4b1"},"title":[{"type":"text","text":{"content":"Test 33 | Database - 2024-12-30 18:21:37.493268"}}],"properties":{"Name":{"title":{}}}}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '203' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/databases 53 | response: 54 | content: '{"object":"database","id":"16cabc1e-edcd-8129-ad77-daf033646084","cover":null,"icon":null,"created_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_time":"2024-12-30T17:21:00.000Z","title":[{"type":"text","text":{"content":"Test 55 | Database - 2024-12-30 18:21:37.493268","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 56 | Database - 2024-12-30 18:21:37.493268","href":null}],"description":[],"is_inline":false,"properties":{"Name":{"id":"title","name":"Name","type":"title","title":{}}},"parent":{"type":"page_id","page_id":"16cabc1e-edcd-815e-91d2-dab5bc6ec4b1"},"url":"https://www.notion.so/16cabc1eedcd8129ad77daf033646084","public_url":null,"archived":false,"in_trash":false,"request_id":"09cabc28-2d6e-4b1d-93c6-99e6e7fc883c"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: "{\"icon\":{\"type\":\"emoji\",\"emoji\":\"\U0001F525\"}}" 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | content-length: 72 | - '40' 73 | content-type: 74 | - application/json 75 | host: 76 | - api.notion.com 77 | notion-version: 78 | - '2022-06-28' 79 | method: PATCH 80 | uri: https://api.notion.com/v1/databases/16cabc1e-edcd-8129-ad77-daf033646084 81 | response: 82 | content: "{\"object\":\"database\",\"id\":\"16cabc1e-edcd-8129-ad77-daf033646084\",\"cover\":null,\"icon\":{\"type\":\"emoji\",\"emoji\":\"\U0001F525\"},\"created_time\":\"2024-12-30T17:21:00.000Z\",\"created_by\":{\"object\":\"user\",\"id\":\"7775f3a3-893f-43fa-b625-460c61094c78\"},\"last_edited_by\":{\"object\":\"user\",\"id\":\"7775f3a3-893f-43fa-b625-460c61094c78\"},\"last_edited_time\":\"2024-12-30T17:21:00.000Z\",\"title\":[{\"type\":\"text\",\"text\":{\"content\":\"Test 83 | Database - 2024-12-30 18:21:37.493268\",\"link\":null},\"annotations\":{\"bold\":false,\"italic\":false,\"strikethrough\":false,\"underline\":false,\"code\":false,\"color\":\"default\"},\"plain_text\":\"Test 84 | Database - 2024-12-30 18:21:37.493268\",\"href\":null}],\"description\":[],\"is_inline\":false,\"properties\":{\"Name\":{\"id\":\"title\",\"name\":\"Name\",\"type\":\"title\",\"title\":{}}},\"parent\":{\"type\":\"page_id\",\"page_id\":\"16cabc1e-edcd-815e-91d2-dab5bc6ec4b1\"},\"url\":\"https://www.notion.so/16cabc1eedcd8129ad77daf033646084\",\"public_url\":null,\"archived\":false,\"in_trash\":false,\"request_id\":\"cbba3e13-4066-4b36-8dd2-638388fd442b\"}" 85 | headers: {} 86 | http_version: HTTP/1.1 87 | status_code: 200 88 | - request: 89 | body: '' 90 | headers: 91 | accept: 92 | - '*/*' 93 | accept-encoding: 94 | - gzip, deflate 95 | authorization: 96 | - ntn_... 97 | connection: 98 | - keep-alive 99 | host: 100 | - api.notion.com 101 | notion-version: 102 | - '2022-06-28' 103 | method: DELETE 104 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8129-ad77-daf033646084 105 | response: 106 | content: '{"object":"block","id":"16cabc1e-edcd-8129-ad77-daf033646084","parent":{"type":"page_id","page_id":"16cabc1e-edcd-815e-91d2-dab5bc6ec4b1"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_database","child_database":{"title":"Test 107 | Database - 2024-12-30 18:21:37.493268"},"request_id":"ed70e3f3-dd4c-413b-b5e1-710a1040870f"}' 108 | headers: {} 109 | http_version: HTTP/1.1 110 | status_code: 200 111 | - request: 112 | body: '' 113 | headers: 114 | accept: 115 | - '*/*' 116 | accept-encoding: 117 | - gzip, deflate 118 | authorization: 119 | - ntn_... 120 | connection: 121 | - keep-alive 122 | host: 123 | - api.notion.com 124 | notion-version: 125 | - '2022-06-28' 126 | method: DELETE 127 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-815e-91d2-dab5bc6ec4b1 128 | response: 129 | content: '{"object":"block","id":"16cabc1e-edcd-815e-91d2-dab5bc6ec4b1","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 130 | 2024-12-30 18:21:36.964085"},"request_id":"a3702f78-b773-48e1-a046-331f0022e186"}' 131 | headers: {} 132 | http_version: HTTP/1.1 133 | status_code: 200 134 | version: 1 135 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_equation_rich_text_item_response.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:24:03.374679"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8192-a856-eb5cd59e9f21","created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:24:03.374679","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:24:03.374679","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-24-03-374679-16cabc1eedcd8192a856eb5cd59e9f21","public_url":null,"request_id":"d479d4df-33b7-4bb2-ac92-77d52fd71004"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"children":[{"paragraph":{"rich_text":[{"equation":{"expression":"E = 33 | mc^2"}}]}}]}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '83' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: PATCH 52 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8192-a856-eb5cd59e9f21/children 53 | response: 54 | content: '{"object":"list","results":[{"object":"block","id":"16cabc1e-edcd-8116-adb6-d3d167fb3399","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8192-a856-eb5cd59e9f21"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"equation","equation":{"expression":"E 55 | = mc^2"},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"E 56 | = mc^2","href":null}],"color":"default"}}],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"f36d4d70-bd33-4afc-b3f8-0878adba86b0"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | host: 72 | - api.notion.com 73 | notion-version: 74 | - '2022-06-28' 75 | method: GET 76 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8116-adb6-d3d167fb3399 77 | response: 78 | content: '{"object":"block","id":"16cabc1e-edcd-8116-adb6-d3d167fb3399","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8192-a856-eb5cd59e9f21"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"equation","equation":{"expression":"E 79 | = mc^2"},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"E 80 | = mc^2","href":null}],"color":"default"},"request_id":"1be570d0-2ae7-4234-8052-24215d0bfcc2"}' 81 | headers: {} 82 | http_version: HTTP/1.1 83 | status_code: 200 84 | - request: 85 | body: '' 86 | headers: 87 | accept: 88 | - '*/*' 89 | accept-encoding: 90 | - gzip, deflate 91 | authorization: 92 | - ntn_... 93 | connection: 94 | - keep-alive 95 | host: 96 | - api.notion.com 97 | notion-version: 98 | - '2022-06-28' 99 | method: DELETE 100 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8116-adb6-d3d167fb3399 101 | response: 102 | content: '{"object":"block","id":"16cabc1e-edcd-8116-adb6-d3d167fb3399","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8192-a856-eb5cd59e9f21"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"paragraph","paragraph":{"rich_text":[{"type":"equation","equation":{"expression":"E 103 | = mc^2"},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"E 104 | = mc^2","href":null}],"color":"default"},"request_id":"67110801-12bf-4a95-a6ae-0737e7582dea"}' 105 | headers: {} 106 | http_version: HTTP/1.1 107 | status_code: 200 108 | - request: 109 | body: '' 110 | headers: 111 | accept: 112 | - '*/*' 113 | accept-encoding: 114 | - gzip, deflate 115 | authorization: 116 | - ntn_... 117 | connection: 118 | - keep-alive 119 | host: 120 | - api.notion.com 121 | notion-version: 122 | - '2022-06-28' 123 | method: DELETE 124 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8192-a856-eb5cd59e9f21 125 | response: 126 | content: '{"object":"block","id":"16cabc1e-edcd-8192-a856-eb5cd59e9f21","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 127 | 2024-12-30 18:24:03.374679"},"request_id":"b4a1df01-b919-44bc-9b16-790aaf1e99a3"}' 128 | headers: {} 129 | http_version: HTTP/1.1 130 | status_code: 200 131 | version: 1 132 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_full_block.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:23:38.665176"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8165-9f0b-ed678bda0d68","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:23:38.665176","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:23:38.665176","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-23-38-665176-16cabc1eedcd81659f0bed678bda0d68","public_url":null,"request_id":"ed76baad-a274-442d-93c7-ae86049c97d4"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"children":[{"paragraph":{"rich_text":[{"text":{"content":"I''m a paragraph."}}]}}]}' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '84' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: PATCH 51 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8165-9f0b-ed678bda0d68/children 52 | response: 53 | content: '{"object":"list","results":[{"object":"block","id":"16cabc1e-edcd-81c8-8309-f5b7b460eed1","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8165-9f0b-ed678bda0d68"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 54 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 55 | a paragraph.","href":null}],"color":"default"}}],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"81b462a0-ae3d-48d4-bc20-29587967cf4a"}' 56 | headers: {} 57 | http_version: HTTP/1.1 58 | status_code: 200 59 | - request: 60 | body: '' 61 | headers: 62 | accept: 63 | - '*/*' 64 | accept-encoding: 65 | - gzip, deflate 66 | authorization: 67 | - ntn_... 68 | connection: 69 | - keep-alive 70 | host: 71 | - api.notion.com 72 | notion-version: 73 | - '2022-06-28' 74 | method: GET 75 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81c8-8309-f5b7b460eed1 76 | response: 77 | content: '{"object":"block","id":"16cabc1e-edcd-81c8-8309-f5b7b460eed1","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8165-9f0b-ed678bda0d68"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 78 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 79 | a paragraph.","href":null}],"color":"default"},"request_id":"7f21ca93-a9dd-4978-a558-4a46dd4d118f"}' 80 | headers: {} 81 | http_version: HTTP/1.1 82 | status_code: 200 83 | - request: 84 | body: '' 85 | headers: 86 | accept: 87 | - '*/*' 88 | accept-encoding: 89 | - gzip, deflate 90 | authorization: 91 | - ntn_... 92 | connection: 93 | - keep-alive 94 | host: 95 | - api.notion.com 96 | notion-version: 97 | - '2022-06-28' 98 | method: DELETE 99 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81c8-8309-f5b7b460eed1 100 | response: 101 | content: '{"object":"block","id":"16cabc1e-edcd-81c8-8309-f5b7b460eed1","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8165-9f0b-ed678bda0d68"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 102 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 103 | a paragraph.","href":null}],"color":"default"},"request_id":"72c3e9a8-d231-418a-8b92-bde2335a3198"}' 104 | headers: {} 105 | http_version: HTTP/1.1 106 | status_code: 200 107 | - request: 108 | body: '' 109 | headers: 110 | accept: 111 | - '*/*' 112 | accept-encoding: 113 | - gzip, deflate 114 | authorization: 115 | - ntn_... 116 | connection: 117 | - keep-alive 118 | host: 119 | - api.notion.com 120 | notion-version: 121 | - '2022-06-28' 122 | method: DELETE 123 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8165-9f0b-ed678bda0d68 124 | response: 125 | content: '{"object":"block","id":"16cabc1e-edcd-8165-9f0b-ed678bda0d68","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 126 | 2024-12-30 18:23:38.665176"},"request_id":"5032be34-3e3e-43ff-8123-c88e9b14d9b0"}' 127 | headers: {} 128 | http_version: HTTP/1.1 129 | status_code: 200 130 | version: 1 131 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_full_comment.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:23:54.022858"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-815b-bb7e-e1a3010bdf89","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:23:54.022858","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:23:54.022858","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-23-54-022858-16cabc1eedcd815bbb7ee1a3010bdf89","public_url":null,"request_id":"58260764-e29e-4b04-8ce5-064aa7baabbd"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"page_id":"16cabc1e-edcd-815b-bb7e-e1a3010bdf89"},"rich_text":[{"text":{"content":"This 33 | is a test comment."}}]}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '122' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/comments 53 | response: 54 | content: '{"object":"comment","id":"16cabc1e-edcd-81c7-a099-001d7bf827a5","parent":{"type":"page_id","page_id":"16cabc1e-edcd-815b-bb7e-e1a3010bdf89"},"discussion_id":"16cabc1e-edcd-81a7-81cc-001c43928b26","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"rich_text":[{"type":"text","text":{"content":"This 55 | is a test comment.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"This 56 | is a test comment.","href":null}],"request_id":"3e242e40-755a-44df-b830-eb7f5f6b27a0"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | host: 72 | - api.notion.com 73 | notion-version: 74 | - '2022-06-28' 75 | method: GET 76 | uri: https://api.notion.com/v1/comments?block_id=16cabc1e-edcd-815b-bb7e-e1a3010bdf89 77 | response: 78 | content: '{"object":"list","results":[{"object":"comment","id":"16cabc1e-edcd-81c7-a099-001d7bf827a5","parent":{"type":"page_id","page_id":"16cabc1e-edcd-815b-bb7e-e1a3010bdf89"},"discussion_id":"16cabc1e-edcd-81a7-81cc-001c43928b26","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"rich_text":[{"type":"text","text":{"content":"This 79 | is a test comment.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"This 80 | is a test comment.","href":null}]}],"next_cursor":null,"has_more":false,"type":"comment","comment":{},"request_id":"d94008dc-c7b3-454a-89f4-a4cc6fbcefbd"}' 81 | headers: {} 82 | http_version: HTTP/1.1 83 | status_code: 200 84 | - request: 85 | body: '' 86 | headers: 87 | accept: 88 | - '*/*' 89 | accept-encoding: 90 | - gzip, deflate 91 | authorization: 92 | - ntn_... 93 | connection: 94 | - keep-alive 95 | host: 96 | - api.notion.com 97 | notion-version: 98 | - '2022-06-28' 99 | method: DELETE 100 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-815b-bb7e-e1a3010bdf89 101 | response: 102 | content: '{"object":"block","id":"16cabc1e-edcd-815b-bb7e-e1a3010bdf89","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 103 | 2024-12-30 18:23:54.022858"},"request_id":"7aa1c17f-e1ec-42d1-9aee-be28a765e9d1"}' 104 | headers: {} 105 | http_version: HTTP/1.1 106 | status_code: 200 107 | version: 1 108 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_full_database.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:23:43.701008"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-810e-9417-cef234a6173a","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:23:43.701008","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:23:43.701008","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-23-43-701008-16cabc1eedcd810e9417cef234a6173a","public_url":null,"request_id":"f21904f9-fce3-4950-b65a-b729be72de99"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"parent":{"type":"page_id","page_id":"16cabc1e-edcd-810e-9417-cef234a6173a"},"title":[{"type":"text","text":{"content":"Test 33 | Database - 2024-12-30 18:23:46.766904"}}],"properties":{"Name":{"title":{}}}}' 34 | headers: 35 | accept: 36 | - '*/*' 37 | accept-encoding: 38 | - gzip, deflate 39 | authorization: 40 | - ntn_... 41 | connection: 42 | - keep-alive 43 | content-length: 44 | - '203' 45 | content-type: 46 | - application/json 47 | host: 48 | - api.notion.com 49 | notion-version: 50 | - '2022-06-28' 51 | method: POST 52 | uri: https://api.notion.com/v1/databases 53 | response: 54 | content: '{"object":"database","id":"16cabc1e-edcd-8192-8dd5-ce6b898d8711","cover":null,"icon":null,"created_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_time":"2024-12-30T17:23:00.000Z","title":[{"type":"text","text":{"content":"Test 55 | Database - 2024-12-30 18:23:46.766904","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 56 | Database - 2024-12-30 18:23:46.766904","href":null}],"description":[],"is_inline":false,"properties":{"Name":{"id":"title","name":"Name","type":"title","title":{}}},"parent":{"type":"page_id","page_id":"16cabc1e-edcd-810e-9417-cef234a6173a"},"url":"https://www.notion.so/16cabc1eedcd81928dd5ce6b898d8711","public_url":null,"archived":false,"in_trash":false,"request_id":"b3bee047-ba28-47b3-94e9-457ce9bc1f7a"}' 57 | headers: {} 58 | http_version: HTTP/1.1 59 | status_code: 200 60 | - request: 61 | body: '' 62 | headers: 63 | accept: 64 | - '*/*' 65 | accept-encoding: 66 | - gzip, deflate 67 | authorization: 68 | - ntn_... 69 | connection: 70 | - keep-alive 71 | host: 72 | - api.notion.com 73 | notion-version: 74 | - '2022-06-28' 75 | method: GET 76 | uri: https://api.notion.com/v1/databases/16cabc1e-edcd-8192-8dd5-ce6b898d8711 77 | response: 78 | content: '{"object":"database","id":"16cabc1e-edcd-8192-8dd5-ce6b898d8711","cover":null,"icon":null,"created_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_time":"2024-12-30T17:23:00.000Z","title":[{"type":"text","text":{"content":"Test 79 | Database - 2024-12-30 18:23:46.766904","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 80 | Database - 2024-12-30 18:23:46.766904","href":null}],"description":[],"is_inline":false,"properties":{"Name":{"id":"title","name":"Name","type":"title","title":{}}},"parent":{"type":"page_id","page_id":"16cabc1e-edcd-810e-9417-cef234a6173a"},"url":"https://www.notion.so/16cabc1eedcd81928dd5ce6b898d8711","public_url":null,"archived":false,"in_trash":false,"request_id":"384d6a42-c75a-4b9c-b307-249e6a78e3ea"}' 81 | headers: {} 82 | http_version: HTTP/1.1 83 | status_code: 200 84 | - request: 85 | body: '' 86 | headers: 87 | accept: 88 | - '*/*' 89 | accept-encoding: 90 | - gzip, deflate 91 | authorization: 92 | - ntn_... 93 | connection: 94 | - keep-alive 95 | host: 96 | - api.notion.com 97 | notion-version: 98 | - '2022-06-28' 99 | method: DELETE 100 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8192-8dd5-ce6b898d8711 101 | response: 102 | content: '{"object":"block","id":"16cabc1e-edcd-8192-8dd5-ce6b898d8711","parent":{"type":"page_id","page_id":"16cabc1e-edcd-810e-9417-cef234a6173a"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_database","child_database":{"title":"Test 103 | Database - 2024-12-30 18:23:46.766904"},"request_id":"d5bd5b3c-1100-4c3f-9007-03b55199e1da"}' 104 | headers: {} 105 | http_version: HTTP/1.1 106 | status_code: 200 107 | - request: 108 | body: '' 109 | headers: 110 | accept: 111 | - '*/*' 112 | accept-encoding: 113 | - gzip, deflate 114 | authorization: 115 | - ntn_... 116 | connection: 117 | - keep-alive 118 | host: 119 | - api.notion.com 120 | notion-version: 121 | - '2022-06-28' 122 | method: DELETE 123 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-810e-9417-cef234a6173a 124 | response: 125 | content: '{"object":"block","id":"16cabc1e-edcd-810e-9417-cef234a6173a","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 126 | 2024-12-30 18:23:43.701008"},"request_id":"df8591db-983a-4650-a072-76b2328c4d65"}' 127 | headers: {} 128 | http_version: HTTP/1.1 129 | status_code: 200 130 | version: 1 131 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_full_page.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:23:41.737250"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8174-a5ee-dad54c04d466","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:23:41.737250","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:23:41.737250","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-23-41-737250-16cabc1eedcd8174a5eedad54c04d466","public_url":null,"request_id":"efe685ca-8350-4eb9-9af1-99970d4ae4f0"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | host: 43 | - api.notion.com 44 | notion-version: 45 | - '2022-06-28' 46 | method: GET 47 | uri: https://api.notion.com/v1/pages/16cabc1e-edcd-8174-a5ee-dad54c04d466 48 | response: 49 | content: '{"object":"page","id":"16cabc1e-edcd-8174-a5ee-dad54c04d466","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 50 | 2024-12-30 18:23:41.737250","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 51 | 2024-12-30 18:23:41.737250","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-23-41-737250-16cabc1eedcd8174a5eedad54c04d466","public_url":null,"request_id":"7e261df7-d0f3-4f1d-aba7-5fe14c0c7f66"}' 52 | headers: {} 53 | http_version: HTTP/1.1 54 | status_code: 200 55 | - request: 56 | body: '' 57 | headers: 58 | accept: 59 | - '*/*' 60 | accept-encoding: 61 | - gzip, deflate 62 | authorization: 63 | - ntn_... 64 | connection: 65 | - keep-alive 66 | host: 67 | - api.notion.com 68 | notion-version: 69 | - '2022-06-28' 70 | method: DELETE 71 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8174-a5ee-dad54c04d466 72 | response: 73 | content: '{"object":"block","id":"16cabc1e-edcd-8174-a5ee-dad54c04d466","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 74 | 2024-12-30 18:23:41.737250"},"request_id":"e49011bc-a0cf-4676-a002-aa4f49dac6ee"}' 75 | headers: {} 76 | http_version: HTTP/1.1 77 | status_code: 200 78 | version: 1 79 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_full_user.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/users/me 19 | response: 20 | content: '{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"},"request_id":"d94e8bae-6467-48ba-b3b1-06fb16f641d4"}' 21 | headers: {} 22 | http_version: HTTP/1.1 23 | status_code: 200 24 | version: 1 25 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_mention_rich_text_item_response.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:24:08.033615"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8120-b0a5-e7b7268892ac","created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:24:08.033615","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:24:08.033615","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-24-08-033615-16cabc1eedcd8120b0a5e7b7268892ac","public_url":null,"request_id":"83910e90-ddf4-4819-b669-d09a4c252e56"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"children":[{"paragraph":{"rich_text":[{"mention":{"type":"date","date":{"start":"2022-12-16","end":null}}}]}}]}' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '113' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: PATCH 51 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8120-b0a5-e7b7268892ac/children 52 | response: 53 | content: '{"object":"list","results":[{"object":"block","id":"16cabc1e-edcd-815e-b1d2-c2e09c9eb547","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8120-b0a5-e7b7268892ac"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"mention","mention":{"type":"date","date":{"start":"2022-12-16","end":null,"time_zone":null}},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"2022-12-16","href":null}],"color":"default"}}],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"5f991c2c-9212-4d06-96f6-0b02f67e3b1c"}' 54 | headers: {} 55 | http_version: HTTP/1.1 56 | status_code: 200 57 | - request: 58 | body: '' 59 | headers: 60 | accept: 61 | - '*/*' 62 | accept-encoding: 63 | - gzip, deflate 64 | authorization: 65 | - ntn_... 66 | connection: 67 | - keep-alive 68 | host: 69 | - api.notion.com 70 | notion-version: 71 | - '2022-06-28' 72 | method: GET 73 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-815e-b1d2-c2e09c9eb547 74 | response: 75 | content: '{"object":"block","id":"16cabc1e-edcd-815e-b1d2-c2e09c9eb547","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8120-b0a5-e7b7268892ac"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"mention","mention":{"type":"date","date":{"start":"2022-12-16","end":null,"time_zone":null}},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"2022-12-16","href":null}],"color":"default"},"request_id":"b2647b87-d84b-4350-91f6-b8ead8637ac8"}' 76 | headers: {} 77 | http_version: HTTP/1.1 78 | status_code: 200 79 | - request: 80 | body: '' 81 | headers: 82 | accept: 83 | - '*/*' 84 | accept-encoding: 85 | - gzip, deflate 86 | authorization: 87 | - ntn_... 88 | connection: 89 | - keep-alive 90 | host: 91 | - api.notion.com 92 | notion-version: 93 | - '2022-06-28' 94 | method: DELETE 95 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-815e-b1d2-c2e09c9eb547 96 | response: 97 | content: '{"object":"block","id":"16cabc1e-edcd-815e-b1d2-c2e09c9eb547","parent":{"type":"page_id","page_id":"16cabc1e-edcd-8120-b0a5-e7b7268892ac"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"paragraph","paragraph":{"rich_text":[{"type":"mention","mention":{"type":"date","date":{"start":"2022-12-16","end":null,"time_zone":null}},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"2022-12-16","href":null}],"color":"default"},"request_id":"26e388db-a45f-41bf-8143-df2e76fac1d9"}' 98 | headers: {} 99 | http_version: HTTP/1.1 100 | status_code: 200 101 | - request: 102 | body: '' 103 | headers: 104 | accept: 105 | - '*/*' 106 | accept-encoding: 107 | - gzip, deflate 108 | authorization: 109 | - ntn_... 110 | connection: 111 | - keep-alive 112 | host: 113 | - api.notion.com 114 | notion-version: 115 | - '2022-06-28' 116 | method: DELETE 117 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8120-b0a5-e7b7268892ac 118 | response: 119 | content: '{"object":"block","id":"16cabc1e-edcd-8120-b0a5-e7b7268892ac","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 120 | 2024-12-30 18:24:08.033615"},"request_id":"ba9810a2-d3d3-402c-ba74-8641e57112c7"}' 121 | headers: {} 122 | http_version: HTTP/1.1 123 | status_code: 200 124 | version: 1 125 | -------------------------------------------------------------------------------- /tests/cassettes/test_is_text_rich_text_item_response.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:23:59.187890"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-81c7-8e8d-eef8e47e03c9","created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:23:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:23:59.187890","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:23:59.187890","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-23-59-187890-16cabc1eedcd81c78e8deef8e47e03c9","public_url":null,"request_id":"fee61046-716a-4220-b77e-996135a3dd9b"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"children":[{"paragraph":{"rich_text":[{"text":{"content":"I''m a paragraph."}}]}}]}' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '84' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: PATCH 51 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81c7-8e8d-eef8e47e03c9/children 52 | response: 53 | content: '{"object":"list","results":[{"object":"block","id":"16cabc1e-edcd-818d-9e25-dc930735797f","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81c7-8e8d-eef8e47e03c9"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 54 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 55 | a paragraph.","href":null}],"color":"default"}}],"next_cursor":null,"has_more":false,"type":"block","block":{},"request_id":"d1710408-91b4-4643-86d2-8a60a4267aee"}' 56 | headers: {} 57 | http_version: HTTP/1.1 58 | status_code: 200 59 | - request: 60 | body: '' 61 | headers: 62 | accept: 63 | - '*/*' 64 | accept-encoding: 65 | - gzip, deflate 66 | authorization: 67 | - ntn_... 68 | connection: 69 | - keep-alive 70 | host: 71 | - api.notion.com 72 | notion-version: 73 | - '2022-06-28' 74 | method: GET 75 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-818d-9e25-dc930735797f 76 | response: 77 | content: '{"object":"block","id":"16cabc1e-edcd-818d-9e25-dc930735797f","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81c7-8e8d-eef8e47e03c9"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":false,"in_trash":false,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 78 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 79 | a paragraph.","href":null}],"color":"default"},"request_id":"3772fc51-0bc2-4844-8e88-c8e5920077fd"}' 80 | headers: {} 81 | http_version: HTTP/1.1 82 | status_code: 200 83 | - request: 84 | body: '' 85 | headers: 86 | accept: 87 | - '*/*' 88 | accept-encoding: 89 | - gzip, deflate 90 | authorization: 91 | - ntn_... 92 | connection: 93 | - keep-alive 94 | host: 95 | - api.notion.com 96 | notion-version: 97 | - '2022-06-28' 98 | method: DELETE 99 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-818d-9e25-dc930735797f 100 | response: 101 | content: '{"object":"block","id":"16cabc1e-edcd-818d-9e25-dc930735797f","parent":{"type":"page_id","page_id":"16cabc1e-edcd-81c7-8e8d-eef8e47e03c9"},"created_time":"2024-12-30T17:24:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":"I''m 102 | a paragraph.","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"I''m 103 | a paragraph.","href":null}],"color":"default"},"request_id":"a57d2c98-171b-48e6-819d-e736685c5796"}' 104 | headers: {} 105 | http_version: HTTP/1.1 106 | status_code: 200 107 | - request: 108 | body: '' 109 | headers: 110 | accept: 111 | - '*/*' 112 | accept-encoding: 113 | - gzip, deflate 114 | authorization: 115 | - ntn_... 116 | connection: 117 | - keep-alive 118 | host: 119 | - api.notion.com 120 | notion-version: 121 | - '2022-06-28' 122 | method: DELETE 123 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81c7-8e8d-eef8e47e03c9 124 | response: 125 | content: '{"object":"block","id":"16cabc1e-edcd-81c7-8e8d-eef8e47e03c9","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:23:00.000Z","last_edited_time":"2024-12-30T17:24:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 126 | 2024-12-30 18:23:59.187890"},"request_id":"fcaac361-5550-462c-a6c9-72f60c8c0188"}' 127 | headers: {} 128 | http_version: HTTP/1.1 129 | status_code: 200 130 | version: 1 131 | -------------------------------------------------------------------------------- /tests/cassettes/test_pages_create.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | Page"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '129' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-81bc-8793-d436d9d768e6","created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | Page","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | Page","href":null}]}},"url":"https://www.notion.so/Test-Page-16cabc1eedcd81bc8793d436d9d768e6","public_url":null,"request_id":"9814c634-9f0c-49d9-881d-fab29b76d615"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | host: 43 | - api.notion.com 44 | notion-version: 45 | - '2022-06-28' 46 | method: DELETE 47 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81bc-8793-d436d9d768e6 48 | response: 49 | content: '{"object":"block","id":"16cabc1e-edcd-81bc-8793-d436d9d768e6","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 50 | Page"},"request_id":"854f71ec-cc14-46f7-bae5-a2461f78fe84"}' 51 | headers: {} 52 | http_version: HTTP/1.1 53 | status_code: 200 54 | version: 1 55 | -------------------------------------------------------------------------------- /tests/cassettes/test_pages_delete.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:48.938313"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-818e-a44e-d725243e4167","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:48.938313","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:48.938313","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-48-938313-16cabc1eedcd818ea44ed725243e4167","public_url":null,"request_id":"3ffa00e7-65dd-4e38-b55e-7cbaedda702d"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | host: 43 | - api.notion.com 44 | notion-version: 45 | - '2022-06-28' 46 | method: DELETE 47 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-818e-a44e-d725243e4167 48 | response: 49 | content: '{"object":"block","id":"16cabc1e-edcd-818e-a44e-d725243e4167","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 50 | 2024-12-30 18:21:48.938313"},"request_id":"d8b429ed-b9f8-4044-a152-a5d8c24c9401"}' 51 | headers: {} 52 | http_version: HTTP/1.1 53 | status_code: 200 54 | - request: 55 | body: '{"archived":false}' 56 | headers: 57 | accept: 58 | - '*/*' 59 | accept-encoding: 60 | - gzip, deflate 61 | authorization: 62 | - ntn_... 63 | connection: 64 | - keep-alive 65 | content-length: 66 | - '18' 67 | content-type: 68 | - application/json 69 | host: 70 | - api.notion.com 71 | notion-version: 72 | - '2022-06-28' 73 | method: PATCH 74 | uri: https://api.notion.com/v1/pages/16cabc1e-edcd-818e-a44e-d725243e4167 75 | response: 76 | content: '{"object":"page","id":"16cabc1e-edcd-818e-a44e-d725243e4167","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 77 | 2024-12-30 18:21:48.938313","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 78 | 2024-12-30 18:21:48.938313","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-48-938313-16cabc1eedcd818ea44ed725243e4167","public_url":null,"request_id":"1ed13687-4b22-478b-af4b-deb44a8e766b"}' 79 | headers: {} 80 | http_version: HTTP/1.1 81 | status_code: 200 82 | - request: 83 | body: '' 84 | headers: 85 | accept: 86 | - '*/*' 87 | accept-encoding: 88 | - gzip, deflate 89 | authorization: 90 | - ntn_... 91 | connection: 92 | - keep-alive 93 | host: 94 | - api.notion.com 95 | notion-version: 96 | - '2022-06-28' 97 | method: DELETE 98 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-818e-a44e-d725243e4167 99 | response: 100 | content: '{"object":"block","id":"16cabc1e-edcd-818e-a44e-d725243e4167","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 101 | 2024-12-30 18:21:48.938313"},"request_id":"79068090-4b95-49df-9def-8981874bc191"}' 102 | headers: {} 103 | http_version: HTTP/1.1 104 | status_code: 200 105 | version: 1 106 | -------------------------------------------------------------------------------- /tests/cassettes/test_pages_properties_retrieve.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:20:58.800421"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8142-a6cb-f67ce3b940a7","created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:20:58.800421","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:20:58.800421","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-20-58-800421-16cabc1eedcd8142a6cbf67ce3b940a7","public_url":null,"request_id":"4e6d8279-80e2-4473-b579-435837c7b118"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | host: 43 | - api.notion.com 44 | notion-version: 45 | - '2022-06-28' 46 | method: GET 47 | uri: https://api.notion.com/v1/pages/16cabc1e-edcd-8142-a6cb-f67ce3b940a7/properties/title 48 | response: 49 | content: '{"object":"list","results":[{"object":"property_item","type":"title","id":"title","title":{"type":"text","text":{"content":"Test 50 | 2024-12-30 18:20:58.800421","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 51 | 2024-12-30 18:20:58.800421","href":null}}],"next_cursor":null,"has_more":false,"type":"property_item","property_item":{"id":"title","next_url":null,"type":"title","title":{}},"request_id":"42d073df-e1ec-4ab9-aa3c-3c9253a7c27d"}' 52 | headers: {} 53 | http_version: HTTP/1.1 54 | status_code: 200 55 | - request: 56 | body: '' 57 | headers: 58 | accept: 59 | - '*/*' 60 | accept-encoding: 61 | - gzip, deflate 62 | authorization: 63 | - ntn_... 64 | connection: 65 | - keep-alive 66 | host: 67 | - api.notion.com 68 | notion-version: 69 | - '2022-06-28' 70 | method: DELETE 71 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8142-a6cb-f67ce3b940a7 72 | response: 73 | content: '{"object":"block","id":"16cabc1e-edcd-8142-a6cb-f67ce3b940a7","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 74 | 2024-12-30 18:20:58.800421"},"request_id":"08967072-141f-4b81-bf34-9d2e255521b3"}' 75 | headers: {} 76 | http_version: HTTP/1.1 77 | status_code: 200 78 | version: 1 79 | -------------------------------------------------------------------------------- /tests/cassettes/test_pages_retrieve.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:20:54.151558"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-8130-8c6b-f9c944d8fc97","created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:20:54.151558","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:20:54.151558","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-20-54-151558-16cabc1eedcd81308c6bf9c944d8fc97","public_url":null,"request_id":"1783eb4b-e62f-456f-8a16-fd0582037bda"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | host: 43 | - api.notion.com 44 | notion-version: 45 | - '2022-06-28' 46 | method: GET 47 | uri: https://api.notion.com/v1/pages/16cabc1e-edcd-8130-8c6b-f9c944d8fc97 48 | response: 49 | content: '{"object":"page","id":"16cabc1e-edcd-8130-8c6b-f9c944d8fc97","created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 50 | 2024-12-30 18:20:54.151558","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 51 | 2024-12-30 18:20:54.151558","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-20-54-151558-16cabc1eedcd81308c6bf9c944d8fc97","public_url":null,"request_id":"cf38c403-b04f-4e4f-8414-6c6ede386776"}' 52 | headers: {} 53 | http_version: HTTP/1.1 54 | status_code: 200 55 | - request: 56 | body: '' 57 | headers: 58 | accept: 59 | - '*/*' 60 | accept-encoding: 61 | - gzip, deflate 62 | authorization: 63 | - ntn_... 64 | connection: 65 | - keep-alive 66 | host: 67 | - api.notion.com 68 | notion-version: 69 | - '2022-06-28' 70 | method: DELETE 71 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-8130-8c6b-f9c944d8fc97 72 | response: 73 | content: '{"object":"block","id":"16cabc1e-edcd-8130-8c6b-f9c944d8fc97","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 74 | 2024-12-30 18:20:54.151558"},"request_id":"b20890cb-0eda-447e-9b2b-6f9bf02f35c9"}' 75 | headers: {} 76 | http_version: HTTP/1.1 77 | status_code: 200 78 | version: 1 79 | -------------------------------------------------------------------------------- /tests/cassettes/test_pages_update.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:20:55.725477"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-812c-945e-d720ee9b73a6","created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:20:55.725477","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:20:55.725477","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-20-55-725477-16cabc1eedcd812c945ed720ee9b73a6","public_url":null,"request_id":"ff441be1-780a-4d1a-87e0-2dfa9513d23a"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: "{\"icon\":{\"type\":\"emoji\",\"emoji\":\"\U0001F6F4\"}}" 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '40' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: PATCH 51 | uri: https://api.notion.com/v1/pages/16cabc1e-edcd-812c-945e-d720ee9b73a6 52 | response: 53 | content: "{\"object\":\"page\",\"id\":\"16cabc1e-edcd-812c-945e-d720ee9b73a6\",\"created_time\":\"2024-12-30T17:20:00.000Z\",\"last_edited_time\":\"2024-12-30T17:20:00.000Z\",\"created_by\":{\"object\":\"user\",\"id\":\"7775f3a3-893f-43fa-b625-460c61094c78\"},\"last_edited_by\":{\"object\":\"user\",\"id\":\"7775f3a3-893f-43fa-b625-460c61094c78\"},\"cover\":null,\"icon\":{\"type\":\"emoji\",\"emoji\":\"\U0001F6F4\"},\"parent\":{\"type\":\"page_id\",\"page_id\":\"95ba0116-6776-4c19-9e45-54e77415f03b\"},\"archived\":false,\"in_trash\":false,\"properties\":{\"title\":{\"id\":\"title\",\"type\":\"title\",\"title\":[{\"type\":\"text\",\"text\":{\"content\":\"Test 54 | 2024-12-30 18:20:55.725477\",\"link\":null},\"annotations\":{\"bold\":false,\"italic\":false,\"strikethrough\":false,\"underline\":false,\"code\":false,\"color\":\"default\"},\"plain_text\":\"Test 55 | 2024-12-30 18:20:55.725477\",\"href\":null}]}},\"url\":\"https://www.notion.so/Test-2024-12-30-18-20-55-725477-16cabc1eedcd812c945ed720ee9b73a6\",\"public_url\":null,\"request_id\":\"b92baa45-9b2a-4ee8-8cf3-d604dbd41aff\"}" 56 | headers: {} 57 | http_version: HTTP/1.1 58 | status_code: 200 59 | - request: 60 | body: '{"icon":null}' 61 | headers: 62 | accept: 63 | - '*/*' 64 | accept-encoding: 65 | - gzip, deflate 66 | authorization: 67 | - ntn_... 68 | connection: 69 | - keep-alive 70 | content-length: 71 | - '13' 72 | content-type: 73 | - application/json 74 | host: 75 | - api.notion.com 76 | notion-version: 77 | - '2022-06-28' 78 | method: PATCH 79 | uri: https://api.notion.com/v1/pages/16cabc1e-edcd-812c-945e-d720ee9b73a6 80 | response: 81 | content: '{"object":"page","id":"16cabc1e-edcd-812c-945e-d720ee9b73a6","created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 82 | 2024-12-30 18:20:55.725477","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 83 | 2024-12-30 18:20:55.725477","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-20-55-725477-16cabc1eedcd812c945ed720ee9b73a6","public_url":null,"request_id":"7a6acc22-63cb-4baa-a1ef-baebda1af3db"}' 84 | headers: {} 85 | http_version: HTTP/1.1 86 | status_code: 200 87 | - request: 88 | body: '' 89 | headers: 90 | accept: 91 | - '*/*' 92 | accept-encoding: 93 | - gzip, deflate 94 | authorization: 95 | - ntn_... 96 | connection: 97 | - keep-alive 98 | host: 99 | - api.notion.com 100 | notion-version: 101 | - '2022-06-28' 102 | method: DELETE 103 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-812c-945e-d720ee9b73a6 104 | response: 105 | content: '{"object":"block","id":"16cabc1e-edcd-812c-945e-d720ee9b73a6","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:20:00.000Z","last_edited_time":"2024-12-30T17:20:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 106 | 2024-12-30 18:20:55.725477"},"request_id":"b9071eae-1e4c-43f9-b5ba-e71e9d1ed54d"}' 107 | headers: {} 108 | http_version: HTTP/1.1 109 | status_code: 200 110 | version: 1 111 | -------------------------------------------------------------------------------- /tests/cassettes/test_search.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '{"parent":{"page_id":"95ba011667764c199e4554e77415f03b"},"properties":{"title":[{"text":{"content":"Test 4 | 2024-12-30 18:21:21.304151"}}]},"children":[]}' 5 | headers: 6 | accept: 7 | - '*/*' 8 | accept-encoding: 9 | - gzip, deflate 10 | authorization: 11 | - ntn_... 12 | connection: 13 | - keep-alive 14 | content-length: 15 | - '151' 16 | content-type: 17 | - application/json 18 | host: 19 | - api.notion.com 20 | notion-version: 21 | - '2022-06-28' 22 | method: POST 23 | uri: https://api.notion.com/v1/pages 24 | response: 25 | content: '{"object":"page","id":"16cabc1e-edcd-81fd-a9a5-f171d995ab0e","created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"cover":null,"icon":null,"parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"archived":false,"in_trash":false,"properties":{"title":{"id":"title","type":"title","title":[{"type":"text","text":{"content":"Test 26 | 2024-12-30 18:21:21.304151","link":null},"annotations":{"bold":false,"italic":false,"strikethrough":false,"underline":false,"code":false,"color":"default"},"plain_text":"Test 27 | 2024-12-30 18:21:21.304151","href":null}]}},"url":"https://www.notion.so/Test-2024-12-30-18-21-21-304151-16cabc1eedcd81fda9a5f171d995ab0e","public_url":null,"request_id":"4efebdf4-d848-4546-9e22-5a0377a560d7"}' 28 | headers: {} 29 | http_version: HTTP/1.1 30 | status_code: 200 31 | - request: 32 | body: '{"query":"16cabc1e-edcd-81fd-a9a5-f171d995ab0e","sort":{"direction":"descending","timestamp":"last_edited_time"}}' 33 | headers: 34 | accept: 35 | - '*/*' 36 | accept-encoding: 37 | - gzip, deflate 38 | authorization: 39 | - ntn_... 40 | connection: 41 | - keep-alive 42 | content-length: 43 | - '113' 44 | content-type: 45 | - application/json 46 | host: 47 | - api.notion.com 48 | notion-version: 49 | - '2022-06-28' 50 | method: POST 51 | uri: https://api.notion.com/v1/search 52 | response: 53 | content: '{"object":"list","results":[],"next_cursor":null,"has_more":false,"type":"page_or_database","page_or_database":{},"request_id":"44e5b7fe-3df5-47b6-bbaa-18b7e16431ea"}' 54 | headers: {} 55 | http_version: HTTP/1.1 56 | status_code: 200 57 | - request: 58 | body: '' 59 | headers: 60 | accept: 61 | - '*/*' 62 | accept-encoding: 63 | - gzip, deflate 64 | authorization: 65 | - ntn_... 66 | connection: 67 | - keep-alive 68 | host: 69 | - api.notion.com 70 | notion-version: 71 | - '2022-06-28' 72 | method: DELETE 73 | uri: https://api.notion.com/v1/blocks/16cabc1e-edcd-81fd-a9a5-f171d995ab0e 74 | response: 75 | content: '{"object":"block","id":"16cabc1e-edcd-81fd-a9a5-f171d995ab0e","parent":{"type":"page_id","page_id":"95ba0116-6776-4c19-9e45-54e77415f03b"},"created_time":"2024-12-30T17:21:00.000Z","last_edited_time":"2024-12-30T17:21:00.000Z","created_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"last_edited_by":{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78"},"has_children":false,"archived":true,"in_trash":true,"type":"child_page","child_page":{"title":"Test 76 | 2024-12-30 18:21:21.304151"},"request_id":"2df65321-91dc-4c70-a457-0ff15d1ac253"}' 77 | headers: {} 78 | http_version: HTTP/1.1 79 | status_code: 200 80 | version: 1 81 | -------------------------------------------------------------------------------- /tests/cassettes/test_users_list.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/users 19 | response: 20 | content: '{"object":"list","results":[{"object":"user","id":"a4f789cc-7bc8-4cf0-82b9-a8ba7d985ecf","name":"Guillaume 21 | Gelin","avatar_url":"https://s3-us-west-2.amazonaws.com/public.notion-static.com/01d7053d-e135-4f27-bba0-5de532d39296/ramnes3.jpeg","type":"person","person":{"email":"notion@ramnes.eu"}},{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"}}],"next_cursor":null,"has_more":false,"type":"user","user":{},"request_id":"d1999e67-7eb2-44d6-b1c6-6d6fc0e8b725"}' 22 | headers: {} 23 | http_version: HTTP/1.1 24 | status_code: 200 25 | version: 1 26 | -------------------------------------------------------------------------------- /tests/cassettes/test_users_me.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/users/me 19 | response: 20 | content: '{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"},"request_id":"dd2d0023-75bb-4503-b71c-0850ddcc1579"}' 21 | headers: {} 22 | http_version: HTTP/1.1 23 | status_code: 200 24 | version: 1 25 | -------------------------------------------------------------------------------- /tests/cassettes/test_users_retrieve.yaml: -------------------------------------------------------------------------------- 1 | interactions: 2 | - request: 3 | body: '' 4 | headers: 5 | accept: 6 | - '*/*' 7 | accept-encoding: 8 | - gzip, deflate 9 | authorization: 10 | - ntn_... 11 | connection: 12 | - keep-alive 13 | host: 14 | - api.notion.com 15 | notion-version: 16 | - '2022-06-28' 17 | method: GET 18 | uri: https://api.notion.com/v1/users/me 19 | response: 20 | content: '{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"},"request_id":"9f4d5a8f-4782-4738-87b2-db2fcc109ec9"}' 21 | headers: {} 22 | http_version: HTTP/1.1 23 | status_code: 200 24 | - request: 25 | body: '' 26 | headers: 27 | accept: 28 | - '*/*' 29 | accept-encoding: 30 | - gzip, deflate 31 | authorization: 32 | - ntn_... 33 | connection: 34 | - keep-alive 35 | host: 36 | - api.notion.com 37 | notion-version: 38 | - '2022-06-28' 39 | method: GET 40 | uri: https://api.notion.com/v1/users/7775f3a3-893f-43fa-b625-460c61094c78 41 | response: 42 | content: '{"object":"user","id":"7775f3a3-893f-43fa-b625-460c61094c78","name":"notion-sdk-py","avatar_url":null,"type":"bot","bot":{"owner":{"type":"workspace","workspace":true},"workspace_name":"notion-sdk-py"},"request_id":"b88ac143-7766-42fa-982e-eef6fe527ce8"}' 43 | headers: {} 44 | http_version: HTTP/1.1 45 | status_code: 200 46 | version: 1 47 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | from datetime import datetime 4 | from typing import Optional 5 | 6 | import pytest 7 | 8 | from notion_client import AsyncClient, Client 9 | 10 | 11 | @pytest.fixture(scope="session") 12 | def vcr_config(): 13 | def remove_headers(response: dict): 14 | response["headers"] = {} 15 | return response 16 | 17 | return { 18 | "filter_headers": [ 19 | ("authorization", "ntn_..."), 20 | ("user-agent", None), 21 | ("cookie", None), 22 | ], 23 | "before_record_response": remove_headers, 24 | "match_on": ["method", "remove_page_id_for_matches"], 25 | } 26 | 27 | 28 | @pytest.fixture(scope="module") 29 | def vcr(vcr): 30 | def remove_page_id_for_matches(r1, r2): 31 | RE_PAGE_ID = r"[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}" 32 | return re.sub(RE_PAGE_ID, r1.uri, "") == re.sub(RE_PAGE_ID, r2.uri, "") 33 | 34 | vcr.register_matcher("remove_page_id_for_matches", remove_page_id_for_matches) 35 | return vcr 36 | 37 | 38 | @pytest.fixture(scope="session") 39 | def token() -> str: 40 | return os.environ.get("NOTION_TOKEN") 41 | 42 | 43 | @pytest.fixture(scope="module", autouse=True) 44 | def parent_page_id(vcr) -> str: 45 | """this is the ID of the Notion page where the tests will be executed 46 | the bot must have access to the page with all the capabilities enabled""" 47 | page_id = os.environ.get("NOTION_TEST_PAGE_ID") 48 | if page_id: 49 | return page_id 50 | 51 | try: 52 | with vcr.use_cassette("test_pages_create.yaml") as cass: 53 | response = cass._serializer.deserialize(cass.data[0][1]["content"]) 54 | return response["parent"]["page_id"] 55 | except Exception: 56 | pytest.exit( 57 | "Missing base page id. Restore test_pages_create.yaml or add " 58 | "NOTION_TEST_PAGE_ID to your environment.", 59 | ) 60 | 61 | 62 | @pytest.fixture(scope="function") 63 | def page_id(client, parent_page_id): 64 | """create a temporary subpage inside parent_page_id to run tests without leaks""" 65 | response = client.pages.create( 66 | parent={"page_id": parent_page_id}, 67 | properties={ 68 | "title": [{"text": {"content": f"Test {datetime.now()}"}}], 69 | }, 70 | children=[], 71 | ) 72 | 73 | yield response["id"] 74 | client.blocks.delete(block_id=response["id"]) 75 | 76 | 77 | @pytest.fixture(scope="function") 78 | def block_id(client, page_id) -> str: 79 | """create a block inside page_id to run each block test without leaks""" 80 | children = [ 81 | {"paragraph": {"rich_text": [{"text": {"content": "I'm a paragraph."}}]}} 82 | ] 83 | 84 | response = client.blocks.children.append(block_id=page_id, children=children) 85 | yield response["results"][0]["id"] 86 | client.blocks.delete(block_id=response["results"][0]["id"]) 87 | 88 | 89 | @pytest.fixture(scope="function") 90 | def database_id(client, page_id) -> str: 91 | """create a block inside page_id to run each database test without leaks""" 92 | db_name = f"Test Database - {datetime.now()}" 93 | properties = { 94 | "Name": {"title": {}}, # required property 95 | } 96 | title = [{"type": "text", "text": {"content": db_name}}] 97 | parent = {"type": "page_id", "page_id": page_id} 98 | response = client.databases.create( 99 | **{"parent": parent, "title": title, "properties": properties} 100 | ) 101 | 102 | yield response["id"] 103 | client.blocks.delete(block_id=response["id"]) 104 | 105 | 106 | @pytest.fixture(scope="function") 107 | def comment_id(client, page_id) -> str: 108 | """create a comment inside page_id to run each comment test without leaks""" 109 | parent = {"page_id": page_id} 110 | rich_text = [ 111 | { 112 | "text": { 113 | "content": "This is a test comment.", 114 | }, 115 | }, 116 | ] 117 | 118 | response = client.comments.create(parent=parent, rich_text=rich_text) 119 | 120 | yield response["id"] 121 | 122 | 123 | text_block_id = block_id 124 | 125 | 126 | @pytest.fixture(scope="function") 127 | def equation_block_id(client, page_id) -> str: 128 | """create a block inside page_id that has an equation""" 129 | children = [ 130 | {"paragraph": {"rich_text": [{"equation": {"expression": "E = mc^2"}}]}} 131 | ] 132 | 133 | response = client.blocks.children.append(block_id=page_id, children=children) 134 | yield response["results"][0]["id"] 135 | client.blocks.delete(block_id=response["results"][0]["id"]) 136 | 137 | 138 | @pytest.fixture(scope="function") 139 | def mention_block_id(client, page_id) -> str: 140 | """create a block inside page_id that has a date mention""" 141 | children = [ 142 | { 143 | "paragraph": { 144 | "rich_text": [ 145 | { 146 | "mention": { 147 | "type": "date", 148 | "date": {"start": "2022-12-16", "end": None}, 149 | } 150 | } 151 | ] 152 | } 153 | } 154 | ] 155 | 156 | response = client.blocks.children.append(block_id=page_id, children=children) 157 | yield response["results"][0]["id"] 158 | client.blocks.delete(block_id=response["results"][0]["id"]) 159 | 160 | 161 | @pytest.fixture(scope="module") 162 | def client(token: Optional[str]): 163 | with Client({"auth": token}) as client: 164 | yield client 165 | 166 | 167 | @pytest.fixture 168 | async def async_client(token: Optional[str]): 169 | async with AsyncClient({"auth": token}) as client: 170 | yield client 171 | -------------------------------------------------------------------------------- /tests/test_client.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from notion_client import APIResponseError, AsyncClient, Client 4 | 5 | 6 | def test_client_init(client): 7 | assert isinstance(client, Client) 8 | 9 | 10 | def test_async_client_init(async_client): 11 | assert isinstance(async_client, AsyncClient) 12 | 13 | 14 | @pytest.mark.vcr() 15 | def test_client_request(client): 16 | with pytest.raises(APIResponseError): 17 | client.request("/invalid", "GET") 18 | 19 | response = client.request("/users", "GET") 20 | assert response["results"] 21 | 22 | 23 | @pytest.mark.vcr() 24 | async def test_async_client_request(async_client): 25 | with pytest.raises(APIResponseError): 26 | await async_client.request("/invalid", "GET") 27 | 28 | response = await async_client.request("/users", "GET") 29 | assert response["results"] 30 | 31 | 32 | @pytest.mark.vcr() 33 | def test_client_request_auth(token): 34 | client = Client(auth="Invalid") 35 | 36 | with pytest.raises(APIResponseError): 37 | client.request("/users", "GET") 38 | 39 | response = client.request("/users", "GET", auth=token) 40 | assert response["results"] 41 | 42 | client.close() 43 | 44 | 45 | @pytest.mark.vcr() 46 | async def test_async_client_request_auth(token): 47 | async_client = AsyncClient(auth="Invalid") 48 | 49 | with pytest.raises(APIResponseError): 50 | await async_client.request("/users", "GET") 51 | 52 | response = await async_client.request("/users", "GET", auth=token) 53 | assert response["results"] 54 | 55 | await async_client.aclose() 56 | -------------------------------------------------------------------------------- /tests/test_endpoints.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.vcr() 5 | def test_pages_create(client, parent_page_id): 6 | response = client.pages.create( 7 | parent={"page_id": parent_page_id}, 8 | properties={ 9 | "title": [{"text": {"content": "Test Page"}}], 10 | }, 11 | children=[], 12 | ) 13 | 14 | assert response["object"] == "page" 15 | 16 | # cleanup 17 | client.blocks.delete(block_id=response["id"]) 18 | 19 | 20 | @pytest.mark.vcr() 21 | def test_pages_retrieve(client, page_id): 22 | response = client.pages.retrieve(page_id=page_id) 23 | assert response["object"] == "page" 24 | 25 | 26 | @pytest.mark.vcr() 27 | def test_pages_update(client, page_id): 28 | icon = {"type": "emoji", "emoji": "🛴"} 29 | 30 | response = client.pages.update(page_id=page_id, icon=icon) 31 | assert response["icon"] 32 | 33 | response = client.pages.update(page_id=page_id, icon=None) 34 | assert response["icon"] is None 35 | 36 | 37 | @pytest.mark.vcr() 38 | def test_pages_properties_retrieve(client, page_id): 39 | response = client.pages.properties.retrieve(page_id=page_id, property_id="title") 40 | assert response["results"][0]["type"] == "title" 41 | 42 | 43 | @pytest.mark.vcr() 44 | def test_blocks_children_create(client, page_id) -> str: 45 | children = [ 46 | {"paragraph": {"rich_text": [{"text": {"content": "I'm a paragraph."}}]}} 47 | ] 48 | 49 | response = client.blocks.children.append(block_id=page_id, children=children) 50 | 51 | assert response["object"] == "list" 52 | assert len(response["results"]) > 0 53 | assert response["results"][0]["id"] 54 | 55 | 56 | @pytest.mark.vcr() 57 | def test_blocks_children_list(client, page_id): 58 | response = client.blocks.children.list(block_id=page_id) 59 | assert response["object"] == "list" 60 | assert response["type"] == "block" 61 | 62 | 63 | @pytest.mark.vcr() 64 | def test_blocks_retrieve(client, block_id): 65 | response = client.blocks.retrieve(block_id=block_id) 66 | assert response["object"] == "block" 67 | assert response["type"] == "paragraph" 68 | 69 | 70 | @pytest.mark.vcr() 71 | def test_blocks_update(client, block_id): 72 | new_plain_text = "I'm an updated paragraph." 73 | new_text = { 74 | "rich_text": [ 75 | { 76 | "text": {"content": new_plain_text}, 77 | "annotations": {"bold": True, "color": "red_background"}, 78 | } 79 | ] 80 | } 81 | response = client.blocks.update(block_id=block_id, paragraph=new_text) 82 | 83 | assert response["paragraph"]["rich_text"][0]["plain_text"] 84 | 85 | 86 | @pytest.mark.vcr() 87 | def test_blocks_delete(client, block_id): 88 | client.blocks.delete(block_id=block_id) 89 | 90 | new_retrieve = client.blocks.retrieve(block_id=block_id) 91 | assert new_retrieve["archived"] 92 | 93 | client.blocks.update(block_id=block_id, archived=False) 94 | 95 | 96 | @pytest.mark.vcr() 97 | def test_users_list(client): 98 | response = client.users.list() 99 | assert response["type"] == "user" 100 | 101 | 102 | @pytest.mark.vcr() 103 | def test_users_me(client): 104 | response = client.users.me() 105 | assert response["type"] == "bot" 106 | assert response["id"] 107 | 108 | 109 | @pytest.mark.vcr() 110 | def test_users_retrieve(client): 111 | me = client.users.me() 112 | response = client.users.retrieve(me["id"]) 113 | 114 | me.pop("request_id", None) 115 | response.pop("request_id", None) 116 | 117 | assert response == me 118 | 119 | 120 | @pytest.mark.vcr() 121 | def test_search(client, page_id): 122 | payload = { 123 | "query": page_id, 124 | "sort": { 125 | "direction": "descending", 126 | "timestamp": "last_edited_time", 127 | }, 128 | } 129 | 130 | response = client.search(**payload) 131 | assert response["object"] == "list" 132 | 133 | 134 | @pytest.mark.vcr() 135 | def test_databases_create(client, page_id): 136 | properties = { 137 | "Name": {"title": {}}, # required property 138 | } 139 | title = [{"type": "text", "text": {"content": "Test Database"}}] 140 | parent = {"type": "page_id", "page_id": page_id} 141 | response = client.databases.create( 142 | **{"parent": parent, "title": title, "properties": properties} 143 | ) 144 | 145 | assert response["object"] == "database" 146 | 147 | 148 | @pytest.mark.vcr() 149 | def test_databases_query(client, database_id): 150 | query = { 151 | "database_id": database_id, 152 | "filter": {"timestamp": "created_time", "created_time": {"past_week": {}}}, 153 | } 154 | 155 | response = client.databases.query(**query) 156 | assert response["object"] == "list" 157 | assert not response["results"] 158 | 159 | 160 | @pytest.mark.vcr() 161 | def test_databases_retrieve(client, database_id): 162 | response = client.databases.retrieve(database_id) 163 | assert response["object"] == "database" 164 | 165 | 166 | @pytest.mark.vcr() 167 | def test_databases_update(client, database_id): 168 | icon = {"type": "emoji", "emoji": "🔥"} 169 | 170 | response = client.databases.update(database_id=database_id, icon=icon) 171 | assert response["icon"] 172 | 173 | 174 | @pytest.mark.vcr() 175 | def test_comments_create(client, page_id): 176 | parent = {"page_id": page_id} 177 | rich_text = [ 178 | { 179 | "text": { 180 | "content": "This is a test comment.", 181 | }, 182 | }, 183 | ] 184 | 185 | response = client.comments.create(parent=parent, rich_text=rich_text) 186 | assert response 187 | 188 | 189 | @pytest.mark.vcr() 190 | def test_comments_list(client, page_id, comment_id): 191 | response = client.comments.list(block_id=page_id) 192 | assert response["object"] == "list" 193 | assert response["results"] != [] 194 | 195 | 196 | @pytest.mark.vcr() 197 | def test_pages_delete(client, page_id): 198 | response = client.blocks.delete(block_id=page_id) 199 | assert response 200 | 201 | client.pages.update(page_id=page_id, archived=False) 202 | -------------------------------------------------------------------------------- /tests/test_errors.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from httpx import TimeoutException 3 | 4 | from notion_client.errors import ( 5 | APIResponseError, 6 | HTTPResponseError, 7 | RequestTimeoutError, 8 | is_api_error_code, 9 | ) 10 | 11 | STATUS_PAGE_BAD_REQUEST = "https://mock.httpstatus.io/400" 12 | 13 | 14 | @pytest.mark.vcr() 15 | def test_api_response_error(client): 16 | with pytest.raises(APIResponseError): 17 | client.request("/invalid", "GET") 18 | with pytest.raises(APIResponseError): 19 | client.request("/users", "GET", auth="Invalid") 20 | 21 | 22 | def test_api_request_timeout_error(monkeypatch, client): 23 | def mock_timeout_request(*args): 24 | raise TimeoutException("Mock Timeout") 25 | 26 | monkeypatch.setattr(client.client, "send", mock_timeout_request) 27 | 28 | with pytest.raises(RequestTimeoutError): 29 | client.request("/users", "GET") 30 | 31 | 32 | @pytest.mark.vcr() 33 | def test_api_http_response_error(client): 34 | with pytest.raises(HTTPResponseError): 35 | client.request(STATUS_PAGE_BAD_REQUEST, "GET") 36 | 37 | 38 | @pytest.mark.vcr() 39 | async def test_async_api_response_error(async_client): 40 | with pytest.raises(APIResponseError): 41 | await async_client.request("/invalid", "GET") 42 | with pytest.raises(APIResponseError): 43 | await async_client.request("/users", "GET", auth="Invalid") 44 | 45 | 46 | async def test_async_api_request_timeout_error(monkeypatch, async_client): 47 | def mock_timeout_request(*args): 48 | raise TimeoutException("Mock Timeout") 49 | 50 | monkeypatch.setattr(async_client.client, "send", mock_timeout_request) 51 | 52 | with pytest.raises(RequestTimeoutError): 53 | await async_client.request("/users", "GET") 54 | 55 | 56 | @pytest.mark.vcr() 57 | async def test_api_async_request_bad_request_error(async_client): 58 | with pytest.raises(HTTPResponseError): 59 | await async_client.request(STATUS_PAGE_BAD_REQUEST, "GET") 60 | 61 | 62 | async def test_is_api_error_code(): 63 | error_code = "unauthorized" 64 | assert is_api_error_code(error_code) 65 | assert not is_api_error_code(None) 66 | assert not is_api_error_code(404) 67 | -------------------------------------------------------------------------------- /tests/test_helpers.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | from types import AsyncGeneratorType, GeneratorType 4 | 5 | import pytest 6 | 7 | from notion_client.helpers import ( 8 | async_collect_paginated_api, 9 | async_iterate_paginated_api, 10 | collect_paginated_api, 11 | get_id, 12 | get_url, 13 | is_equation_rich_text_item_response, 14 | is_full_block, 15 | is_full_comment, 16 | is_full_database, 17 | is_full_page, 18 | is_full_page_or_database, 19 | is_full_user, 20 | is_mention_rich_text_item_response, 21 | is_text_rich_text_item_response, 22 | iterate_paginated_api, 23 | pick, 24 | ) 25 | 26 | 27 | def test_pick(): 28 | my_dict = { 29 | "Product": "Notion", 30 | "API": 2021, 31 | "python-sdk": "ramnes", 32 | "optional-variable": None, 33 | } 34 | assert pick(my_dict, "Product") == {"Product": "Notion"} 35 | assert pick(my_dict, "API", "python-sdk") == { 36 | "API": 2021, 37 | "python-sdk": "ramnes", 38 | } 39 | assert pick(my_dict, "optional-variable") == {"optional-variable": None} 40 | assert pick(my_dict, "start_cursor") == {} 41 | 42 | 43 | def test_get_id(): 44 | page_url = "https://notion.so/aahnik/Aahnik-Daw-621cc4c1ad324159bcea215ce18e03a8" 45 | page_id = "621cc4c1-ad32-4159-bcea-215ce18e03a8" 46 | db_url = "https://notion.so/aahnik/99572135464649bd95a14ff08f79c7a5?\ 47 | v=f41969f937614159857f6a5725990649" 48 | db_id = "99572135-4646-49bd-95a1-4ff08f79c7a5" 49 | assert get_id(page_url) == page_id 50 | assert get_id(db_url) == db_id 51 | with pytest.raises(ValueError): 52 | get_id("https://example.com") 53 | with pytest.raises(ValueError): 54 | get_id("https://notion.so/123") 55 | with pytest.raises(ValueError): 56 | get_id("https://notion.so/99572135464649b-d95a14ff08f79c7a5") 57 | 58 | 59 | def test_get_url(): 60 | dashed_id = "540f8e2b-7991-4654-ba10-3c5d8a03e10e" 61 | obj_id = "540f8e2b79914654ba103c5d8a03e10e" 62 | url = "https://notion.so/540f8e2b79914654ba103c5d8a03e10e" 63 | assert get_url(dashed_id) == url 64 | assert get_url(obj_id) == url 65 | with pytest.raises(ValueError): 66 | get_url("540f8e2b799-14654ba103c5d8a03-e10e") 67 | get_url("123abc") 68 | 69 | 70 | @pytest.mark.vcr() 71 | @pytest.mark.timeout(90) 72 | def test_iterate_paginated_api(client, parent_page_id): 73 | def create_page(page_name): 74 | page = client.pages.create( 75 | parent={"page_id": parent_page_id}, 76 | properties={"title": [{"text": {"content": page_name}}]}, 77 | children=[], 78 | ) 79 | return page["id"] 80 | 81 | page_ids = [] 82 | for i in range(0, 5): 83 | page_id = create_page(f"Test Page (test_iterate_paginated_api iteration {i})") 84 | page_ids.append(page_id) 85 | 86 | # give time to Notion to index these pages 87 | time.sleep(20) 88 | 89 | generator = iterate_paginated_api( 90 | client.search, 91 | query="test_iterate_paginated_api", 92 | page_size=2, 93 | ) 94 | assert isinstance(generator, GeneratorType) 95 | results = [result for result in generator] 96 | assert len(results) == 5 97 | 98 | for page_id in page_ids: 99 | client.blocks.delete(block_id=page_id) 100 | 101 | time.sleep(20) 102 | 103 | generator = iterate_paginated_api( 104 | client.search, 105 | query="test_iterate_paginated_api", 106 | page_size=2, 107 | ) 108 | assert isinstance(generator, GeneratorType) 109 | results = [result for result in generator] 110 | assert len(results) == 0 111 | 112 | 113 | @pytest.mark.vcr() 114 | def test_collect_paginated_api(client): 115 | function = client.search 116 | results = collect_paginated_api(function) 117 | 118 | assert isinstance(results, list) 119 | assert results != [] 120 | 121 | results_empty = collect_paginated_api(function, query="This should have no results") 122 | assert results_empty == [] 123 | 124 | 125 | @pytest.mark.vcr() 126 | @pytest.mark.timeout(90) 127 | async def test_async_iterate_paginated_api(async_client, parent_page_id): 128 | async def create_page(page_name): 129 | page = await async_client.pages.create( 130 | parent={"page_id": parent_page_id}, 131 | properties={"title": [{"text": {"content": page_name}}]}, 132 | children=[], 133 | ) 134 | return page["id"] 135 | 136 | page_ids = [] 137 | for i in range(0, 5): 138 | page_id = await create_page( 139 | f"Test Page (test_async_iterate_paginated_api iteration {i})" 140 | ) 141 | page_ids.append(page_id) 142 | 143 | # give time to Notion to index these pages 144 | await asyncio.sleep(20) 145 | 146 | generator = async_iterate_paginated_api( 147 | async_client.search, 148 | query="test_async_iterate_paginated_api", 149 | page_size=2, 150 | ) 151 | assert isinstance(generator, AsyncGeneratorType) 152 | results = [result async for result in generator] 153 | assert len(results) == 5 154 | 155 | for page_id in page_ids: 156 | await async_client.blocks.delete(block_id=page_id) 157 | 158 | await asyncio.sleep(20) 159 | 160 | generator = async_iterate_paginated_api( 161 | async_client.search, 162 | query="test_async_iterate_paginated_api", 163 | page_size=2, 164 | ) 165 | assert isinstance(generator, AsyncGeneratorType) 166 | results = [result async for result in generator] 167 | assert len(results) == 0 168 | 169 | 170 | @pytest.mark.vcr() 171 | async def test_async_collect_paginated_api(async_client): 172 | function = async_client.search 173 | results = await async_collect_paginated_api(function) 174 | 175 | assert isinstance(results, list) 176 | assert results != [] 177 | 178 | results_empty = await async_collect_paginated_api( 179 | function, query="This should have no results" 180 | ) 181 | assert results_empty == [] 182 | 183 | 184 | @pytest.mark.vcr() 185 | def test_is_full_block(client, block_id): 186 | response = client.blocks.retrieve(block_id=block_id) 187 | assert is_full_block(response) 188 | 189 | 190 | @pytest.mark.vcr() 191 | def test_is_full_page(client, page_id): 192 | response = client.pages.retrieve(page_id=page_id) 193 | assert is_full_page(response) 194 | 195 | 196 | @pytest.mark.vcr() 197 | def test_is_full_database(client, database_id): 198 | response = client.databases.retrieve(database_id=database_id) 199 | assert is_full_database(response) 200 | 201 | 202 | @pytest.mark.vcr() 203 | def test_is_full_page_or_database(client, database_id, page_id): 204 | response = client.pages.retrieve(page_id=page_id) 205 | assert is_full_page_or_database(response) 206 | 207 | response = client.databases.retrieve(database_id=database_id) 208 | assert is_full_page_or_database(response) 209 | 210 | 211 | @pytest.mark.vcr() 212 | def test_is_full_user(client): 213 | response = client.users.me() 214 | assert is_full_user(response) 215 | 216 | 217 | @pytest.mark.vcr() 218 | def test_is_full_comment(client, page_id, comment_id): 219 | response = client.comments.list(block_id=page_id) 220 | assert is_full_comment(response) 221 | 222 | 223 | @pytest.mark.vcr() 224 | def test_is_text_rich_text_item_response(client, text_block_id): 225 | response = client.blocks.retrieve(block_id=text_block_id) 226 | assert is_text_rich_text_item_response(response["paragraph"]["rich_text"][0]) 227 | 228 | 229 | @pytest.mark.vcr() 230 | def test_is_equation_rich_text_item_response(client, equation_block_id): 231 | response = client.blocks.retrieve(block_id=equation_block_id) 232 | assert is_equation_rich_text_item_response(response["paragraph"]["rich_text"][0]) 233 | 234 | 235 | @pytest.mark.vcr() 236 | def test_is_mention_rich_text_item_response(client, mention_block_id): 237 | response = client.blocks.retrieve(block_id=mention_block_id) 238 | assert is_mention_rich_text_item_response(response["paragraph"]["rich_text"][0]) 239 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py37,py38,py39,py310,py311,py312,py313 3 | 4 | [testenv] 5 | deps = -r requirements/tests.txt 6 | commands = pytest 7 | --------------------------------------------------------------------------------