OAuthseus

Notion (public connections / OAuth)

Curated guide, researched and checked, updated 2026-10-30 · www.notion.com

Download Markdown
Easy

1-3 hours to a working OAuth connection with no approval; +1-2 weeks only if you want a Marketplace listing

Notion now calls integrations 'connections' and manages them in the Developer portal (app.notion.com/developers/connections). A public (OAuth) connection needs no approval to work for real users: create it, pick an installation scope, add redirect URIs, and you get a client ID/secret in minutes. Only an optional Marketplace listing is reviewed (Notion says 5-10 business days). The real constraint for AI agents is the page picker: your agent only ever sees the pages each user explicitly shares.

How long until your users can connect

Depends on who connects and what you ask for
Your work: 1–3 hoursWaiting on provider: 1–2 weeksUsers can connect

No approval is needed to create or use a public connection with real users. Review happens only if you submit a Marketplace listing (Listings > Connections); the Notion team reviews every submission, including a security review, and says to expect an email reply within 5-10 business days. Rejections can be fixed and resubmitted, which restarts the wait.

Choose your launch path to filter the steps

Do these first

  1. 1Decide installation scope now - pick 'Any workspace' unless you are certain you will never list publicly
  2. 2Create the public connection at app.notion.com/developers/connections with your HTTPS redirect URI and minimal capabilities
  3. 3Have your agent implement the OAuth callback with rotating refresh-token storage
  4. 4Test install from a second workspace and confirm the agent handles 'no pages shared'
  5. 5Only if you want discoverability: prepare listing assets and submit via Listings > Connections (budget 1-2 weeks)

What you're actually registering

Public connection (formerly 'public integration') in the Notion Developer portal. One public connection = your product. Each end user who completes OAuth creates their own authorization (a bot_id) scoped to one workspace and to only the pages they selected in the page picker. If five members of one workspace want to use your agent, each must authorize individually; one user's grant does not cover teammates. The access token acts on behalf of the authorizing user, but can only touch pages shared with the connection (plus their children).

Token exchange at POST https://api.notion.com/v1/oauth/token (HTTP Basic auth with client_id:client_secret) returns access_token, refresh_token, bot_id, workspace_id, owner. Refresh tokens now exist: grant_type=refresh_token returns a NEW access token AND a NEW refresh token, so always persist the latest pair. Since 2026-06-08, new public connections mint a fresh token pair on every authorization (including re-auth) instead of returning the existing one. The REST docs do not state an access-token lifetime and the token response documents no expires_in; build refresh-on-401 rather than assuming tokens never expire. Changing capabilities forces users to re-authenticate. (Hosted Notion MCP is separate: its tokens last ~8 hours and use dynamic client registration.)

What you'll need

  • Notion account + a development workspace

    Public connections are created against a development workspace you belong to. For internal connections you must be a Workspace Owner.

  • Redirect URI(s)

    Entered under the OAuth configuration section. If you register more than one, you must send redirect_uri in the token request.

  • Installation scope decision (permanent)

    'Any workspace' (Marketplace-eligible) or 'Selected workspaces only' (not eligible). Cannot be changed later.

  • Capabilities (content, comments, user info)

    Read content / Update content / Insert content; Read comments / Insert comments; user info: No user information, User information without email addresses, or User information with email addresses. Request the minimum: fewer capabilities make admin approval more likely, and later changes force re-auth.

  • Website, privacy policy URL, terms of use URL, support/contact email, icon

    Older Notion UI (and third-party guides) required these to make an integration public. Current official docs no longer list them for creating a public connection; they appear to have moved to the Marketplace listing / Basic information sections. Have them ready anyway: you will need them for the listing and they appear on the consent and connection menus.

  • Marketplace listing assets

    Listing name and description, category and tags, listing images and logo, and the associated public connection.

  • Notion security review

    Required before Marketplace listing only. Not required to use the connection unlisted.

Step by step

