Unofficial Python API client for Notion.so

Overview

notion-py

Unofficial Python 3 client for Notion.so API v3.

  • Object-oriented interface (mapping database tables to Python classes/attributes)
  • Automatic conversion between internal Notion formats and appropriate Python objects
  • Local cache of data in a unified data store (Note: disk cache now disabled by default; to enable, add enable_caching=True when initializing NotionClient)
  • Real-time reactive two-way data binding (changing Python object -> live updating of Notion UI, and vice-versa) (Note: Notion->Python automatic updating is currently broken and hence disabled by default; call my_block.refresh() to update, in the meantime, while monitoring is being fixed)
  • Callback system for responding to changes in Notion (e.g. for triggering actions, updating another API, etc)

Read more about Notion and Notion-py on Jamie's blog

Usage

Quickstart

Note: the latest version of notion-py requires Python 3.5 or greater.

pip install notion

from notion.client import NotionClient

# Obtain the `token_v2` value by inspecting your browser cookies on a logged-in (non-guest) session on Notion.so
client = NotionClient(token_v2="<token_v2>")

# Replace this URL with the URL of the page you want to edit
page = client.get_block("https://www.notion.so/myorg/Test-c0d20a71c0944985ae96e661ccc99821")

print("The old title is:", page.title)

# Note: You can use Markdown! We convert on-the-fly to Notion's internal formatted text data structure.
page.title = "The title has now changed, and has *live-updated* in the browser!"

Concepts and notes

  • We map tables in the Notion database into Python classes (subclassing Record), with each instance of a class representing a particular record. Some fields from the records (like title in the example above) have been mapped to model properties, allowing for easy, instantaneous read/write of the record. Other fields can be read with the get method, and written with the set method, but then you'll need to make sure to match the internal structures exactly.
  • The tables we currently support are block (via Block class and its subclasses, corresponding to different type of blocks), space (via Space class), collection (via Collection class), collection_view (via CollectionView and subclasses), and notion_user (via User class).
  • Data for all tables are stored in a central RecordStore, with the Record instances not storing state internally, but always referring to the data in the central RecordStore. Many API operations return updating versions of a large number of associated records, which we use to update the store, so the data in Record instances may sometimes update without being explicitly requested. You can also call the refresh method on a Record to trigger an update, or pass force_update to methods like get.
  • The API doesn't have strong validation of most data, so be careful to maintain the structures Notion is expecting. You can view the full internal structure of a record by calling myrecord.get() with no arguments.
  • When you call client.get_block, you can pass in either an ID, or the URL of a page. Note that pages themselves are just blocks, as are all the chunks of content on the page. You can get the URL for a block within a page by clicking "Copy Link" in the context menu for the block, and pass that URL into get_block as well.

Updating records

We keep a local cache of all data that passes through. When you reference an attribute on a Record, we first look to that cache to retrieve the value. If it doesn't find it, it retrieves it from the server. You can also manually refresh the data for a Record by calling the refresh method on it. By default (unless we instantiate NotionClient with monitor=False), we also subscribe to long-polling updates for any instantiated Record, so the local cache data for these Records should be automatically live-updated shortly after any data changes on the server. The long-polling happens in a background daemon thread.

Example: Traversing the block tree

for child in page.children:
    print(child.title)

print("Parent of {} is {}".format(page.id, page.parent.id))

Example: Adding a new node

from notion.block import TodoBlock

newchild = page.children.add_new(TodoBlock, title="Something to get done")
newchild.checked = True

Example: Deleting nodes

# soft-delete
page.remove()

# hard-delete
page.remove(permanently=True)

Example: Create an embedded content type (iframe, video, etc)

from notion.block import VideoBlock

video = page.children.add_new(VideoBlock, width=200)
# sets "property.source" to the URL, and "format.display_source" to the embedly-converted URL
video.set_source_url("https://www.youtube.com/watch?v=oHg5SJYRHA0")

Example: Create a new embedded collection view block

