Authorization

Integrations can be authorized for a single workspace or use OAuth to access multiple workspaces. Learn about implementing the right authorization for your integration.

Overview

The Notion API uses bearer tokens to authorize requests from integrations. As an integration developer, you'll need to choose the appropriate integration type for the integration you create. Based on the integration type, you'll receive and store bearer tokens differently. For both types, an integration must send the bearer token in the HTTP Authorization request header, as shown:

GET /v1/pages/b55c9c91-384d-452b-81db-d1ef79372b75 HTTP/1.1
Authorization: Bearer {MY_NOTION_TOKEN}

Integrations are granted access to resources (pages and databases) which users have shared with the integration. Once an integration has been added to a workspace by an Admin, users see the integration within Share menus inside Notion. Any user in the workspace can grant access to additional resources by sharing those resources with the integration.

📘

Integrations have broad access to resources

When a user grants an integration access to a page or databases, the integration can read and write to that resource and its children. In the future, integrations may be allowed to request specific kinds of access (such as read-only) to give users more clarity and control.

Integration types

There are two types of integrations:

  1. Internal integrations are used to integrate the tools and services in use by you and your team in a way that's tailored to your people, workflows, and resources.
  2. Public OAuth integrations are used to build a product that is used by a broad audience, across many Notion workspaces.

By default, newly created integrations are internal integrations. After creation, the type can be changed to public integration in the integration settings.

Internal integrations are much simpler to develop. Public integrations require additional configuration and implement the client side of OAuth 2.0. Read on for details on how to implement authorization for each integration type.

Authorizing internal integrations

Internal integrations simply use a single integration token as the bearer token for all requests. In order to create an internal integration, you must choose an associated workspace. You must have Admin access level within the workspace you choose.

📘

Not an admin in your current workspace?

You can start building right now by creating a new personal workspace. Later, you can ask an admin to help you move the integration into another workspace. This may require using a different token, which is easy to do if you keep the token outside of source code using environment variables.

You can view the integration token later in the integration settings. This token is a secret. You should avoid storing it in your source code and avoid committing it in version control. Instead, we recommend reading the the token from an environment variable in your source code, and using a secret manager or deployment system to set the the token in the environment.

In each API request, send the token in the Authorization header as shown:

GET /v1/pages/b55c9c91-384d-452b-81db-d1ef79372b75 HTTP/1.1
Authorization: Bearer {MY_NOTION_TOKEN}

Authorizing public integrations

Public OAuth integrations receive an access token each time a user grants the integration access. This process follows OAuth 2.0 using an authorization code grant, described in a few simple steps below.

The integration stores all the access tokens it receives (typically in a database) and chooses one as the bearer token for each request the integration sends to the Notion API.

📘

During the Notion API public beta

We strongly recommend labeling your integration as "beta" or "preview" while the Notion API is in beta. This sets the right expectations with users as the API continues to evolve.

Currently, Notion does not review public integrations and does not list all public integrations in a directory. You may help users discover your integration by promoting it in your own product and in your marketing initiatives.

Prompting users to add an integration

The first step in the OAuth process is to request authorization from a user. This is done by sending a user to the authorization URL. You may send the user to this URL with a simple hyperlink or a redirect from another request.

The authorization URL is created using a few parameters. The URL begins with https://api.notion.com/v1/oauth/authorize and the parameters are added in the query string.

ParameterDescriptionRequired
client_idAn identifier for your integration, found in the integration settings
redirect_uriA URL where the user should return after granting access. This is described in detail below.
response_typeAlways use code
stateIf the user was in the middle of an interaction or operation, this parameter can be used to restore state after the user returns. It is also can be used to prevent CSRF attacks.

As an example, the following hyperlink can be used to request authorization from a user:

<a href="https://api.notion.com/v1/oauth/authorize?client_id=463558a3-725e-4f37-b6d3-0889894f68de&redirect_uri=https%3A%2F%2Fexample.com%2Fauth%2Fnotion%2Fcallback&response_type=code">Add to Notion</a>

🚧

Limitations

  • Only one access token can be granted for an integration in a given workspace.
  • Only users with Admin access to a workspace can grant an access token using OAuth.