8 steps
  1. 1

    Pick connection type and installation scope

    About 5–15 min

    Agent prepares, you submit

    An agent can lay out the trade-offs; you make the irreversible scope choice.

    1. Internal connection: only your own workspace, static token, no OAuth.
    2. Public connection with 'Any workspace': any Notion user can install via OAuth; Marketplace-eligible. Default choice for an AI agent product.
    3. Public connection with 'Selected workspaces only': OAuth restricted to chosen workspaces; never Marketplace-eligible and subject to Free-plan block limits.
    4. Installation scope cannot be changed after creation - switching later means a new connection and every user re-authorizing.
  2. 2

    Create the public connection in the Developer portal

    About 10–20 min

    You do this

    Requires your Notion login; an agent can draft the name and redirect URIs.

    1. Open the Developer portal at app.notion.com/developers/connections.
    2. In the Build section of the sidebar, select Public connections.
    3. Click Create new connection.
    4. Enter the connection name and choose your development workspace.
    5. Add your redirect URI(s) under the OAuth configuration section (exact match, HTTPS in production).
    6. Choose installation scope: Any workspace or Selected workspaces only (then select workspaces).
    7. Select capabilities: tick only Read content / Update content / Insert content and comment capabilities you need; choose the user-information level (prefer 'User information without email addresses' unless you need email).
    8. Save/create the connection.
    Redirect URI
    https://YOUR_APP_DOMAIN/oauth/notion/callback
    Must exactly match the redirect_uri you send in the authorize and token requests.
    Installation scope
    Any workspace
    Keeps the Marketplace option open; cannot be changed later.
    Developer portalCreating a public connectionCapabilities referencePointer ready: highlights “Public connections”
  3. 3

    Copy OAuth client ID, client secret and authorization URL

    About 5–10 min

    You do this

    Secrets are only visible to you in the logged-in portal; paste them into your secret manager, never into code or chat.

    1. Open your connection and go to the Configuration tab.
    2. Copy the OAuth client ID and OAuth client secret into environment variables (e.g. OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET).
    3. Copy the Authorization URL if shown. If the field is empty, build it yourself: https://api.notion.com/v1/oauth/authorize?client_id=...&response_type=code&owner=user&redirect_uri=...&state=...
    Authorize endpoint
    https://api.notion.com/v1/oauth/authorize?client_id={CLIENT_ID}&response_type=code&owner=user&redirect_uri={URL_ENCODED_REDIRECT}&state={CSRF}
    Token endpoint
    https://api.notion.com/v1/oauth/token
    HTTP Basic auth: base64(client_id:client_secret)
    Authorization guide - step 1Pointer ready: highlights “Configuration”
  4. 4

    Implement authorize, code exchange and refresh-token rotation

    About 45–120 min

    An agent can do this

    Pure code work an AI agent can do end to end once secrets are in env vars.

    1. Send users to the authorize URL with owner=user, response_type=code and a random state; verify state on return.
    2. Handle error=access_denied on the redirect (user pressed Cancel).
    3. POST the code to https://api.notion.com/v1/oauth/token with grant_type=authorization_code (include redirect_uri if it was in the authorize URL or you registered several).
    4. Persist access_token, refresh_token, bot_id, workspace_id, workspace_name and owner per authorization; store every new pair, including on re-authorization.
    5. Refresh with grant_type=refresh_token; replace BOTH tokens with the response (refresh tokens rotate). On invalid_grant, send the user back through OAuth.
    6. Send Notion-Version header on API calls and handle 429 with Retry-After.
    Exchange body
    {"grant_type":"authorization_code","code":"...","redirect_uri":"..."}
    Refresh body
    {"grant_type":"refresh_token","refresh_token":"..."}
  5. 5

    Design the agent around the page picker

    About 20–60 min

    Agent prepares, you submit

    Agent can build the UX and empty-state handling; you decide whether to ship a template.

    1. Tell users before redirecting: 'Select pages' then 'Allow access' - the agent can only see pages they pick (and their children).
    2. Handle the zero-pages case: after connecting, call Search; if empty, prompt the user to re-run OAuth or add the connection to pages via ••• > Connections.
    3. Optionally set 'Notion URL for optional template' (Configuration tab > Basic information) so users can duplicate a starter page that is shared with your connection automatically.
    4. Remember the picker only shows pages the user has full access to, and each workspace member must authorize separately.
    Page picker and template optionPreparing your connection for usersPointer ready: highlights “Configuration”
  6. 6

    Test the full install from a second workspace

    About 15–30 min

    You do this

    Requires clicking through Notion's consent screen as a real Notion user.

    1. Open your authorize URL logged in as a test user in a different workspace.
    2. Confirm the capability prompt, click Select pages, choose a page, click Allow access.
    3. Verify the callback stores tokens and that a refresh works.
    4. Check the connection's Health tab in the Developer portal for failed requests.
    Connection healthAdd & manage connections (Help Center)Pointer ready: highlights “Select pages”
  7. 7

    Create an internal connection (single-workspace path)

    About 10–20 min

    You do this

    Requires Workspace Owner login.

    1. In the Developer portal, under Build, select Internal connections.
    2. Click Create a new connection, enter a name, choose the workspace.
    3. Open the Configuration tab and copy the API token; set capabilities.
    4. Open the Content access tab, click Edit access, and select pages/databases (a new connection has no access by default).
    Internal connectionsPointer ready: highlights “Internal connections”
  8. 8

    Create and submit a Marketplace listing

    About 2–5 hours

    Agent prepares, you submit

    Agent can draft description, tags and image specs; you upload assets, confirm brand/trademark rights and submit.

    1. Open the Marketplace listing dashboard (notion.so/profile/connections).
    2. In the Listings section of the sidebar, select Connections.
    3. Under Drafts, click Start a new connection listing.
    4. Fill in listing name and description, category and tags, listing images and logo, and associate your 'Any workspace' public connection.
    5. Save as draft, review everything, then submit for review; the listing moves to Submitted.
    6. Watch email for feedback (5-10 business days); fix and resubmit if rejected.
    List on the MarketplaceNotion connections galleryPointer ready: highlights “Connections”