collection = client.get_collection(COLLECTION_ID) # get an existing collection
cvb = page.children.add_new(CollectionViewBlock, collection=collection)
view = cvb.views.add_new(view_type="table")

# Before the view can be browsed in Notion, 
# the filters and format options on the view should be set as desired.
# 
# for example:
#   view.set("query", ...)
#   view.set("format.board_groups", ...)
#   view.set("format.board_properties", ...)

Example: Moving blocks around

# move my block to after the video
my_block.move_to(video, "after")

# move my block to the end of otherblock's children
my_block.move_to(otherblock, "last-child")

# (you can also use "before" and "first-child")

Example: Subscribing to updates

(Note: Notion->Python automatic updating is currently broken and hence disabled by default; call my_block.refresh() to update, in the meantime, while monitoring is being fixed)

We can "watch" a Record so that we get a callback whenever it changes. Combined with the live-updating of records based on long-polling, this allows for a "reactive" design, where actions in our local application can be triggered in response to interactions with the Notion interface.

# define a callback (note: all arguments are optional, just include the ones you care about)
def my_callback(record, difference):
    print("The record's title is now:" record.title)
    print("Here's what was changed:")
    print(difference)

# move my block to after the video
my_block.add_callback(my_callback)

Example: Working with databases, aka "collections" (tables, boards, etc)

Here's how things fit together:

  • Main container block: CollectionViewBlock (inline) / CollectionViewPageBlock (full-page)
    • Collection (holds the schema, and is parent to the database rows themselves)
      • CollectionRowBlock
      • CollectionRowBlock
      • ... (more database records)
    • CollectionView (holds filters/sort/etc about each specific view)

Note: For convenience, we automatically map the database "columns" (aka properties), based on the schema defined in the Collection, into getter/setter attributes on the CollectionRowBlock instances. The attribute name is a "slugified" version of the name of the column. So if you have a column named "Estimated value", you can read and write it via myrowblock.estimated_value. Some basic validation may be conducted, and it will be converted into the appropriate internal format. For columns of type "Person", we expect a User instance, or a list of them, and for a "Relation" we expect a singular/list of instances of a subclass of Block.

# Access a database using the URL of the database page or the inline block
cv = client.get_collection_view("https://www.notion.so/myorg/8511b9fc522249f79b90768b832599cc?v=8dee2a54f6b64cb296c83328adba78e1")

# List all the records with "Bob" in them
for row in cv.collection.get_rows(search="Bob"):
    print("We estimate the value of '{}' at {}".format(row.name, row.estimated_value))

# Add a new record
row = cv.collection.add_row()
row.name = "Just some data"
row.is_confirmed = True
row.estimated_value = 399
row.files = ["https://www.birdlife.org/sites/default/files/styles/1600/public/slide.jpg"]
row.person = client.current_user
row.tags = ["A", "C"]
row.where_to = "https://learningequality.org"

# Run a filtered/sorted query using a view's default parameters
result = cv.default_query().execute()
for row in result:
    print(row)

# Run an "aggregation" query
aggregations = [{
    "property": "estimated_value",
    "aggregator": "sum",
    "id": "total_value",
}]
result = cv.build_query(aggregate=aggregate_params).execute()
print("Total estimated value:", result.get_aggregate("total_value"))

# Run a "filtered" query (inspect network tab in browser for examples, on queryCollection calls)
filter_params = {
    "filters": [{
        "filter": {
            "value": {
                "type": "exact",
                "value": {"table": "notion_user", "id": client.current_user.id}
            },
            "operator": "person_contains"
        },
        "property": "assigned_to"
    }],
    "operator": "and"
}
result = cv.build_query(filter=filter_params).execute()
print("Things assigned to me:", result)

# Run a "sorted" query
sort_params = [{
    "direction": "descending",
    "property": "estimated_value",
}]
result = cv.build_query(sort=sort_params).execute()
print("Sorted results, showing most valuable first:", result)

Note: You can combine filter, aggregate, and sort. See more examples of queries by setting up complex views in Notion, and then inspecting the full query: cv.get("query2").

