### Example Project Commands Source: https://github.com/makenotion/notion-sdk-js/blob/main/CLAUDE.md Commands to manage dependencies and type-checking for example projects. ```bash npm run install:examples # Install dependencies for all example projects npm run examples:typecheck # Type-check all examples ``` -------------------------------- ### Client Initialization Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/client.md Examples of initializing the Client class with different configurations, including basic setup, custom options, and disabling retries. ```typescript import { Client, LogLevel } from "@notionhq/client" // Basic initialization const notion = new Client({ auth: process.env.NOTION_TOKEN, }) // With custom configuration const client = new Client({ auth: process.env.NOTION_TOKEN, logLevel: LogLevel.DEBUG, timeoutMs: 30000, retry: { maxRetries: 5, initialRetryDelayMs: 500, maxRetryDelayMs: 30000, }, }) // Disable retries const noRetryClient = new Client({ auth: process.env.NOTION_TOKEN, retry: false, }) ``` -------------------------------- ### Response example Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of a response from the users.list endpoint. ```typescript { results: [ { object: "user", id: "d40e767c-d7af-4b18-a86d-55c61f1e39a4", type: "person", person: { email: "avo@example.org", }, name: "Avocado Lovelace", avatar_url: "https://secure.notion-static.com/e6a352a8-8381-44d0-a1dc-9ed80e62b53d.jpg", }, // ... ] } ``` -------------------------------- ### Usage Example: Get Current Bot/Integration Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-core.md Example of how to retrieve details of the current bot/integration. ```typescript const bot = await notion.users.me({}) console.log(bot.name) // Bot/integration name console.log(bot.id) // Bot ID ``` -------------------------------- ### Usage Example: List Users Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-core.md Example of how to list users, including pagination. ```typescript const users = await notion.users.list({ page_size: 50, }) for (const user of users.results) { console.log(`${user.name} (${user.id})`) } // Paginate if (users.has_more) { const nextPage = await notion.users.list({ start_cursor: users.next_cursor, }) } ``` -------------------------------- ### Retry Configuration Examples Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Examples demonstrating how to configure retry behavior for the Notion client. ```typescript import { Client } from "@notionhq/client" // Custom retry configuration const notion = new Client({ auth: process.env.NOTION_TOKEN, retry: { maxRetries: 5, initialRetryDelayMs: 500, maxRetryDelayMs: 30000, }, }) // Disable retries const noRetryClient = new Client({ auth: process.env.NOTION_TOKEN, retry: false, }) // Use defaults const defaultRetryClient = new Client({ auth: process.env.NOTION_TOKEN, // retry: defaults to { maxRetries: 2, initialRetryDelayMs: 1000, maxRetryDelayMs: 60000 } }) ``` -------------------------------- ### Logging Examples Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Provides examples of configuring default console logging and custom loggers for different scenarios. ```typescript import { Client, LogLevel } from "@notionhq/client" // Debug logging to console (default behavior) const notion = new Client({ auth: process.env.NOTION_TOKEN, logLevel: LogLevel.DEBUG, }) // Custom logger to send logs elsewhere const customLogger = (level, message, extraInfo) => { if (level === LogLevel.ERROR) { console.error(`[${level}] ${message}`, extraInfo) } else if (level === LogLevel.WARN) { console.warn(`[${level}] ${message}`, extraInfo) } } const notion2 = new Client({ auth: process.env.NOTION_TOKEN, logLevel: LogLevel.INFO, logger: customLogger, }) // Log to external service const externalLogger = (level, message, extraInfo) => { fetch("https://logs.example.com/log", { method: "POST", body: JSON.stringify({ level, message, extraInfo }), }) } const notion3 = new Client({ auth: process.env.NOTION_TOKEN, logger: externalLogger, }) ``` -------------------------------- ### Usage Example (Fastify) Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md An example of how to use verifyWebhookSignature with Fastify. ```typescript import Fastify from "fastify" import { verifyWebhookSignature } from "@notionhq/client" const fastify = Fastify() fastify.post("/notion-webhook", async (request, reply) => { const verified = await verifyWebhookSignature({ body: request.rawBody, // Fastify provides raw body signature: request.headers["x-notion-signature"], verificationToken: process.env.NOTION_WEBHOOK_VERIFICATION_TOKEN, }) if (!verified) { return reply.status(401).send("Invalid signature") } const event = JSON.parse(request.rawBody) console.log("Event type:", event.type) reply.status(200).send("ok") }) ``` -------------------------------- ### Installation Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Install the Notion SDK for JavaScript using npm. ```bash npm install @notionhq/client ``` -------------------------------- ### SelectDatabaseProperty Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md An example of a single-choice select database property configuration. ```typescript { id: "abc", name: "Status", type: "select", select: { options: [ { id: "1", name: "Not started", color: "red" }, { id: "2", name: "In progress", color: "yellow" }, { id: "3", name: "Done", color: "green" } ] } } ``` -------------------------------- ### Usage Example (Express) Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md An example of how to use verifyWebhookSignature with Express.js. ```typescript import express from "express" import { verifyWebhookSignature } from "@notionhq/client" const app = express() app.post("/notion-webhook", express.text({ type: "application/json" }), async (req, res) => { const verified = await verifyWebhookSignature({ body: req.body, // Raw text body, not JSON signature: req.header("x-notion-signature"), verificationToken: process.env.NOTION_WEBHOOK_VERIFICATION_TOKEN, }) if (!verified) { return res.status(401).send("Invalid signature") } // Parse and handle the event const event = JSON.parse(req.body) console.log("Webhook event:", event) res.status(200).send("ok") }) ``` -------------------------------- ### Usage Example: Create Comment Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-core.md Example of how to create a comment on a Notion page. ```typescript const comment = await notion.comments.create({ parent: { page_id: "page_id", }, rich_text: [ { type: "text", text: { content: "Great work! 🎉", }, }, ], }) ``` -------------------------------- ### Usage Example (Testing) Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md An example demonstrating how to use `signWebhookPayload` and `verifyWebhookSignature` for testing webhook handlers. ```typescript import { signWebhookPayload, verifyWebhookSignature } from "@notionhq/client" async function testWebhookHandler() { const verificationToken = "your_verification_token" const body = JSON.stringify({ object: "event", type: "page.created", id: "abc123", created_time: "2024-01-01T00:00:00.000Z", }) // Generate signature for testing const signature = await signWebhookPayload({ body, verificationToken, }) // Verify it works const isValid = await verifyWebhookSignature({ body, signature, verificationToken, }) console.log("Signature valid:", isValid) // true } ``` -------------------------------- ### MultiSelectDatabaseProperty Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md An example of a multiple-choice multi-select database property configuration. ```typescript { id: "def", name: "Tags", type: "multi_select", multi_select: { options: [ { id: "1", name: "Important", color: "red" }, { id: "2", name: "Bug", color: "purple" } ] } } ``` -------------------------------- ### Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md This example demonstrates how to verify a webhook signature and process an incoming event. ```typescript import { verifyWebhookSignature, PageCreatedWebhookPayload } from "@notionhq/client" app.post("/webhook", express.text({ type: "application/json" }), async (req, res) => { const verified = await verifyWebhookSignature({ body: req.body, signature: req.header("x-notion-signature"), verificationToken: process.env.NOTION_WEBHOOK_VERIFICATION_TOKEN, }) if (!verified) { return res.status(401).send("Invalid signature") } const event: PageCreatedWebhookPayload = JSON.parse(req.body) console.log(`Page created: ${event.id}`) res.status(200).send("ok") }) ``` -------------------------------- ### API Version Examples Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Illustrates how to specify different Notion API versions when initializing the client. ```typescript import { Client } from "@notionhq/client" // Use default version (2025-09-03) const notion1 = new Client({ auth: process.env.NOTION_TOKEN, }) // Use newer version (2026-03-11) const notion2 = new Client({ auth: process.env.NOTION_TOKEN, notionVersion: "2026-03-11", }) ``` -------------------------------- ### Initial Verification Handshake Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md An example demonstrating how to handle the initial verification handshake with Notion. ```typescript import { verifyWebhookSignature } from "@notionhq/client" app.post("/notion-webhook", express.text({ type: "application/json" }), async (req, res) => { const verified = await verifyWebhookSignature({ body: req.body, signature: req.header("x-notion-signature"), verificationToken: process.env.NOTION_WEBHOOK_VERIFICATION_TOKEN, }) if (!verified) { return res.status(401).send("Invalid signature") } const body = JSON.parse(req.body) if (body.verification_token) { // Initial handshake return res.status(200).send("") } // Regular webhook event console.log("Event:", body.type) res.status(200).send("ok") }) ``` -------------------------------- ### SelectPropertyItemObjectResponse Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md An example of a select property item value response. ```typescript { id: "status", type: "select", select: { id: "1", name: "In progress", color: "yellow" } | null } ``` -------------------------------- ### Usage Example: List Comments Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-core.md Example of how to list comments for a given page or block. ```typescript const comments = await notion.comments.list({ block_id: "page_or_block_id", }) for (const comment of comments.results) { console.log(comment.rich_text) } ``` -------------------------------- ### Usage Example: Retrieve User Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-core.md Example of how to retrieve a user and access their properties. ```typescript const user = await notion.users.retrieve({ user_id: "user_id", }) console.log(user.type) // "person" or "bot" console.log(user.name) // User name console.log(user.person?.email) // Email (if person) ``` -------------------------------- ### oauth.token Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of exchanging an authorization code for a token. ```typescript // After user authorizes, exchange code for token const tokenResponse = await notion.oauth.token({ code: authorization_code_from_user, grant_type: "authorization_code", redirect_uri: "https://yourapp.com/callback", client_id: process.env.NOTION_CLIENT_ID, client_secret: process.env.NOTION_CLIENT_SECRET, }) console.log(tokenResponse.access_token) // Use for API calls console.log(tokenResponse.workspace_id) // User's workspace console.log(tokenResponse.workspace_name) // User's workspace name console.log(tokenResponse.owner) // User object (person/bot) ``` -------------------------------- ### DatePropertyItemObjectResponse Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md An example of a date property item value response, including start and optional end dates and time zone. ```typescript { id: "due_date", type: "date", date: { start: "2024-01-15", end: "2024-01-20" | null, time_zone?: "America/New_York" } | null } ``` -------------------------------- ### Create a page in a database Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of creating a page in a database. ```typescript await notion.pages.create({ parent: { database_id: "..." }, properties: { title: [{ type: "text", text: { content: "New Page" } }], status: { status: { name: "To Do" } }, }, }) ``` -------------------------------- ### Direct HTTP Request Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/client.md Examples of making direct HTTP requests to Notion API endpoints using the `request` method, including GET and POST requests with different parameters. ```typescript // Simple GET request const response = await notion.request({ path: "comments", method: "get", query: { page_id: "abc123" }, }) // POST request with body const comment = await notion.request({ path: "comments", method: "post", body: { parent: { page_id: "5c6a28216bb14a7eb6e1c50111515c3d" }, rich_text: [{ text: { content: "Hello, world!" } }], }, }) ``` -------------------------------- ### Usage Example: List Data Source Templates Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-core.md Example of how to list and iterate through data source templates. ```typescript const templates = await notion.dataSources.listTemplates({ data_source_id: "data_source_id", }) for (const template of templates.templates) { console.log(`${template.name}: ${template.description}`) } ``` -------------------------------- ### Basic Usage Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/client.md Basic usage example for the Notion client. ```typescript import { Client } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) // Retrieve a page const page = await notion.pages.retrieve({ page_id: "abc123" }) console.log(page) ``` -------------------------------- ### OAuth Flow - Handle Callback Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of handling the callback to get the authorization code. ```typescript const code = request.query.code ``` -------------------------------- ### Filter Examples Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md Examples of common filter configurations for different property types. ```typescript // Text filters { property: "Title", rich_text: { contains: "project" } } // Date filters { property: "Due Date", date: { after: "2024-01-01" } } // Select filters { property: "Status", select: { equals: "Done" } } // Checkbox filters { property: "Completed", checkbox: { equals: true } } // Number filters { property: "Priority", number: { greater_than: 5 } } ``` -------------------------------- ### RelationDatabaseProperty Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md An example of a relation database property configuration, linking to another database. ```typescript { id: "ghi", name: "Related Pages", type: "relation", relation: { database_id: "other_database_id", synced_property_id?: string // If synced both ways synced_property_name?: string } } ``` -------------------------------- ### Search workspace Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of searching the workspace. ```typescript const results = await notion.search({ query: "project status", filter: { property: "object", value: "page" }, }) ``` -------------------------------- ### oauth.introspect Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of inspecting an access token. ```typescript const introspection = await notion.oauth.introspect({ token: access_token, client_id: process.env.NOTION_CLIENT_ID, client_secret: process.env.NOTION_CLIENT_SECRET, }) if (introspection.active) { console.log(`Token is valid for workspace: ${introspection.workspace_id}`) } else { console.log("Token is invalid or expired") } ``` -------------------------------- ### OAuth Authentication Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Provides an example of how to use the `oauth.token` method for OAuth flows. ```typescript const notion = new Client() const tokenResponse = await notion.oauth.token({ code: "authorization_code_from_user", client_id: "your_client_id", client_secret: "your_client_secret", }) ``` -------------------------------- ### Pagination Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/client.md Pagination example using collectPaginatedAPI. ```typescript import { Client, collectPaginatedAPI } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) // Iterate through paginated results for await (const block of notion.blocks.children.list({ block_id: "abc123" })) { console.log(block) } // Or collect all results at once (use with caution for large datasets) const allBlocks = await collectPaginatedAPI(notion.blocks.children.list, { block_id: "abc123", }) ``` -------------------------------- ### Querying data sources Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of querying data sources with a filter. ```javascript const myPage = await notion.dataSources.query({ data_source_id: "897e5a76-ae52-4b48-9fdf-e71f5945d1af", filter: { property: "Landmark", rich_text: { contains: "Bridge", }, }, }) ``` -------------------------------- ### oauth.revoke Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of revoking an access token. ```typescript await notion.oauth.revoke({ token: access_token, client_id: process.env.NOTION_CLIENT_ID, client_secret: process.env.NOTION_CLIENT_SECRET, }) console.log("Token revoked successfully") ``` -------------------------------- ### Verify webhook Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of verifying a webhook signature. ```typescript const isValid = await verifyWebhookSignature({ body: req.body, signature: req.header("x-notion-signature"), verificationToken: process.env.WEBHOOK_TOKEN, }) ``` -------------------------------- ### Usage Example (Vercel Edge Function) Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md An example of how to use verifyWebhookSignature with a Vercel Edge Function. ```typescript import { verifyWebhookSignature } from "@notionhq/client" export default async function handler(request, response) { if (request.method !== "POST") { return response.status(405).json({ error: "Method not allowed" }) } const body = await request.text() const signature = request.headers.get("x-notion-signature") const verified = await verifyWebhookSignature({ body, signature, verificationToken: process.env.NOTION_WEBHOOK_VERIFICATION_TOKEN, }) if (!verified) { return response.status(401).json({ error: "Invalid signature" }) } const event = JSON.parse(body) return response.status(200).json({ ok: true }) } ``` -------------------------------- ### Custom Fetch Implementation Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Shows how to provide a custom fetch implementation, for example, using `node-fetch` in older Node.js versions. ```typescript import { Client } from "@notionhq/client" import fetch from "node-fetch" // Example: use node-fetch in older Node versions const notion = new Client({ auth: process.env.NOTION_TOKEN, fetch: fetch, }) ``` -------------------------------- ### Get Current Bot/Integration Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-core.md Gets details about the current authenticated bot/integration. ```typescript public me(args: WithAuth): Promise ``` -------------------------------- ### Handling errors Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of handling API errors, specifically 'ObjectNotFound'. ```javascript const { Client, APIErrorCode } = 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 (error.code === APIErrorCode.ObjectNotFound) { // // For example: handle by asking the user to select a different data source // } else { // Other error handling code console.error(error) } } ``` -------------------------------- ### Client with specific Notion API version Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of constructing the Client with a specific Notion API version. ```javascript const notion = new Client({ auth: process.env.NOTION_TOKEN, notionVersion: "2026-03-11", }) ``` -------------------------------- ### RelationPropertyItemObjectResponse Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md An example of a relation property item value response, listing related page IDs. ```typescript { id: "related", type: "relation", relation: [ { id: "page_id_1" }, { id: "page_id_2" } ] } ``` -------------------------------- ### Verifying webhook signatures Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Express example demonstrating how to verify Notion webhook signatures using `verifyWebhookSignature`. ```typescript import { verifyWebhookSignature } from "@notionhq/client" // Express example. The body must be read as the raw text/bytes that // arrived over the wire — JSON-parsed and re-serialized bodies will not // verify, because re-serialization changes whitespace and key order. app.post( "/notion-webhook", express.text({ type: "application/json" }), async (req, res) => { const ok = await verifyWebhookSignature({ body: req.body, signature: req.header("x-notion-signature"), verificationToken: process.env.NOTION_WEBHOOK_VERIFICATION_TOKEN!, }) if (!ok) { return res.status(401).send("invalid signature") } const event = JSON.parse(req.body) // …handle the event res.status(200).send("ok") } ) ``` -------------------------------- ### APIResponseError Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/errors.md Example demonstrating how to catch and handle APIResponseError, including specific error codes like ObjectNotFound and RateLimited. ```typescript import { Client, APIErrorCode, isNotionClientError } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) try { const database = await notion.databases.retrieve({ database_id: "invalid_id", }) } catch (error) { if (isNotionClientError(error) && error.code === APIErrorCode.ObjectNotFound) { console.log("Database not found") } else if (isNotionClientError(error) && error.code === APIErrorCode.RateLimited) { console.log("Rate limited, waiting before retry") } } ``` -------------------------------- ### RequestTimeoutError Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/errors.md Example showing how to configure a timeout for Notion client requests and handle RequestTimeoutError. ```typescript import { Client, ClientErrorCode, isNotionClientError } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN, timeoutMs: 5000, // 5 second timeout }) try { const pages = await notion.pages.retrieve({ page_id: "abc123" }) } catch (error) { if (isNotionClientError(error) && error.code === ClientErrorCode.RequestTimeout) { console.log("Request timed out after 5 seconds") } } ``` -------------------------------- ### Rich Text Type Guards Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/helpers.md Example demonstrating the usage of rich text type guards. ```typescript import { Client, isTextRichTextItemResponse, isMentionRichTextItemResponse, } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) const page = await notion.pages.retrieve({ page_id: "abc123" }) // Properties is a paginated list; we'd need to get specific property const titleProp = await notion.pages.properties.retrieve({ page_id: "abc123", property_id: "title", }) if (titleProp.object === "list" && titleProp.results.length > 0) { const richText = titleProp.results[0] if (isTextRichTextItemResponse(richText)) { console.log(`Text: ${richText.text.content}`) } } ``` -------------------------------- ### UnknownHTTPResponseError Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/errors.md Demonstrates how to catch and handle an UnknownHTTPResponseError. ```typescript import { Client, isHTTPResponseError } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) try { const page = await notion.pages.retrieve({ page_id: "abc123" }) } catch (error) { if (isHTTPResponseError(error)) { console.log(`HTTP ${error.status}: ${error.body}`) } } ``` -------------------------------- ### Creating a Page with Rich Text Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md An example of creating a Notion page with a title property that includes rich text, demonstrating text formatting and links. ```typescript const page = await notion.pages.create({ parent: { database_id: "..." }, properties: { title: [ { type: "text", text: { content: "My Page", link: { url: "https://example.com" }, }, annotations: { bold: true, italic: false, code: false, color: "red", }, }, ], }, }) ``` -------------------------------- ### List all views for a database Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of listing all views associated with a database and logging their names and types. ```typescript const views = await notion.views.list({ database_id: "database_id", }) for (const view of views.results) { console.log(`${view.name} (${view.type})`) } ``` -------------------------------- ### Error Handling Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/client.md Error handling example for the Notion client. ```typescript import { Client, APIErrorCode, isNotionClientError } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) try { const page = await notion.pages.retrieve({ page_id: "invalid-id" }) } catch (error) { if (isNotionClientError(error)) { if (error.code === APIErrorCode.ObjectNotFound) { console.log("Page not found") } else { console.error("API error:", error.code, error.message) } } else { throw error } } ``` -------------------------------- ### Verify Webhook Signature Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md Example of how to verify a webhook signature using the SDK. ```typescript import { verifyWebhookSignature, } from "@notionhq/client/webhooks"; const signature = req.headers["x-notion-signature"]; const rawBody = req.body; const signingSecret = process.env.NOTION_WEBHOOK_SECRET; if (!signingSecret) { throw new Error("NOTION_WEBHOOK_SECRET not set"); } try { verifyWebhookSignature(rawBody, signature, signingSecret); // Signature is valid, process the webhook event console.log("Webhook verified successfully!"); } catch (error) { // Signature is invalid console.error("Webhook verification failed:", error); } ``` -------------------------------- ### Query a database with filters Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of querying a database with filters and sorts. ```typescript const results = await notion.dataSources.query({ data_source_id: "...", filter: { property: "Status", select: { equals: "Active" }, }, sorts: [{ property: "Name", direction: "ascending" }], }) ``` -------------------------------- ### Configure Client Retry Behavior Source: https://github.com/makenotion/notion-sdk-js/blob/main/CLAUDE.md Examples for configuring custom retry logic or disabling retries entirely in the Notion client. ```typescript const client = new Client({ auth: "secret_...", retry: { maxRetries: 2, // Default: 2 retry attempts initialRetryDelayMs: 1000, // Default: 1 second base delay maxRetryDelayMs: 60000, // Default: 60 second cap }, }) // Or disable retries entirely: const client = new Client({ auth: "secret_...", retry: false }) ``` -------------------------------- ### Create table view with filters Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of creating a table view with specific filters and column configurations. ```typescript const view = await notion.views.create({ database_id: "database_id", name: "Active Tasks", type: "table", filter: { property: "status", status: { does_not_equal: "done", }, }, configuration: { table: { properties: [ { property_id: "name", visible: true, width: 300, }, { property_id: "status", visible: true, width: 100, }, ], }, }, }) ``` -------------------------------- ### List all users Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of iterating through paginated API results to list all users. ```typescript for await (const user of iteratePaginatedAPI( notion.users.list, {} )) { console.log(user.name) } ``` -------------------------------- ### Custom Authentication per Request Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/client.md Example of custom authentication for a specific request. ```typescript const notion = new Client() // Authenticate with a token for this specific request const page = await notion.pages.retrieve({ page_id: "abc123", auth: "secret_abc123...", }) ``` -------------------------------- ### Setting minimum column width in a table view Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of creating a table view with a specific column set to the minimum allowed width, useful for collapsed columns. ```javascript 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, }, ], }, }, }) ``` -------------------------------- ### Using Constants Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Demonstrates how to import and use predefined constants from the SDK, such as default URLs, timeouts, retry settings, and minimum view column width. ```typescript import { DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_INITIAL_RETRY_DELAY_MS, DEFAULT_MAX_RETRY_DELAY_MS, MIN_VIEW_COLUMN_WIDTH, } from "@notionhq/client" console.log(DEFAULT_BASE_URL) // "https://api.notion.com" console.log(DEFAULT_TIMEOUT_MS) // 60000 // Use MIN_VIEW_COLUMN_WIDTH to collapse a column in a view await notion.views.update({ view_id: "abc123", configuration: { table: { properties: [ { property_id: "checkboxId", visible: true, width: MIN_VIEW_COLUMN_WIDTH, // Displays as collapsed }, ], }, }, }) ``` -------------------------------- ### Request times out Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of increasing the timeout for requests. ```typescript const notion = new Client({ auth: token, timeoutMs: 120000, // 2 minutes }) ``` -------------------------------- ### Rich Text Object - Equation Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-blocks.md Example of a rich text object for an equation. ```typescript { type: "equation", equation: { expression: "E = mc^2" } } ``` -------------------------------- ### OAuth Flow - Use Access Token Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of creating a new Notion client with the obtained access token. ```typescript const userClient = new Client({ auth: tokenResponse.access_token, }) ``` -------------------------------- ### blocks.retrieve Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-blocks.md Retrieves a single block by ID. ```typescript const block = await notion.blocks.retrieve({ block_id: "abc123def456789012345678901234ab", }) console.log(block.type) // "paragraph", "heading_1", etc. ``` -------------------------------- ### Custom requests Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of making a direct request to a Notion API endpoint using the `request()` method. ```typescript // POST /v1/comments const response = await notion.request({ path: "comments", method: "post", body: { parent: { page_id: "5c6a28216bb14a7eb6e1c50111515c3d" }, rich_text: [{ text: { content: "Hello, world!" } }], }, // No `query` params in this example, only `body`. }) console.log(JSON.stringify(response, null, 2)) ``` -------------------------------- ### OAuth Flow - Verify Token Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of verifying a token using `oauth.introspect`. ```typescript const info = await notion.oauth.introspect({ token: access_token, client_id: process.env.NOTION_CLIENT_ID, client_secret: process.env.NOTION_CLIENT_SECRET, }) ``` -------------------------------- ### Initializing a client Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Import and initialize a client using an integration token or an OAuth access token. ```javascript const { Client } = require("@notionhq/client") // Initializing a client const notion = new Client({ auth: process.env.NOTION_TOKEN, }) ``` -------------------------------- ### Webhook Verification and Signing Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Provides examples for verifying incoming webhook signatures using `verifyWebhookSignature` and signing outgoing payloads with `signWebhookPayload`. ```typescript import { verifyWebhookSignature, signWebhookPayload } from "@notionhq/client" // Verify incoming webhook const isValid = await verifyWebhookSignature({ body: req.body, // Raw text body signature: req.header("x-notion-signature"), verificationToken: process.env.WEBHOOK_TOKEN, }) // Test webhook handler const signature = await signWebhookPayload({ body: JSON.stringify(testPayload), verificationToken: process.env.WEBHOOK_TOKEN, }) ``` -------------------------------- ### pages.retrieve - Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-pages.md Retrieves a page by its ID and logs its properties, URL, and creation time. ```typescript const page = await notion.pages.retrieve({ page_id: "abc123def456789012345678901234ab", }) console.log(page.properties) // Page property values console.log(page.url) // Page URL console.log(page.created_time) // Creation timestamp ``` -------------------------------- ### Build Commands Source: https://github.com/makenotion/notion-sdk-js/blob/main/CLAUDE.md Commands for building the project and cleaning the build directory. ```bash npm run build # Runs: npm run clean && tsc npm run clean # Remove build/ directory ``` -------------------------------- ### Using Type Guards for API Responses Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example demonstrating how to use type guards like `isFullPageOrDataSource` to narrow down the type of API response objects, enabling type-safe access to properties. ```typescript const fullOrPartialPages = await notion.dataSources.query({ data_source_id: "897e5a76-ae52-4b48-9fdf-e71f5945d1af", }) for (const page of fullOrPartialPages.results) { if (!isFullPageOrDataSource(page)) { continue } // The page variable has been narrowed from // PageObjectResponse | PartialPageObjectResponse | DataSourceObjectResponse | PartialDataSourceObjectResponse // to // PageObjectResponse | DataSourceObjectResponse. console.log("Created at:", page.created_time) } ``` -------------------------------- ### Rich Text Object - Mention Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-blocks.md Example of a rich text object representing a user mention. ```typescript { type: "mention", mention: { type: "user", user: { id: "user_id" } } } ``` -------------------------------- ### Type errors with properties Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of using the correct property type when updating a page and checking database schema for property types. ```typescript // Correct await notion.pages.update({ page_id: "...", properties: { status: { status: { name: "Done" } }, }, }) // Check property types in database schema first const db = await notion.databases.retrieve({ database_id: "..." }) console.log(db.properties) // See property types ``` -------------------------------- ### Rich Text Object - Text Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-blocks.md Example of a rich text object with text content, optional link, and annotations. ```typescript { type: "text", text: { content: "String content", link: { url: "https://example.com" } // Optional }, annotations: { bold: false, italic: false, strikethrough: false, underline: false, code: false, color: "default" // or specific color }, href: "https://example.com" // Optional link } ``` -------------------------------- ### Update page content Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Examples of updating page content via markdown or blocks. ```typescript // Via markdown await notion.pages.updateMarkdown({ page_id: "...", markdown: "# Heading\n\nContent here", }) // Via blocks await notion.blocks.children.append({ block_id: "...", children: [ { object: "block", type: "paragraph", paragraph: { rich_text: [{ type: "text", text: { content: "..." } }] }, }, ], }) ``` -------------------------------- ### Client-Level Authentication Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Shows how to configure authentication using a token provided during client initialization. ```typescript const notion = new Client({ auth: process.env.NOTION_TOKEN, }) // All requests use this token const page = await notion.pages.retrieve({ page_id: "abc123" }) ``` -------------------------------- ### OAuth Flow - Exchange for Token Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of exchanging the authorization code for a token using `oauth.token`. ```typescript const tokenResponse = await notion.oauth.token({ code, grant_type: "authorization_code", redirect_uri: process.env.NOTION_REDIRECT_URI, client_id: process.env.NOTION_CLIENT_ID, client_secret: process.env.NOTION_CLIENT_SECRET, }) ``` -------------------------------- ### iteratePaginatedAPI Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/helpers.md Demonstrates how to use the `iteratePaginatedAPI` utility to fetch paginated results. ```typescript import { Client, iteratePaginatedAPI } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) // Iterate through all blocks in a parent for await (const block of iteratePaginatedAPI( notion.blocks.children.list, { block_id: "parent_block_id" } )) { console.log(block.id) } // Iterate through all users for await (const user of iteratePaginatedAPI( notion.users.list, {} )) { console.log(user.id) } // Iterate through all comments on a page for await (const comment of iteratePaginatedAPI( notion.comments.list, { block_id: "page_id" } )) { console.log(comment.id) } ``` -------------------------------- ### SDK Type Support for Version Differences Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/types.md Example showing how SDK types handle version-specific field name differences, marking older fields as deprecated. ```typescript type PageObjectResponse = { // Available in v2025-09-03+ archived: boolean // @deprecated Use in_trash for v2026-03-11+ // Available in v2026-03-11+ in_trash?: boolean // ... other fields } ``` -------------------------------- ### isFullPage Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/helpers.md Determines whether an object is a complete `PageObjectResponse` with all properties. ```typescript import { Client, isFullPage } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) const response = await notion.dataSources.query({ data_source_id: "abc123", }) for (const item of response.results) { if (isFullPage(item)) { // item has url, created_time, parent, properties, etc. console.log(`Page: ${item.url}`) } } ``` -------------------------------- ### isFullDatabase Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/helpers.md Determines whether an object is a complete `DatabaseObjectResponse`. ```typescript import { Client, isFullDatabase } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) const item = await notion.dataSources.query({ data_source_id: "abc123" }) for (const result of item.results) { if (isFullDatabase(result)) { console.log(`Database: ${result.title}`) } } ``` -------------------------------- ### OAuth Flow - Generate Authorization URL Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of generating the authorization URL for the OAuth flow. ```url https://api.notion.com/v1/oauth/authorize? client_id=YOUR_CLIENT_ID& response_type=code& owner=user& redirect_uri=YOUR_REDIRECT_URI& state=random_state_string ``` -------------------------------- ### Update view properties Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/endpoints-advanced.md Example of updating a view's name, filter, and sort order. ```typescript await notion.views.update({ view_id: "view_id", name: "Completed Tasks", filter: { property: "status", status: { equals: "done", }, }, }) ``` -------------------------------- ### Rate limited Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/index.md Example of handling rate limiting, including disabling automatic retries. ```typescript const notion = new Client({ auth: token, retry: false, // Handle retries yourself }) try { // retry logic } catch (error) { if (error.code === APIErrorCode.RateLimited) { // Wait and retry } } ``` -------------------------------- ### Path Validation Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/errors.md Illustrates how the client automatically validates request paths to prevent path traversal attacks, throwing `InvalidPathParameterError` for invalid paths. ```typescript const notion = new Client({ auth: process.env.NOTION_TOKEN }) try { await notion.request({ path: "../../sensitive_path", method: "get", }) } catch (error) { // InvalidPathParameterError thrown console.log("Path validation failed:", error.message) } ``` -------------------------------- ### Testing Express Handler Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md Example of testing an Express webhook handler using `supertest` and `signWebhookPayload` to ensure valid signatures are accepted and invalid ones are rejected. ```typescript import request from "supertest" import { signWebhookPayload } from "@notionhq/client" describe("webhook handler", () => { it("accepts valid signatures", async () => { const verificationToken = process.env.NOTION_WEBHOOK_VERIFICATION_TOKEN const body = JSON.stringify({ type: "page.created", id: "abc123" }) const signature = await signWebhookPayload({ body, verificationToken }) const response = await request(app) .post("/notion-webhook") .set("x-notion-signature", signature) .send(body) expect(response.status).toBe(200) }) it("rejects invalid signatures", async () => { const body = JSON.stringify({ type: "page.created", id: "abc123" }) const response = await request(app) .post("/notion-webhook") .set("x-notion-signature", "sha256=invalidsignature") .send(body) expect(response.status).toBe(401) }) }) ``` -------------------------------- ### Iterating Paginated API Results Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of using the `iteratePaginatedAPI` utility function to asynchronously iterate over results from a paginated Notion API endpoint. ```javascript for await (const block of iteratePaginatedAPI(notion.blocks.children.list, { block_id: parentBlockId, })) { // Do something with block. } ``` -------------------------------- ### Proxy Configuration Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/configuration.md Demonstrates how to configure the client to use an HTTP proxy by providing an `agent`. ```typescript import { Client } from "@notionhq/client" import HttpsProxyAgent from "https-proxy-agent" const agent = new HttpsProxyAgent("http://proxy.example.com:8080") const notion = new Client({ auth: process.env.NOTION_TOKEN, agent: agent, }) ``` -------------------------------- ### isFullDataSource Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/helpers.md Determines whether an object is a complete `DataSourceObjectResponse`. ```typescript import { Client, isFullDataSource } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) const item = await notion.dataSources.retrieve({ data_source_id: "abc123", }) if (isFullDataSource(item)) { console.log(`DataSource: ${item.name}`) } ``` -------------------------------- ### Collecting Paginated API Results Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of using the `collectPaginatedAPI` utility function to fetch all results from a paginated Notion API endpoint into an in-memory array. ```javascript const blocks = await collectPaginatedAPI(notion.blocks.children.list, { block_id: parentBlockId, }) // Do something with blocks. ``` -------------------------------- ### Webhook Verification Best Practices - Extract Signature from Headers Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/webhooks.md Provides examples for extracting the `x-notion-signature` header in various Node.js frameworks (Express, Fastify, Next.js) and the Edge Runtime. ```typescript // Express const signature = req.header("x-notion-signature") // Headers are lowercased // Fastify const signature = request.headers["x-notion-signature"] // Next.js const signature = request.headers["x-notion-signature"] // Fetch in Edge Runtime const signature = request.headers.get("x-notion-signature") ``` -------------------------------- ### Run Prepublish Checks Source: https://github.com/makenotion/notion-sdk-js/blob/main/CLAUDE.md Execute prepublishOnly script which includes login check, linting, and testing before publishing. ```bash npm run prepublishOnly # Runs: checkLoggedIn && lint && test ``` -------------------------------- ### Handling Errors with Type Guards Source: https://github.com/makenotion/notion-sdk-js/blob/main/README.md Example of using `isNotionClientError` to handle errors in a type-safe way, distinguishing between client-produced and server-produced error codes. ```typescript try { const response = await notion.dataSources.query({ /* ... */ }) } 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: // you could even take advantage of exhaustiveness checking assertNever(error.code) } } } ``` -------------------------------- ### Manual Retry Logic with Error Handling Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/errors.md Provides an example of implementing custom retry logic for rate-limited errors when the SDK's automatic retry is disabled. ```typescript import { Client, APIErrorCode, ClientErrorCode, isNotionClientError } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN, retry: false, // Handle retries manually }) async function fetchWithManualRetry(pageId, maxAttempts = 3) { for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { return await notion.pages.retrieve({ page_id: pageId }) } catch (error) { if ( isNotionClientError(error) && error.code === APIErrorCode.RateLimited && attempt < maxAttempts ) { console.log(`Rate limited. Retrying in 2 seconds... (attempt ${attempt})`) await new Promise(resolve => setTimeout(resolve, 2000)) } else { throw error } } } } const page = await fetchWithManualRetry("abc123") ``` -------------------------------- ### InvalidPathParameterError Usage Example Source: https://github.com/makenotion/notion-sdk-js/blob/main/_autodocs/errors.md Example demonstrating how to catch InvalidPathParameterError, which is thrown when a request path contains dangerous characters. ```typescript import { Client, isNotionClientError } from "@notionhq/client" const notion = new Client({ auth: process.env.NOTION_TOKEN }) try { // Path traversal detected const response = await notion.request({ path: "../../etc/passwd", method: "get", }) } catch (error) { if (isNotionClientError(error) && error.name === "InvalidPathParameterError") { console.log("Invalid path parameter:", error.message) } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.