What can block you, and the way around

  • Agent 'can't find' a page the user expects

    You'll see: API returns object_not_found / empty Search results even though the page exists in the user's workspace.

    Do this: The page was not selected in the page picker (or is not a child of a selected page). Ask the user to re-run the OAuth flow and select it, or add your connection via the page's ••• > Connections menu. Users can only share pages they have full access to.

  • Wrong installation scope chosen

    You'll see: You picked 'Selected workspaces only' and now cannot list on the Marketplace or install for new customers.

    Do this: Scope can't be edited. Create a new public connection with 'Any workspace', migrate redirect URIs/secrets, and have users re-authorize.

  • Refresh fails with invalid_grant after a refresh

    You'll see: Second refresh using the original refresh_token fails.

    Do this: Refresh tokens rotate: persist the new refresh_token from every refresh and every re-authorization atomically; serialize refreshes per authorization.

  • Enterprise workspace blocks your connection

    You'll see: Users on Enterprise plans cannot find or install your connection.

    Do this: Workspace owners can restrict installs to an approved list. Ask the customer's workspace owner to approve your connection in Settings > Connections > Manage; request minimal capabilities to ease approval.

  • Users forced to re-authorize after you add a capability

    You'll see: Existing users' calls fail or they are prompted to reconnect after you change capabilities.

    Do this: Decide capabilities up front; if you must change them, ship a reconnect prompt and expect drop-off.

  • Block-creation writes fail with 403 on Free workspaces

    You'll see: Create page / append blocks fail on a multi-member Free workspace after the 1,000-block limit grace period.

    Do this: Applies to internal and 'Selected workspaces only' connections, not 'Any workspace' OAuth connections. Use an 'Any workspace' public connection, or ask the workspace to upgrade.

  • Authorization URL field is empty in the portal

    You'll see: Configuration tab shows no Authorization URL for a new public connection.

    Do this: Docs say it populates after the connection is submitted for review; you can construct the authorize URL yourself from client_id, redirect_uri, response_type=code and owner=user.

  • Marketplace listing rejected

    You'll see: Email from Notion declining the listing.

    Do this: Common causes per Notion: brand/trademark issues, quality concerns, or baseline criteria not met. Address feedback and resubmit from Listings > Connections.

What we checked

