# Notion (public connections / OAuth): OAuth app setup guide

> Curated guide, updated 2026-10-30. Source: https://oauthseus.vercel.app/guides/notion

**Difficulty:** easy. 1-3 hours to a working OAuth connection with no approval; +1-2 weeks only if you want a Marketplace listing _[documented s3,s2]_

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.

**Your work:** 1–3 hours. **Waiting on provider:** 1–2 weeks (review depends on path).

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.

## Launch paths

| Path | Difficulty | Your work | Provider wait |
|---|---|---|---|
| Internal connection (your own workspace only) | easy | 10–30 min | None |
| Public connection, 'Selected workspaces only' (OAuth, private beta/design partners) | easy | 1–3 hours | None |
| Public connection, 'Any workspace', not listed (default for an AI agent product) | easy | 1–3 hours | None |
| Public connection listed on the Notion Marketplace | moderate | 3–8 hours | 1–2 weeks |

## Do these first

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

## What you're 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. _[documented s1]_
- **Redirect URI(s)**: Entered under the OAuth configuration section. If you register more than one, you must send redirect_uri in the token request. _[documented s1]_
- **Installation scope decision (permanent)**: 'Any workspace' (Marketplace-eligible) or 'Selected workspaces only' (not eligible). Cannot be changed later. _[documented s2]_
- **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. _[documented s5]_
- **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. _[unverified s13]_
- **Marketplace listing assets**: Listing name and description, category and tags, listing images and logo, and the associated public connection. _[documented s3]_
- **Notion security review**: Required before Marketplace listing only. Not required to use the connection unlisted. _[documented s4]_

## Steps

### 1. Pick connection type and installation scope (5–15 min, agent prepares, you submit)

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.