In the future, these limitations may be lifted or changed.

📘

Reauthorization

After the remaining steps are complete and the integration is added to the workspace, other users cannot use OAuth to authorize the integration in the same workspace. If a different user visits the authorization URL and chooses the same workspace, that user will see an error preventing the reauthorization.

If the initial user to authorize the integration in a workspace visits the authorization URL and chooses the same workspace, that user may reauthorize the integration. During reauthorization, the page picker will not be shown. The access token received after exchanging the grant will be the same as the initial access token received.

User grants access

Once a user is sent to the authorization URL, they see a prompt to choose whether to grant the integration access or not.

Integration authorization

If the user grants access, they are shown a page picker next. The page picker allows the user to select resources to share with your integration while granting access for convenience. Next, the user is redirected to the redirect_uri with a temporary authorization code (code).

Page picker

If the user denies access, they are redirected to the redirect_uri with an error (error).

Exchanging the grant for an access token

After the user grants access, the integration will receive an incoming request to the redirect_uri with the following information in the query string.

ParameterDescriptionRequired
codeA temporary authorization code
stateThe value provided by the integration when the user was prompted for access.

Finally, the integration exchanges the authorization code for an access token by sending an HTTP POST request to Notion's token URL: https://api.notion.com/v1/oauth/token. This request is authorized using HTTP Basic Authentication, using the integration's client_id and client_secret (found in the integration settings) to create a credential: {client_id}:{client_secret}. Please note, in HTTP Basic Authentication, the credentials are base64 encoded before adding to the Authorization header.

The body of the request contains the following JSON-encoded fields:

FieldTypeDescriptionRequired
"grant_type"stringAlways use "authorization_code"
"code"stringThe temporary authorization code received in the incoming request to the
"redirect_uri"stringThe "redirect_uri" that was provided in the Authorization step

The following is an example request to exchange the authorization code for an access token:

POST /v1/oauth/token HTTP/1.1
Authorization: Basic NDYzNTU4YTMtNzI1ZS00ZjM3LWI2ZDMtMDg4OTg5NGY2OGRlOnNlY3JldF95b3VfZm91bmRfbXlfZmFrZV9zZWNyZXQ=
Content-Type: application/json

{"grant_type":"authorization_code","code":"e202e8c9-0990-40af-855f-ff8f872b1ec6", "redirect_uri":"https://example.com/auth/notion/callback"}

Notion will respond to the request with an access token and some additional information. The response contains the following JSON-encoded fields:

FieldTypeDescriptionRequired
"access_token"stringAn access token used to authorize requests to the Notion API.
"workspace_name"stringA human-readable name which can be used to display this authorization in UI
"workspace_icon"stringA URL to an image which can be used to display this authorization in UI
"bot_id"stringAn identifier for this authorization

Tips for storing and using access tokens

  • Store all of the information your integration receives with the access token. You never know when your UI requirements or product requirements might change, and you find some use of this data. It's really hard (or impossible) to send users to authorize again to get this information.
  • When storing this information in a database, build relations between this information and the resources in Notion that you are accessing. For example, if you store a Notion database or page ID, relate those records with the correct access token that you can use to authorize requests when reading or writing to that database or page.

Handling errors

Integrations should be prepared for two kinds of errors: user authorization failures and token request failures.

User authorization failures

User authorization failures occur when Notion cannot create an authorization code before redirecting back to the redirect_uri. This type of failure is normal - a user simply choosing not to approve the authorization request will trigger a failure. Integrations should be built to handle these cases gracefully.

In some cases, Notion sends the user back to the redirect_uri with additional error query parameter. Integrations should present the user with a helpful user interface. Notion uses the common error codes in the OAuth specification. In other cases, Notion shows the error to the user without redirecting. These are logical errors and should be remedied by updating the integration implementation.

Token request failures

Token request failures occur when the integration attempts to exchange the code grant for an access token, but something goes wrong. In these cases, the response contains a JSON-encoded body with an "error" field. Once again, Notion uses the common error codes from the OAuth specification.

Updated 26 days ago


Authorization


Integrations can be authorized for a single workspace or use OAuth to access multiple workspaces. Learn about implementing the right authorization for your integration.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.