0 tested 29 documented 0 inferred 1 unverified
  • CorrectedWhere integrations are created and what they are calledCommonly repeated advice says 'create an integration at notion.so/profile/integrations (or my-integrations)'. Current docs call them 'connections' and send developers to the Developer portal (app.notion.com/developers/connections, launched 2026-05-12) under Build > Public connections / Internal connections. notion.so/profile/connections is now the Marketplace listing dashboard.Read against official docs, 2026-10-30
  • CorrectedDo Notion OAuth tokens have refresh tokens / expire?Older advice: Notion access tokens never expire and there are no refresh tokens. Current docs return a refresh_token on exchange and document grant_type=refresh_token, which rotates both tokens. Since 2026-06-08 new public connections mint a fresh pair per authorization. Access-token lifetime itself remains undocumented.Read against official docs, 2026-10-30
  • CorrectedPublic vs internal: 'Distribution' tab toggle to make an integration publicOlder flow converted an internal integration to public via a Distribution tab with company name, website, privacy policy, terms and support email. Current docs: you create a public connection directly and choose an installation scope (Any workspace / Selected workspaces only) that cannot be changed later; listing details live in a separate Listings section.Read against official docs, 2026-10-30
  • ConfirmedMarketplace review timeline and requirementMarketplace guide FAQ: reply within 5-10 business days via email; listing is optional; only 'Any workspace' connections are eligible. Overview: public connections must undergo a Notion security review before being listed.Read against official docs, 2026-10-30
  • ConfirmedPage picker model and per-user authorizationUsers choose pages in the picker; picker shows only pages with full access; each workspace member must authorize individually; access extends to children of shared pages.Read against official docs, 2026-10-30
  • ConfirmedWorkspace owner restrictionsHelp Center: on Enterprise plans workspace owners can restrict which connections members install and maintain an approved list. Internal connections require Workspace Owner to create.Read against official docs, 2026-10-30
  • ConfirmedFree workspace block limit applies to APIFrom 2026-09-01 the REST API enforces the 1,000-block limit on multi-member Free workspaces for internal and 'Selected workspaces only' connections, not 'Any workspace' OAuth connections.Read against official docs, 2026-10-30
  • ConfirmedDeveloper portal and dashboard URLs reachableapp.notion.com/developers/connections, notion.so/profile/connections and notion.so/profile/integrations all returned HTTP 200 (unauthenticated; content behind login not inspected).Live HTTP probe, 2026-10-30
  • Couldn't verifyConnection Gallery Best Practices pageLink from the Marketplace guide redirected to app.notion.com and returned 404.Live HTTP probe, 2026-10-30
  • ConfirmedAutomated: developer console (https://app.notion.com/developers/connections)Loaded: "Notion".Live HTTP probe, 2026-10-30
  • ConfirmedAutomated: authorize endpoint with a fake client_id (https://api.notion.com/v1/oauth/authorize)Endpoint is live; responded 302 redirecting to app.notion.com (usually sign-in before client validation).Live HTTP probe, 2026-10-30
  • ConfirmedAutomated: 30 quotes re-fetched and matched against their cited pages30 of 30 quotes found verbatim in the live page HTML. 13/13 source URLs returned HTTP 200.Read against official docs, 2026-10-30

What we couldn't confirm

  • Access-token lifetime for REST public connections is not documented and the token response documents no expires_in; whether access tokens currently expire (and when) could not be verified.
  • Whether website, privacy policy, terms of use and support email are still mandatory fields anywhere in the new Developer portal could not be confirmed; official docs no longer list them for creating a public connection.
  • The authorization guide says the Authorization URL field populates after a public connection is 'submitted for review', while the Marketplace guide says listing is optional; it is unclear whether a separate non-Marketplace submission step exists in the portal.
  • The 'Notion Connection Gallery Best Practices' page linked from the Marketplace guide returned 404 on 2026-10-30, so detailed listing review criteria could not be read.
  • Exact on-screen labels were taken from docs, not a live console walkthrough (no login performed); labels such as 'Create new connection' vs 'Create a new connection' differ between public and internal guides.
  • 5-10 business days is Notion's stated time to first response; real-world approval time including resubmissions is unknown.

Sources

  1. s1Authorization - Notion Docs (official docs, accessed 2026-10-30)
  2. s2Public connections - Notion Docs (official docs, accessed 2026-10-30)
  3. s3List on the Marketplace - Notion Docs (official docs, accessed 2026-10-30)
  4. s4Overview - Notion Docs (official docs, accessed 2026-10-30)
  5. s5Connection capabilities - Notion API reference (official docs, accessed 2026-10-30)
  6. s6Add & manage connections in Notion - Notion Help (official docs, accessed 2026-10-30)
  7. s7Notion API changelog (official blog, accessed 2026-10-30)
  8. s8Internal connections - Notion Docs (official docs, accessed 2026-10-30)
  9. s9Workspace block limits - Notion API reference (official docs, accessed 2026-10-30)
  10. s10Refresh a token - Notion API reference (official docs, accessed 2026-10-30)
  11. s11Create a token - Notion API reference (official docs, accessed 2026-10-30)
  12. s12Build an MCP client for Notion - Notion Docs (official docs, accessed 2026-10-30)
  13. s13Notion provider guide - Ampersand docs (community, accessed 2026-10-30)
  14. p1Live probe (console): Loaded: "Notion". (probe, accessed 2026-10-30)
  15. p2Live probe (authorize-endpoint): Endpoint is live; responded 302 redirecting to app.notion.com (usually sign-in before client validat (probe, accessed 2026-10-30)