Notion SDK for JavaScript
A JavaScript and TypeScript client for the Notion API. This reference covers the SDK's methods, options, and helpers.
Installation
npm install @notionhq/client
Usage
[!NOTE] For setup steps, see Notion's getting started guide.
Client accepts an integration token or an OAuth access token.
const { Client } = require("@notionhq/client")
const notion = new Client({
auth: process.env.NOTION_TOKEN,
})
Make a request to any Notion API endpoint.
;(async () => {
const listUsersResponse = await notion.users.list({})
console.log(listUsersResponse)
})()
[!NOTE] See the complete list of endpoints in the API reference.
Request methods return a Promise with the response. For example:
{
results: [
{
object: "user",
id: "d40e767c-d7af-4b18-a86d-55c61f1e39a4",
type: "person",
person: {
email: "[email protected]",
},
name: "Avocado Lovelace",
avatar_url:
"https://secure.notion-static.com/e6a352a8-8381-44d0-a1dc-9ed80e62b53d.jpg",
},
// ...
]
}
Endpoint parameters are grouped into a single object. You don't need to remember which parameters go in the path, query, or body.
const myPage = await notion.dataSources.query({
data_source_id: "897e5a76-ae52-4b48-9fdf-e71f5945d1af",
filter: {
property: "Landmark",
rich_text: {
contains: "Bridge",
},
},
})
Handling errors
Notion API errors reject the request with an APIResponseError. The code property identifies the error. APIErrorCode contains the known server error codes.
const {
Client,
APIErrorCode,
isNotionClientError,
} = require("@notionhq/client")
try {
const notion = new Client({ auth: process.env.NOTION_TOKEN })
const myPage = await notion.dataSources.query({
data_source_id: dataSourceId,
filter: {
property: "Landmark",
rich_text: {
contains: "Bridge",
},
},
})
} catch (error) {
if (
isNotionClientError(error) &&
error.code === APIErrorCode.ObjectNotFound
) {
// Ask the user to select a different data source.
} else {
// Other error handling code
console.error(error)
}
}
Logging
The default logger writes warnings and errors to the console. LogLevel.DEBUG also logs response bodies.
const { Client, LogLevel } = require("@notionhq/client")
const notion = new Client({
auth: process.env.NOTION_TOKEN,
logLevel: LogLevel.DEBUG,
})
A custom logger receives logLevel, message, and extraInfo. It should return no value.
Client options
The Client constructor accepts one options object.
| Option | Default value | Type | Description |
|---|---|---|---|
auth |
undefined |
string |
Bearer token for authentication. If left undefined, the auth parameter should be set on each request. |
logLevel |
LogLevel.WARN |
LogLevel |
Verbosity of logs the instance will produce. By default, logs are written to stdout. |
timeoutMs |
DEFAULT_TIMEOUT_MS |
number |
Number of milliseconds to wait before emitting a RequestTimeoutError |
baseUrl |
DEFAULT_BASE_URL |
string |
The root URL for sending API requests. This can be changed to test with a mock server. |
logger |
Log to console | Logger |
A custom logging function. This function is only called when the client emits a log that is equal or greater severity than logLevel. |
agent |
Default node agent | http.Agent |
Used to control creation of TCP sockets. A common use is to proxy requests with https-proxy-agent |
retry |
See constants | RetryOptions |
Configuration for automatic retries on rate limits (429), service overloads (529), and server errors (500, 503). See Automatic retries below. |
Automatic retries
The client retries failed requests up to 2 times by default. Delays increase with each retry and include a random offset.
Retried errors:
rate_limited(HTTP 429) - Too many requests; retried for all HTTP methodsservice_overload(HTTP 529) - Service overloaded; retried for all HTTP methodsinternal_server_error(HTTP 500) - Server error; retried only for GET and DELETEservice_unavailable(HTTP 503) - Service temporarily unavailable; retried only for GET and DELETE
For server errors, only GET and DELETE are retried to avoid repeating writes. The client uses the Retry-After header when present. It accepts a delay in seconds or an HTTP date.
Retry options:
const notion = new Client({
auth: process.env.NOTION_TOKEN,
retry: {
maxRetries: 5, // Maximum retry attempts (default: 2)
initialRetryDelayMs: 500, // Initial delay between retries (default: 1000ms)
maxRetryDelayMs: 60000, // Maximum delay between retries (default: 60000ms)
},
})
To disable automatic retries:
const notion = new Client({
auth: process.env.NOTION_TOKEN,
retry: false,
})
Constants
The SDK exports these defaults and Notion-specific values:
const {
DEFAULT_BASE_URL, // "https://api.notion.com"
DEFAULT_TIMEOUT_MS, // 60_000
DEFAULT_MAX_RETRIES, // 2
DEFAULT_INITIAL_RETRY_DELAY_MS, // 1_000
DEFAULT_MAX_RETRY_DELAY_MS, // 60_000
MIN_VIEW_COLUMN_WIDTH, // 32
} = require("@notionhq/client")
MIN_VIEW_COLUMN_WIDTH is the minimum table column width in pixels. A column at this width appears collapsed. For example:
await notion.views.create({
database_id: databaseId,
name: "My view",
type: "table",
configuration: {
table: {
properties: [
{
property_id: checkboxPropId,
visible: true,
width: MIN_VIEW_COLUMN_WIDTH,
},
],
},
},
})
TypeScript
The package includes types for request parameters, responses, and their fields.
With strict TypeScript, caught errors have type unknown. isNotionClientError
narrows the error to a known SDK error type. APIErrorCode identifies server
errors; ClientErrorCode identifies errors raised by the client.
import {
APIErrorCode,
ClientErrorCode,
isNotionClientError,
} from "@notionhq/client"
try {
const response = await notion.dataSources.query({
data_source_id: dataSourceId,
})
} catch (error: unknown) {
if (isNotionClientError(error)) {
// error is now strongly typed to NotionClientError
switch (error.code) {
case ClientErrorCode.RequestTimeout:
// ...
break
case APIErrorCode.ObjectNotFound:
// ...
break
case APIErrorCode.Unauthorized:
// ...
break
default:
console.error(error)
}
}
}
Type guards
These type guards distinguish full API responses from partial responses.
| Type guard function | Purpose |
|---|---|
isFullPage |
Determine whether an object is a full PageObjectResponse |
isFullBlock |
Determine whether an object is a full BlockObjectResponse |
isFullDataSource |
Determine whether an object is a full DataSourceObjectResponse |
isFullPageOrDataSource |