I've recently published my first Notion handbook and would like to share with you how I managed to auto-update the workspace permissions immediately after a customer's payment goes through!
The reasoning behind the ability to instantly access the handbook's workspace is that people aren't used to purchasing digital products and having to wait while the author is AFK and possibly in a completely different time zone.
The following guide may be too technical. If you're rather a no-code aficionado, scroll to the bottom of this post for an alternative.
My landing page runs on Next.js and contains a few CTA buttons. Clicking on any of these creates a standard stripe Checkout Session via a Vercel serverless function. The checkout session is then passed back onto the frontend which redirects to the stripe-hosted Checkout page. When the payment goes through, I listen to the charge.succeeded webhook event and that's where the "magic" happens.
Notion hasn't opened its planned API to the public yet so I had to resort to the unofficial Python API client. I wanted to run it within a serverless function on Vercel, but Vercel itself, afaik, runs on AWS. Now, it appeared that AWS's lambda python runtime was so sandboxed that it was blocking even basic Notion login methods so I chose to run it in a GCP Cloud Function instead — as lots of components of the IndieHackers platform do too 😉.
As it turns out, I was of course not the only one looking for ways to automate adding access to my workspace. There's an open GH issue based on which I came up with my own approach:
pip install notion
from notion.client import NotionClient
429 Too Many Requests
. On the other hand, when you log out of Notion and log back in, the v2_token
will have changed which'd require you to re-deploy the cloud function or replace its environment variables! In any event, it's good to provide a fallback:try:
client = NotionClient(email="...", password="...")
except Exception:
client = NotionClient(token_v2="...")
page = client.get_block("https://www.notion.so/elasticsearchbook/...")
uid = client.post('findUser', data=dict(email="[email protected]"))\
.json()\
.get('value', {})\
.get('value', {})\
.get('id', {})
uid = client\
.post('createEmailUser',
data=dict(
email="[email protected]",
preferredLocale="en-US",
preferredLocaleOrigin="inferred_from_inviter"
)).json().get('userId', None)
uid
work with, you can set that user's permissions. The "Can View" mode I was after required the reader
role: user_permissions_dict = {
'role': 'reader',
'type': 'user_permission',
'user_id': uid
}
# append the user permissions to the local cached dictionary object
page.get()['permissions'].append(user_permissions_dict)
# update the permissions
page.set(path=['permissions'], value=page.get()['permissions'])
# make sure they're in
assert uid in [u.get('user_id', None)
for u in page.get()['permissions']]
And voilà — if everything went right, your customer will have received an invitation link from Notion!
Note that all children pages inherit the parent permissions, as explained here.
Something tells me that this'd be a perfect candidate for a Zapier workflow. If you're like me and create member-only workspaces through Notion but need a low-effort, automated way to assign permissions, feel free to fill out my Typeform and maybe I can help!
Over and out ✌️
very cool! thanks for sharing!
Thanks!
Super cool! Is it hard to market?
BTW I should mention that posting on Reddit and HackerNews helped a lot. More on that in this IH post: https://www.indiehackers.com/post/a-well-timed-show-hackernews-post-brings-in-10-new-paying-customers-a-mini-analysis-e55ce6a2e0
Thanks! It's a niche within a niche so it's appropriately hard.
But I rely on writing high-quality content on StackOverflow so that people are drawn to the book's page out of curiosity. Lots of them convert when they've arrived through the SO funnel.
On top of that, I'm building backlinks to climb the SEO ranks.
One step at a time.