You can also see more examples in action in the smoke test runner. Run it using:

python run_smoke_test.py --page [YOUR_NOTION_PAGE_URL] --token [YOUR_NOTION_TOKEN_V2]

Example: Lock/Unlock A Page

from notion.client import NotionClient

# Obtain the `token_v2` value by inspecting your browser cookies on a logged-in session on Notion.so
client = NotionClient(token_v2="<token_v2>")

# Replace this URL with the URL of the page or database you want to edit
page = client.get_block("https://www.notion.so/myorg/Test-c0d20a71c0944985ae96e661ccc99821")

# The "locked" property is available on PageBlock and CollectionViewBlock objects
# Set it to True to lock the page/database
page.locked = True
# and False to unlock it again
page.locked = False

Example: Set the current user for multi-account user

from notion.client import NotionClient
client = NotionClient(token_v2="<token_v2>")

# The initial current_user of a multi-account user may be an unwanted user
print(client.current_user.email) # → [email protected]

# Set current_user to the desired user
client.set_user_by_email('[email protected]')
print(client.current_user.email) # → [email protected]

# You can also set the current_user by uid.
client.set_user_by_uid('<uid>')
print(client.current_user.email) # → [email protected]

Quick plug: Learning Equality needs your support!

If you'd like to support notion-py development, please consider donating to my open-source nonprofit, Learning Equality, since when I'm not working on notion-py, it probably means I'm heads-down fundraising for our global education work (bringing resources like Khan Academy to communities with no Internet). COVID has further amplified needs, with over a billion kids stuck at home, and over half of them without the connectivity they need for distance learning. You can now also support our work via GitHub Sponsors!

Related Projects

TODO

  • Cloning pages hierarchically
  • Debounce cache-saving?
  • Support inline "user" and "page" links, and reminders, in markdown conversion
  • Utilities to support updating/creating collection schemas
  • Utilities to support updating/creating collection_view queries
  • Support for easily managing page permissions
  • Websocket support for live block cache updating
  • "Render full page to markdown" mode
  • "Import page from html" mode