[Public connections: installation scope](https://developers.notion.com/guides/get-started/public-connections#installation-scope) · [Connection types overview](https://developers.notion.com/guides/get-started/overview) _[documented s2]_

### 2. Create the public connection in the Developer portal (10–20 min, you)

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 portal](https://app.notion.com/developers/connections) · [Creating a public connection](https://developers.notion.com/guides/get-started/public-connections#creating-a-public-connection) · [Capabilities reference](https://developers.notion.com/reference/capabilities) _[documented s1]_

### 3. Copy OAuth client ID, client secret and authorization URL (5–10 min, you)

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 1](https://developers.notion.com/guides/get-started/authorization#public-connection-auth-flow-set-up) _[documented s1]_

### 4. Implement authorize, code exchange and refresh-token rotation (45–120 min, agent can do)

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":"..."}`

[Authorization guide](https://developers.notion.com/guides/get-started/authorization) · [Create a token](https://developers.notion.com/reference/create-a-token) · [Refresh a token](https://developers.notion.com/reference/refresh-a-token) _[documented s10]_

### 5. Design the agent around the page picker (20–60 min, agent prepares, you submit)

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 option](https://developers.notion.com/guides/get-started/authorization#prompt-for-a-connection-with-a-notion-template-option) · [Preparing your connection for users](https://developers.notion.com/guides/get-started/preparing-for-users) _[documented s1]_

### 6. Test the full install from a second workspace (15–30 min, you)

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 health](https://developers.notion.com/guides/manage-connections/connection-health) · [Add & manage connections (Help Center)](https://www.notion.com/help/add-and-manage-connections-with-the-api) _[documented s6]_

### 7. Create an internal connection (single-workspace path) (10–20 min, you)

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 connections](https://developers.notion.com/guides/get-started/internal-connections) _[documented s8]_

### 8. Create and submit a Marketplace listing (2–5 hours, agent prepares, you 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 Marketplace](https://developers.notion.com/guides/get-started/marketplace-listing) · [Notion connections gallery](https://www.notion.com/integrations/all) _[documented s3]_

## Blockers

- **Agent 'can't find' a page the user expects** (high). Symptom: API returns object_not_found / empty Search results even though the page exists in the user's workspace. Fix: 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. _[documented s1]_
- **Wrong installation scope chosen** (high). Symptom: You picked 'Selected workspaces only' and now cannot list on the Marketplace or install for new customers. Fix: Scope can't be edited. Create a new public connection with 'Any workspace', migrate redirect URIs/secrets, and have users re-authorize. _[documented s2]_
- **Refresh fails with invalid_grant after a refresh** (medium). Symptom: Second refresh using the original refresh_token fails. Fix: Refresh tokens rotate: persist the new refresh_token from every refresh and every re-authorization atomically; serialize refreshes per authorization. _[documented s7]_
- **Enterprise workspace blocks your connection** (medium). Symptom: Users on Enterprise plans cannot find or install your connection. Fix: 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. _[documented s6]_
- **Users forced to re-authorize after you add a capability** (medium). Symptom: Existing users' calls fail or they are prompted to reconnect after you change capabilities. Fix: Decide capabilities up front; if you must change them, ship a reconnect prompt and expect drop-off. _[documented s5]_
- **Block-creation writes fail with 403 on Free workspaces** (low). Symptom: Create page / append blocks fail on a multi-member Free workspace after the 1,000-block limit grace period. Fix: 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. _[documented s9]_
- **Authorization URL field is empty in the portal** (low). Symptom: Configuration tab shows no Authorization URL for a new public connection. Fix: 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. _[documented s1]_
- **Marketplace listing rejected** (medium). Symptom: Email from Notion declining the listing. Fix: Common causes per Notion: brand/trademark issues, quality concerns, or baseline criteria not met. Address feedback and resubmit from Listings > Connections. _[documented s3]_

## Agent vs. you

**An agent can:**
- Explain internal vs public vs PAT and recommend an installation scope
- Draft connection name, redirect URIs and a minimal capability set
- Write the full OAuth code: authorize URL with state, callback, code exchange, rotating refresh-token storage, invalid_grant re-auth
- Build page-picker UX: pre-auth explainer, empty-access detection via Search, reconnect prompts
- Draft Marketplace listing copy, tags, and privacy policy / terms drafts for your review
- Monitor the connection's Health tab data and API 429/403 handling in code

**You must:**
- Log in to Notion and create the connection in the Developer portal (agent must not handle your credentials)
- Make the permanent installation-scope choice
- Copy the client secret into your secret manager
- Click through the consent screen (Select pages / Allow access) to test
- Approve legal text (privacy policy, terms), confirm brand/trademark rights, upload listing assets, and submit the Marketplace listing
- Coordinate with customers' Enterprise workspace owners to get your connection allow-listed

## 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.

## Verification log

- 2026-10-30 · doc-review · **corrected**: Where integrations are created and what they are called. Commonly 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.
- 2026-10-30 · doc-review · **corrected**: Do 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.
- 2026-10-30 · doc-review · **corrected**: Public vs internal: 'Distribution' tab toggle to make an integration public. Older 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.
- 2026-10-30 · doc-review · **confirmed**: Marketplace review timeline and requirement. Marketplace 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.
- 2026-10-30 · doc-review · **confirmed**: Page picker model and per-user authorization. Users 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.
- 2026-10-30 · doc-review · **confirmed**: Workspace owner restrictions. Help Center: on Enterprise plans workspace owners can restrict which connections members install and maintain an approved list. Internal connections require Workspace Owner to create.
- 2026-10-30 · doc-review · **confirmed**: Free workspace block limit applies to API. From 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.
- 2026-10-30 · http-probe · **confirmed**: Developer portal and dashboard URLs reachable. app.notion.com/developers/connections, notion.so/profile/connections and notion.so/profile/integrations all returned HTTP 200 (unauthenticated; content behind login not inspected).
- 2026-10-30 · http-probe · **unverifiable**: Connection Gallery Best Practices page. Link from the Marketplace guide redirected to app.notion.com and returned 404.
- 2026-10-30 · http-probe · **confirmed**: Automated: developer console (https://app.notion.com/developers/connections). Loaded: "Notion".
- 2026-10-30 · http-probe · **confirmed**: Automated: 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).
- 2026-10-30 · doc-review · **confirmed**: Automated: 30 quotes re-fetched and matched against their cited pages. 30 of 30 quotes found verbatim in the live page HTML.  13/13 source URLs returned HTTP 200.

## Sources

- s1: [Authorization - Notion Docs](https://developers.notion.com/guides/get-started/authorization) (official-docs, accessed 2026-10-30)
- s2: [Public connections - Notion Docs](https://developers.notion.com/guides/get-started/public-connections) (official-docs, accessed 2026-10-30)
- s3: [List on the Marketplace - Notion Docs](https://developers.notion.com/guides/get-started/marketplace-listing) (official-docs, accessed 2026-10-30)
- s4: [Overview - Notion Docs](https://developers.notion.com/guides/get-started/overview) (official-docs, accessed 2026-10-30)
- s5: [Connection capabilities - Notion API reference](https://developers.notion.com/reference/capabilities) (official-docs, accessed 2026-10-30)
- s6: [Add & manage connections in Notion - Notion Help](https://www.notion.com/help/add-and-manage-connections-with-the-api) (official-docs, accessed 2026-10-30)
- s7: [Notion API changelog](https://developers.notion.com/page/changelog) (official-blog, accessed 2026-10-30)
- s8: [Internal connections - Notion Docs](https://developers.notion.com/guides/get-started/internal-connections) (official-docs, accessed 2026-10-30)
- s9: [Workspace block limits - Notion API reference](https://developers.notion.com/reference/workspace-block-limits) (official-docs, accessed 2026-10-30)
- s10: [Refresh a token - Notion API reference](https://developers.notion.com/reference/refresh-a-token) (official-docs, accessed 2026-10-30)
- s11: [Create a token - Notion API reference](https://developers.notion.com/reference/create-a-token) (official-docs, accessed 2026-10-30)
- s12: [Build an MCP client for Notion - Notion Docs](https://developers.notion.com/guides/mcp/build-mcp-client) (official-docs, accessed 2026-10-30)
- s13: [Notion provider guide - Ampersand docs](https://docs.ampersand.ai/provider-guides/notion) (community, accessed 2026-10-30)
- p1: [Live probe (console): Loaded: "Notion".](https://app.notion.com/developers/connections) (probe, accessed 2026-10-30)
- p2: [Live probe (authorize-endpoint): Endpoint is live; responded 302 redirecting to app.notion.com (usually sign-in before client validat](https://api.notion.com/v1/oauth/authorize) (probe, accessed 2026-10-30)

Evidence tags: tested = exercised live; documented = official source, quote checked; inferred = reasoning; unverified = unconfirmed.