Comments
  • 400 error when getting collection view

    400 error when getting collection view

    Tracceback is below. Quick start instructions worked fine on a page, but when trying to pick up a database/collection I get the following. Any suggestions, and thanks!

    File "<stdin>", line 1, in <module>
      File "/usr/local/lib/python3.7/site-packages/notion/client.py", line 98, in get_collection_view
        collection = self.get_block(block_id, force_refresh=force_refresh).collection
      File "/usr/local/lib/python3.7/site-packages/cached_property.py", line 35, in __get__
        value = obj.__dict__[self.func.__name__] = self.func(obj)
      File "/usr/local/lib/python3.7/site-packages/notion/block.py", line 618, in collection
        self._collection = self._client.get_collection(collection_id)
      File "/usr/local/lib/python3.7/site-packages/notion/client.py", line 70, in get_collection
        return Collection(self, collection_id) if coll else None
      File "/usr/local/lib/python3.7/site-packages/notion/collection.py", line 104, in __init__
        self._client.refresh_collection_rows(self.id)
      File "/usr/local/lib/python3.7/site-packages/notion/client.py", line 115, in refresh_collection_rows
        row_ids = self.search_pages_with_parent(collection_id)
      File "/usr/local/lib/python3.7/site-packages/notion/client.py", line 172, in search_pages_with_parent
        response = self.post("searchPagesWithParent", data).json()
      File "/usr/local/lib/python3.7/site-packages/notion/client.py", line 126, in post
        raise HTTPError(response.json().get("message", "There was an error (400) submitting the request."))
    requests.exceptions.HTTPError: Invalid input.
    
    
    opened by heyflorin 18
  • Inconsistent error while initializing the notion client

    Inconsistent error while initializing the notion client

    I had a script that was working fine up until now and it just started breaking for some reason. Sometimes, when I'm initializing the notion client, I get the following error:

    Initialization

    notionClient = NotionClient(token_v2=os.environ.get('NOTION_TOKEN'))
    

    Error

    Traceback (most recent call last):
      File "/Users/<username>/.config/yarn/global/node_modules/serverless/lib/plugins/aws/invokeLocal/invoke.py", line 72, in <module>
    
        module = import_module(args.handler_path.replace('/', '.'))
      File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/importlib/__init__.py", line 127, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
      File "<frozen importlib._bootstrap>", line 991, in _find_and_load
      File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    
      File "<frozen importlib._bootstrap_external>", line 783, in exec_module
    
      File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
      File "./src/handlers/scrapeMentors.py", line 6, in <module>
    
        from ..services.notion import addMentorToNotion, updateMentorOnNotion, deleteRow
      File "./src/services/notion.py", line 4, in <module>
    
        notionClient = NotionClient(token_v2=os.environ.get('NOTION_TOKEN'))
      File "/Users/<username>/Library/Python/3.8/lib/python/site-packages/notion/client.py", line 68, in __init__
    
        self._update_user_info()
      File "/Users/<username>/Library/Python/3.8/lib/python/site-packages/notion/client.py", line 75, in _update_user_info
    
        self._store.store_recordmap(records)
      File "/Users/<username>/Library/Python/3.8/lib/python/site-packages/notion/store.py", line 292, in store_recordmap
    
        for id, record in records.items():
    AttributeError: 'NoneType' object has no attribute 'items'
    

    Investigation

    On store.py#L292, I noticed a table named __json__ that has None for records

    opened by yanmendes 11
  • Unexpected behaviour with adding rows to a collection

    Unexpected behaviour with adding rows to a collection

    With the recent changes in https://github.com/jamalex/notion-py/pull/85, my usage of adding rows to a collection from 0.0.21 to 0.0.25 broke.

    For context, I add tasks via the following: https://github.com/kevinjalbert/notion-toolbox/blob/master/alfred/src/add_task.py#L12-L23

    What I end up getting is the following:

    Traceback (most recent call last):
      File "src/add_task.py", line 28, in <module>
        row = collection.add_row()
      File "/usr/local/lib/python3.7/site-packages/notion/collection.py", line 156, in add_row
        view.set("page_sort", view.get("page_sort", []) + [row_id])
    AttributeError: 'NoneType' object has no attribute 'set'
    

    So for some reason, the view is None at this point.


    Now for the strange part. If I do the following:

        collection = notion_api.tasks_database().collection
    
        # HACK: For some reason, we need all the views loaded up for the collection.add_row() to work
        #       it also has to be 'printed' for whatever reason, just accessing it doesn't work
        print(collection.parent.views)
    ...
    

    It works 🤔.

    I went and looked at the new changes added (https://github.com/jamalex/notion-py/blob/master/notion/collection.py#L152-L156) to see what is happening. I found that the first view for my collection's parent is None (which explains the exception). I went and added the following to collection.py:

                # make sure the new record is inserted at the end of each view
                for view in self.parent.views:
    +               print(view)
    +               if view is None or isinstance(view, CalendarView):
                        continue
                    view.set("page_sort", view.get("page_sort", []) + [row_id])
    

    It works as expected, and I saw the following output:

    None
    None
    None
    None
    None
    None
    None
    id='afc7fdaa-7870-48e2-9a6c-4b1c98acf05a'
    

    So only the last view had a value. I'm not sure why this is the case. Is there maybe some lazy loading going on for views? For additional context, I had monkey-patched out the caching a while back (https://github.com/kevinjalbert/notion-toolbox/commit/8e4e4098ea99eaa5cf24320da5805d0a341b3153) but removed that with this release.


    I can live with a temporary solution for my own needs. Although, I'm curious about what is happening here.

    opened by kevinjalbert 9
  • block sometimes needs an initial refresh to get most recent information

    block sometimes needs an initial refresh to get most recent information

    Sometimes edits to blocks made in the Notion web UI are not immediately available through the API.

    For example, create a sample script test.py like:

    client = NotionClient("[TOKEN]", monitor=False) 
    page = client.get_block("[PAGE URL]")
    print(page.title)
    page.refresh()
    print(page.title)
    

    Create new page with title "A" and run the script on it. It will output

    A
    A
    

    Edit the title to "B" in the web UI and re-run. It will output

    A
    B
    

    I would expect it to output

    B
    B
    
    priority 
    opened by indirectlylit 7
  • De-activable Markdown conversion in CodeBlock

    De-activable Markdown conversion in CodeBlock

    While using markdown_to_notion() for the title property makes lot's of sense for most blocks, it might be an issue for CodeBlock.

    I saw that property_map has a flag for markdown conversion but it's not accessible from the block initialisation.

    https://github.com/jamalex/notion-py/blob/ef0c5e02bd4ae5ad8d34c6c56e4e842b15aeaa01/notion/maps.py#L47

    opened by aureliensibiril 7
  • os.makedirs not callable on aws lambda

    os.makedirs not callable on aws lambda

    on write-only containers (with temp dirs) like lambda instances, DATADIR and the likes should be created in tmp/<path>. I don't see much downside in doing this in all cases. will be forking for my own purposes, lmk if I should open a PR

    question 
    opened by EvanFarrell 7
  • requests.exceptions.HTTPError: Invalid input.

    requests.exceptions.HTTPError: Invalid input.

    I am trying out notion-py for the first time, but actually can't get it to run the Quickstart example.

    I installed for Pyton 3.9 via pip install notion with version 0.0.28.

    from notion.block import TweetBlock
    client = NotionClient(token_v2="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
    page = client.get_block("https://www.notion.so/myorg/Test-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
    print("The old title is:", page.title)
    

    Gives:

    Traceback (most recent call last):
      File "…/test_notion-py.py", line 35, in <module>
        page = client.get_block("https://www.notion.so/myorg/Test-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
      File "…/lib/python3.9/site-packages/notion/client.py", line 169, in get_block
        block = self.get_record_data("block", block_id, force_refresh=force_refresh)
      File "…/lib/python3.9/site-packages/notion/client.py", line 162, in get_record_data
        return self._store.get(table, id, force_refresh=force_refresh)
      File "…/lib/python3.9/site-packages/notion/store.py", line 184, in get
        self.call_load_page_chunk(id)
      File "…/lib/python3.9/site-packages/notion/store.py", line 286, in call_load_page_chunk
        recordmap = self._client.post("loadPageChunk", data).json()["recordMap"]
      File "…/lib/python3.9/site-packages/notion/client.py", line 260, in post
        raise HTTPError(
    requests.exceptions.HTTPError: Invalid input.
    
    opened by 7k50 6
  • Can't write value to NotionDate type object

    Can't write value to NotionDate type object

    I can get NotionDate type object and it's value '.start', '.end' easilly with:

    client = NotionClient([token_notion]) row = client.get_block([url_to_block_in_a_database]) print(row.start) print(row.end)

    however, I can never change the value of it, do I have any way to write value into NotionDate type object ? It's important for me.

    Hope you can feedback!

    opened by realCrush 6
  • Image source always returns none

    Image source always returns none

    For some reason, whenever I try to get an image block's source URL, it turns up none, even though it has worked in the past.

    The code I've been using to test looks something like this:

    for block in page.children: 
        if block.type == 'image': 
            print(block.source)
    

    This will print "None" for all image blocks. I've tried accessing different properties like "display_source" and nothing works.

    Are other people having this issue?

    opened by aivantg 6
  • Polling is broken

    Polling is broken

    Hi.First, thank you for the library, very helpful! Second, I was experiencing lines in a log like 2019-06-24 01:43:26,076 - ERROR - Persistent error submitting polling request: b'{"code":1,"message":"Session ID unknown"}' / 400 Client Error: Bad Request for url: https://msgstore.www.notion.so/primus/?sessionId=SESSION_ID&EIO=3&transport=polling&sid=SID (will retry 5 more times)

    Also, CPU was always 100% busy and I saw that caching was working in a very strange manner. Looked like the data was constantly re-written: I monitored the sizes of cache files, and they were growing to some point, then reset back to zero and then the growth repeated with the reset in the end and so on. My system monitoring shown that for about an hour the amount of data the process written to disk was about 15 gigs, but no such network activity was seen for this process at the same time.

    When I restarted the shell and created a client with monitor=False, this stopped and everything went fine.

    bug priority 
    opened by apollovy 6
  • get_rows() returns empty result, but build_query().execute() is not

    get_rows() returns empty result, but build_query().execute() is not

    I have a simple notion database (in table view) and try to retrieve all rows. collection_view.collection.get_rows returns an empty list, but if I try to retrieve row with collection_view.build_query().execute() it working. I have this issue on a few tables, but other works well with get_rows.

    Do you have any ideas about why it happens?

    question 
    opened by b0g3r 6
  • Failed To Run

    Failed To Run "setup.py" Due To Encoding Error

    image As The Picture Shown, It Seems To Have An Encoding Error When I Tried To Run It.. image And This Error Is Not About The Directory Error ...

    • python 3.10.2
    opened by IceStarDragon707 0
  • Notion crashes when setting CollectionView filter with no id

    Notion crashes when setting CollectionView filter with no id

    I have a collection view that I want to set a filter on. Doing the following works just fine:

    
            view.set('format', {
                 ...
                "property_filters": [
                    {
                        "filter": {
                            "filter": {
                                "value": {
                                    "type": "exact",
                                    "value": <relationid>
                                },
                                "operator": "relation_contains"
                            },
                            "property": "MRxh"
                        }
                    }
                ]
            })
    

    ...with the one exception that the notion page itself will crash if the user tries to modify the filter in notion. The filter works, it filters as expected, but if the user tries to change it in notion, notion shows the following error:

    image

    The page stops crashing if I use an ID for the filter:

                # This no longer crashes
                "property_filters": [
                    {
                        "id": "d7fb...c01",
                        "filter": {
                            "filter": {
                                "value": {
                                    "type": "exact",
                                    "value": <relationid>
                                },
                                "operator": "relation_contains"
                            },
                            "property": "MRxh"
                        }
                    }
                ]
    

    So apparently IDs are required when setting property filters on a view. The question is, how do I generate the ID programmatically? Or should I be setting the filter a different way?

    opened by emmby 2
  • Need to cut a new release

    Need to cut a new release

    Can we get a new cut of notion-py? The README.md examples no longer work out of the box due to https://github.com/jamalex/notion-py/issues/292.

    Sure, notion has an official API now, but notion-py seems to support several things that are not yet supported by the official api.

    opened by emmby 0
  • Uploading image doesn't work

    Uploading image doesn't work

    This worked before but since maybe 2 months ago, it started showing this error message.

    Notion APi HTTPError: 403 Client Error: Forbidden for url: https://www.notion.so/api/v3/getUploadFileUrl

    Does anyone know how to fix it?

    The official API doesn't suppor the image/file upload.

    Thanks,

    opened by nballen-tx 0
  • Not documented: how to set the size of an image

    Not documented: how to set the size of an image

    By default, ImageBlocks take up the entire width of the page. If you have a small image, this can look terrible.

    You can set the dimensions of an image by setting its width, like so:

    image_block = row.children.add_new(ImageBlock)
    image_block.width = 250
    

    Notion will automatically scale the height to keep the aspect ratio.

    Be sure to set the size after uploading an image:

    image_block = row.children.add_new(ImageBlock)
    image_block.upload_file(f)
    image_block.width = 250
    

    Mostly making an issue because I couldn't find the information in this repo. Hopefully this helps someone else.

    opened by konahart 1
Owner
Jamie Alexandre
Jamie Alexandre
Unofficial Python API client for Notion.so

notion-py Unofficial Python 3 client for Notion.so API v3. Object-oriented interface (mapping database tables to Python classes/attributes) Automatic

Jamie Alexandre 3.9k Jan 3, 2023
Notion API Database Python Implementation

Python Notion Database Notion API Database Python Implementation created only by database from the official Notion API. Installing / Getting started p

minwook 78 Dec 19, 2022
Python 3 tools for interacting with Notion API

NotionDB Python 3 tools for interacting with Notion API: API client Relational database wrapper Installation pip install notiondb API client from noti

Viet Hoang 14 Nov 24, 2022
A small repository with convenience functions for working with the Notion API.

Welcome! Within this respository are a few convenience functions to assist with the pulling and pushing of data from the Notion API.

null 10 Jul 9, 2022
TeslaPy - A Python implementation based on unofficial documentation of the client side interface to the Tesla Motors Owner API

TeslaPy - A Python implementation based on unofficial documentation of the client side interface to the Tesla Motors Owner API, which provides functiona

Tim Dorssers 233 Dec 30, 2022
A small Python app to create Notion pages from Jira issues

Jira to Notion This little program will capture a Jira issue and create a corresponding Notion subpage. Mac users can fetch the current issue from the

Dr. Kerem Koseoglu 12 Oct 27, 2022
Discord RPC for Notion written in Python

Discord RPC for Notion This is a program that allows you to add your Notion workspace activities to your Discord profile. This project is currently un

Thuliumitation 1 Feb 10, 2022
A way to export your saved reddit posts to a Notion table.

reddit-saved-to-notion A way to export your saved reddit posts and comments to a Notion table.Uses notion-sdk-py and praw for interacting with Notion

null 19 Sep 12, 2022
Import Notion Tasks to

Notion-to-Google-Calendar (1 way) Import Notion Tasks to Google Calendar NO MORE UPDATES WILL BE MADE TO THIS REPO. Attention has been put on a 2-way

null 12 Aug 11, 2022
A simple object model for the Notion SDK.

A simplified object model for the Notion SDK. This is loosely modeled after concepts found in SQLAlchemy.

Jason Heddings 54 Jan 2, 2023
Token-gate Notion pages

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

John 8 Oct 13, 2022
A script to automate the process of downloading Markdown and CSV backups of Notion

Automatic-Notion-Backup A script to automate the process of downloading Markdown and CSV backups of Notion. In addition, the data is processed to remo

Jorge Manuel Lozano Gómez 2 Nov 2, 2022
A small package to markdownify Notion blocks.

markdownify-notion A small package to markdownify notion blocks. Installation Install this library using pip: $ pip install markdownify-notion Usage

Sergio Sánchez Zavala 2 Oct 29, 2022
Notflix - Notion / Netflix and IMDb to organise your movie dates. Happy Valentine <3 from 0x1za

Welcome to notflix ?? This is a project to help organise shows to watch with my

Mwiza Ed' Simbeye 3 Feb 15, 2022
An API wrapper for Henrik's Unofficial VALORANT API

ValorantAPI.py An API wrapper for Henrik's Unofficial VALORANT API Warning!! This project is still in beta and only contains barely anything yet. If y

Jakkaphat Chalermphanaphan 0 Feb 4, 2022
This package accesses nitrotype's official api along with its unofficial user api

NitrotypePy This package accesses nitrotype's official api along with its unofficial user api. Currently still in development. Install To install, run

The Moon That Rises 2 Sep 4, 2022
An unofficial client library for Google Music.

gmusicapi: an unofficial API for Google Play Music gmusicapi allows control of Google Music with Python. from gmusicapi import Mobileclient api = Mob

Simon Weber 2.5k Dec 15, 2022
An unofficial client library for Google Music.

gmusicapi: an unofficial API for Google Play Music gmusicapi allows control of Google Music with Python. from gmusicapi import Mobileclient api = Mob

Simon Weber 2.5k Dec 15, 2022
Unofficial Meteor Client wiki

Welcome to the Unofficial Meteor Client wiki! Meteor FAQs | A rewritten and better FAQ page. Installation Guide | A guide on how to install Meteor Cli

Anti Cope 0 Feb 21, 2022