Skip to main content

Data source schema update fixes

Update a data source now changes the color of an existing select, multi_select, or status option instead of returning a validation_error. Option names also match existing options without regard to case, so sending high keeps the existing High option and its ID instead of replacing it. See Existing select options.Property updates now keep the existing description when you omit it, for every property type and when you change a type. Send null to clear it. The same rule applies to an option’s own description. Omitting options on a select or multi_select update now keeps the current options. See Update data source properties.

Admin API list endpoints accept start_cursor

List MCP client connections and List personal access tokens now accept start_cursor, like other Admin API list endpoints. Before this change, these endpoints ignored start_cursor and returned the first page again. The cursor parameter still works but is deprecated. If you send both with different values, the request fails with a 400 error.

Control notifications from page writes

Page write endpoints now accept notifications.mode. Set it to silent to skip page update, @mention, and Person property notifications for the change. Database automations, reminders, and connection webhooks still work as usual. See Create a page, Update a page, and Append block children for details.

One search tool in Notion MCP

Hosted Notion MCP sessions now list one content-search tool, notion-search (search for OpenAI clients). Its description matches the user’s AI search access. It describes AI search when the user has it, and keyword search otherwise, with a one-line upgrade note when the plan lacks AI search. notion-ai-search no longer appears in tools/list, but it stays callable by name, so clients with a cached tool list keep working. Workspace-owned MCP connections, which have a selected tool list, keep the earlier tool list and descriptions. In the other sessions, the server instructions also tell clients to use the Notion search tool for every content search.

notion-get-tool-access is optional

Except on workspace-owned connections, tool descriptions no longer tell clients to call notion-get-tool-access before they use a tool. Tools apply access limits themselves and report them in their results. Call notion-get-tool-access only when you want plan or parameter details up front. This replaces the September 17, 2026 advice to call it first.

OpenAI’s search and fetch shape for ChatGPT

For ChatGPT connections, a content search with search returns { results: [{ id, title, url }] } and fetch returns { id, title, text, url, metadata }, as both structuredContent and JSON text. This is the shape that OpenAI’s MCP requirements set for company knowledge and deep research. ChatGPT search results no longer include highlights, path, timestamps, or notices. When fetch gets include_file_urls: true, file download URLs are under metadata.references. User lookups and other clients don’t change; see Supported tools.

Status group filters beta

Status filters can now match groups with group_equals and group_does_not_equal. These operators remove option and group name ambiguity.Send Notion-Beta: status-group-filters-2026-10-06 to opt in. With the header, equals and does_not_equal match only option names. Views return saved group filters with group operators. Without the header, nothing changes. See Status group filters beta.

Warnings from notion-update-page

notion-update-page now returns an optional warnings array, for direct and queued updates, when it changed or ignored part of the input, such as lines dropped for incorrect indentation or text auto-corrected to match the page. Each warning has a code and a message, and Markdown parser warnings also carry category and autofix. Each message is at most 500 characters; a longer one is cut and ends with a note giving its original length. A clean update has no warnings key; see Supported tools.

No more tool-specific Notion MCP rate limits

notion-search and notion-query-data-sources no longer have their own rate limits. Calls to these tools now count toward the standard request limits, like other Notion MCP tools. See Supported tools.

Create teamspace root pages with Notion MCP

notion-create-pages now supports creating pages directly in a teamspace with parent.teamspace_id. Use a user-backed connection with permission to add top-level pages; see Teamspace root pages for details and an example.

Page edits return 400 when a page is too large to load

Update a page’s content as markdown and the notion-update-page MCP tool now return HTTP 400 validation_error when a page is too large to load in full (about 20,000 records, most of them blocks) and the edit targets a block that wasn’t loaded or would remove content that wasn’t loaded. Before, they returned HTTP 500 internal_server_error. Retrying the same request fails the same way. Content that wasn’t loaded appears as <unknown> tags when you retrieve the page as markdown, so edit only content outside those tags. The response’s additional_data.limit_kind is page_record_count, and additional_data.limit holds the limit.

Custom blocks in markdown

The markdown content API and Notion MCP now read custom blocks with inherited bindings as <custom-block definition-id="…" url="…" /> instead of <unknown>. You can place existing definitions and preserve unchanged instances during page edits; see Working with markdown content. Definition creation remains in private alpha.The SIEM and DLP event stream now sends workspace.settings.meeting_notes_consent_setting_updated when an admin changes whether a workspace requires consent before AI meeting notes transcription. The payload carries the final state, either enabled or disabled. See SIEM events.This is separate from the existing audit log entry for a person confirming consent in a meeting. The new event records a change to the requirement, not an instance of consent.

Preview: Notion-flavored Markdown with markdown_version

The markdown endpoints accept a new optional markdown_version parameter. Set it to v2 to read and write Notion-flavored Markdown. This is an opt-in preview: v1 (enhanced markdown) stays the default, and requests without the parameter work as before. v2 doesn’t support include_transcript yet, and synchronous v2 updates return parser warnings. Sending markdown_version without markdown on POST /v1/pages or the comment endpoints returns a 400 validation_error. See Markdown versions and the Notion-flavored Markdown format reference.

Completing the query tool update in Notion MCP

notion-query-database-view is no longer available. Call notion-query-data-sources instead, and pass the same view_url as {"data": {"mode": "view", "view_url": "..."}}. Calls to the old tool name now return a tool error that names this replacement.

Higher Notion MCP search and query limits

Notion MCP now allows 20 search calls and 20 data source query calls per connection every 10 seconds. Rate-limit tool errors also include their structured JSON in the text response for clients that read only text. See Supported tools.

Custom emoji icons are validated

A custom_emoji icon on a page, database, data source, or callout must now name a custom emoji in the integration’s workspace. Otherwise the request returns a validation_error instead of saving an icon that reads back as null. See Emoji and icon. Notion MCP applies the same check to custom_emoji:<id> page icons in notion-create-pages and notion-update-page.

Rate limit waits in the response body

Any 429 or 529 response that includes a Retry-After header now repeats the wait in the body as additional_data.retry_after, so clients that can’t read headers, such as MCP clients, can still see how long to wait. Two new rate_limit_reason values identify an endpoint’s own limit (public_api_endpoint_rate_limit) and a connection whose API access has been restricted (public_api_request_blocked). A workspace-limit 429 now says that the limit is shared by all of the workspace’s connections. See Request limits.

Page writes return 504 when a request times out

Update a page’s content as markdown and the notion-update-page MCP tool now return HTTP 504 gateway_timeout when a request runs past its deadline. Before, they returned HTTP 500 internal_server_error. The notion-create-pages and notion-convert-page-to-skill MCP tools already returned 504 in this case. A 504 does not mean the write was undone, so check whether the change was saved before you retry it. A write that runs out of its time budget still returns 503 service_unavailable, with additional_data.retry_guidance. See Request limits for when to retry each status.

Notion icon URLs are validated

An external icon URL that points at Notion’s built-in icon set, such as https://www.notion.so/icons/pizza_blue.svg, sets a native icon and reads back as type: "icon". A URL that names no real icon or color now returns a validation_error instead of saving a broken icon. In Notion MCP, the page icon parameter on notion-create-pages and notion-update-page now accepts the icons/pizza_blue identifier that notion-fetch returns, so an icon can be copied from one page to another.

File uploads accept CAD and 3D model formats

The File Upload API now accepts common CAD and 3D model formats, including .dwg, .dxf, .dwf, .rvt, .rfa, .3dm, .step, .stl, .obj, and .glb. They attach to pages as file blocks.

application/octet-stream resolves from the file extension

Many HTTP clients label files with application/octet-stream when they can’t infer a MIME type from the extension. Create a file upload and Send a file upload now treat that generic type as unspecified and resolve the real type from the filename extension, or from the content type set at creation. Files with unsupported extensions are still rejected.

Check tool access with notion-get-tool-access

Notion MCP has a new notion-get-tool-access tool. Call it with {} to get the full connection-scoped current_tool_access map. It takes an optional tool_names array such as ["search", "ai_search"] to narrow the result. Call it before you use a tool whose availability depends on the plan: to choose between notion-search and notion-ai-search, for example, or to see which parameters the workspace’s plan restricts. Those tools now say so in their descriptions, and each points to one call for the whole map that you can reuse across them. It doesn’t grant access or change the workspace.Entries in the map can now include restricted_parameters, which maps a parameter path such as filters.title_only to the reason it’s unavailable. A restriction applies even when the entry’s status is available, so check it before sending the parameter. Read the reason against your requested value: a single teamspace remains supported even when filters.teamspace_ids lists a restriction on multiple teamspaces.When ai_search is exposed and available, the map omits search, even when requested by name. Otherwise, the map can include both an available search entry and an unavailable ai_search entry, depending on the connection’s selected tools. Choose only an exposed tool. If only notion-ai-search is exposed, plan restrictions still allow its Notion-only keyword fallback; billing restrictions don’t.

Search drops unavailable options instead of failing

A notion-search or notion-ai-search call that asks for a filter or sort the workspace’s plan doesn’t include now runs the supported part of the search. These calls previously returned a validation_error. The response adds a notices array naming the dropped fields, with an upgrade link when available, and results can be broader than requested and use relevance sorting. On a plan without multiple-teamspace search, when teamspace_id and filters.teamspace_ids select different teamspaces, both are dropped. If dropping the options leaves an empty query with no supported constraint, the response returns no results and a notice asking for a non-empty query or a supported filter.notion-ai-search content search on a plan without AI access now runs a keyword search in Notion only rather than returning an upgrade error. It still reports type: "ai_search" and explains in notices that connected sources weren’t searched. A workspace with a billing restriction, such as an unpaid invoice, still gets a permission error asking a workspace owner to manage billing.

notion-ai-search handles user lookup

notion-ai-search now takes query_type. Set it to user with a name or email to look up a workspace user, and the response reports type: "user_search", the same as notion-search. Omit query_type, or set it to internal, for a content search. Content filters and sorting aren’t valid with a user lookup and return a validation_error. A user lookup doesn’t need AI access, but both search tools need user information capabilities. Workspace-owned MCP connections must also expose notion-get-users. Choose an exposed search tool; switching tools doesn’t bypass these permissions.

AI search accepts filters, and notion-search routes content queries to it

notion-ai-search now accepts the exact filters and sort options that notion-search accepts, and it accepts an empty query for filter-only browsing. These options return Notion-only workspace results so the constraints are enforced exactly, and the response still reports type: "ai_search". Omit them to search Notion and connected sources together. Filtering by editor, last-edited date, multiple teamspaces, title only, or content status, and sorting by date, still require Business or Enterprise. User lookup remains on notion-search with query_type: "user".Content searches sent to notion-search now run AI search when the connection can use it. When notion-fetch with the id self reports current_tool_access.ai_search.status as available, a keyword content query sent to notion-search searches Notion and connected sources and reports type: "ai_search", so clients that haven’t adopted notion-ai-search keep getting unified results. A call that passes an exact filter, an empty query, or a sort other than relevance stays on Notion workspace search. Routing respects the connection’s tool list: a connection that can’t use notion-ai-search keeps its content searches on workspace search, and the legacy content_search_mode: "ai_search" parameter returns a permission error for that connection. The 30-requests-per-minute limit on notion-search counts these calls either way.

Session URL shorthand for Custom Agent session tools

Notion MCP’s Custom Agent session tools now accept the shorthand session://<sessionId> and thread://<sessionId> for session_url, resolving both in the connected workspace. The full form session://<spaceId>/<sessionId> that session tools return still works, and a full URL whose workspace ID differs from the connected workspace still returns HTTP 400 validation_error.

Validation and conflict errors from Custom Agent session tools

Notion MCP’s Custom Agent session tools now return HTTP 400 validation_error for malformed URLs, URLs for a resource other than a session, or full URLs naming another workspace, and notion-send-message-to-session returns a conflict error when the session already has a run in progress. Both cases previously returned a generic failure. Valid URLs for missing, inaccessible, or unsupported sessions return HTTP 404 object_not_found. Wait for the run to finish with notion-wait-session before sending another message.

Faster retries and plan-based rate limits

The per-connection rate limit is now enforced over a fixed 60-second window: 600 requests per minute on Business and Enterprise plans, and 180 requests per minute on all other plans. Retry-After for this limit never exceeds 60 seconds, down from up to 15 minutes, and per-connection 429 responses now also include the wait as additional_data.retry_after in the body. See Request limits.
notion-search is now keyword-only. It matches short, specific terms in Notion and no longer searches connected apps like Slack, Google Drive, and Jira. Use it for content search only when notion-fetch with the id self reports that current_tool_access.ai_search.status is not available. It remains the tool for user lookup by name or email.Semantic search moved to a new notion-ai-search tool. Use it for every content search when current_tool_access.ai_search.status is available, including searches that include specific terms. It takes one concise natural-language query and searches sources connected to the workspace, such as Slack, Mail, and Calendar, when they are available to the caller. Using it requires Notion AI; without it, calls return a prompt with a recovery link, and notion-fetch with the id self reports ai_search in current_tool_access so clients can route to notion-search. notion-ai-search does not accept the exact filters, the sort options, or the user lookup that notion-search accepts.Clients that still send the old content_search_mode parameter on notion-search keep working: workspace_search behaves like notion-search, and ai_search behaves like notion-ai-search. The parameter is no longer advertised, so call the tool you want directly.

Page covers and icons in notion-fetch responses

The notion-fetch MCP tool now returns cover and icon metadata for pages and database items. Both use the same shapes as the REST API, so clients can inspect the current cover or icon before deciding whether to replace it.

Rich text in data source queries

The notion-query-data-sources MCP tool now supports mode: "rows" to keep rich text in data source results. This mode preserves mentions and link targets that SQL output can omit.

Typed databases in the REST API

Create a database now accepts an optional database_type of tasks, projects, or skills. Notion builds the database from its canonical schema and metadata for that type, so the result matches a database of that type created in the Notion app. database_type can’t be combined with initial_data_source, and when title is omitted the database is named after its type. See Typed databases for the properties each type creates. Database and data source objects now include a read-only database_type field.

Free workspace block limits now apply to the REST API

Starting today, the REST API enforces the existing Free workspace block limit for internal connections and OAuth connections restricted to selected workspaces. This is not a new workspace limit. See Workspace block limits for the grace period, HTTP 403 response, and background template behavior.

Upgrade prompts for Custom Agent tools in Notion MCP

Notion MCP’s Custom Agent tools — notion-list-agents, notion-search-agents, and the session tools — now return a prompt with a recovery link when the workspace doesn’t have access to Notion AI and Custom Agents. They previously returned a generic permission error with no recovery link. notion-fetch with the id self also reports these tools as upgrade_required with an upgrade_url, or as plan_required with a landing_page_url and landing_page_action when Notion routes the user through a plan landing page. Clients can use this status to route around unavailable tools before calling.Workspaces with a billing restriction, such as an unpaid invoice, are treated separately: the tools return a permission error that asks a workspace owner to manage billing, and current_tool_access reports them as not_enabled rather than upgrade_required.A connection that lacks the “View sessions and interact with agents” capability does not advertise these tools and must reconnect or re-authorize.

Capture ideas and draft content in Notion

Your agent can now capture ideas and draft content in Notion without choosing where the page belongs first. The page starts as a private draft, so you can review it and organize it later.

Save and reuse your preferred workflows with Notion Skills

When you ask your AI to save a workflow you want to reuse, it can now create a Notion Skill or turn an existing page into one. Skills are reusable instructions stored as Notion pages that you own and can edit.When you ask for that workflow later, your AI can find the right Skill and read its instructions before starting.

Find the right page more easily

Your AI can now narrow Notion searches by where a page lives, who created or edited it, when it changed, whether the title matches, and the page’s status. It can also sort results and look through up to 50 matches.Search results now show more context, including where a page lives and whether Notion has verified it. This helps your AI choose between similar or conflicting pages before reading the full content.Every plan includes filters for creator, creation date, and a single page, data source, or teamspace. On Business and Enterprise plans, your AI can also filter by editor, last-edited date, multiple teamspaces, title, or content status, and sort by date.

Fetch saved database views in Notion MCP

Notion MCP’s notion-fetch now accepts view:// URLs to read saved view settings. Tool response text now names fetch instead of view, without changing page content.

Custom Agent session tools in Notion MCP

Notion MCP now supports finding and working with Custom Agent sessions. The new tools can query or search sessions, start a session, send a follow-up message, check or wait for its status, stop a run, and list or read session events. See Supported tools for the full tool list and examples.

Atomic batched content updates in Notion MCP

notion-update-page calls that use the update_content command now apply every content-changing replacement in the batch or none of them. Previously, when one old_str matched no page content and another one in the same call did, the matching replacements were saved and the call returned success — so a batch that removed content in one operation and reinserted it in another could drop that content. These calls now return a validation_error naming the old_str that wasn’t found, and the page is left unchanged. Operations whose old_str and new_str are identical are ignored without checking for a match. See Supported tools for the tool’s matching rules.old_str must also be a non-empty string. Empty values were previously ignored, which silently skipped the replacement; they now fail validation on both notion-update-page and Update a page’s content as markdown.

Admin API reference for users and permission groups

The Admin API reference now covers listing workspace users and managing workspace permission groups and direct memberships. These endpoints require the new user:read, permission-group:read, and permission-group:write scopes and are available to eligible Enterprise organizations.

Notion Agent APIs in public beta

The Notion Agent APIs are now in public beta. Use sessions to start a chat with a Custom Agent, stream its reply, submit an action, and page through a session’s event history, so you can bring Custom Agents into a Slack bot, an internal tool, or a mobile client. The quickstart walks through a first request end to end with a personal access token.The beta also covers managing Custom Agents programmatically: find the agents a token can reach with Query agents, read per-agent usage with Retrieve agent insights, and set credit limits, enable, disable, or delete agents — individually or in an asynchronous batch.If you built against the private alpha routes for agents, threads, messages, or chat, see Upgrading to public beta. The replacements take JSON request bodies instead of query parameters and return sessions and events instead of threads and messages. Migrate off the alpha routes by September 30, 2026.

More filters in Notion MCP view tools

The notion-create-view and notion-update-view tools now apply relation, person, status, created by, last edited by, unique ID, last visited, verification, and place filters. Previously, some calls succeeded but saved a view without the requested filter.Use a page URL or ID for relation filters and a user ID or "me" for person filters. Invalid values now return an error. See Supported tools for accepted values, and read the notion://docs/view-dsl-spec resource for the full configuration syntax.Verification filters now round-trip through view responses for both matching (status) and non-matching (does_not_equal) conditions. Data source queries accept the same conditions.

Updating the query tool list in Notion MCP

New tool-list responses no longer include notion-query-database-view. Use notion-query-data-sources with mode: "view" for saved views. Clients with a cached tool list can still call notion-query-database-view; those calls continue to work and return migration guidance.The current_tool_access map returned by notion-fetch with the id self no longer has a query_database_view entry, since the map describes the tools that a current tool list advertises. See Supported tools for the tool list.

Multi-source SQL on Business plans in Notion MCP

notion-query-data-sources SQL queries that span multiple data sources now work on Business plans with Notion AI, which previously required an Enterprise plan. SQL is unlimited on Business and Enterprise plans with Notion AI; other plans keep the metered single-data-source allowance, and saved-view mode stays free on every plan.

JS SDK updates

@notionhq/client v5.25.1 fixes the isFullDataSource and isFullDatabase type guards, which previously accepted partial responses and narrowed them to the full type. Both now require the title field, the same structural check the other full-object guards use. isFullPageOrDataSource picks up the fix.v5.25.2 adds the does_not_equal condition to verification property filters in data source and database query request types, alongside the existing status condition.

prop() references in formula property writes

Formula expressions submitted through Update a data source now store prop("Property Name") references exactly as written. Previously, the API accepted some expressions but silently rewrote them — most visibly, a reference to a unique ID property dropped the ID’s prefix from computed values, and a prop() reference inside an array literal emptied the array. Expressions the API can’t store now return a validation_error instead. Formulas saved before this fix keep their old stored expression until you resubmit the update.Formula properties created through the API also now keep their result type, so number formatting options stay available in Notion and other formulas can reference them with prop().

Readable formula expressions in data source schemas

Retrieve a data source now returns formula expressions using the same prop("Property Name") syntax you write. Expressions that can’t be rendered faithfully in this syntax continue to use the internal property reference syntax.

Admin API reference for agents

The Admin API reference now covers the endpoints for managing agents in a workspace: credit usage and limits, permissions, status, creation policy, and workflow metadata.

Filter properties on page writes

Create a page and Update page properties now accept the same filter_properties query parameter as Retrieve a page. Pass the IDs of the properties you want, and the write response includes only those properties. This keeps responses small and fast for pages with many properties.SDK support: @notionhq/client v5.25.0 adds filter_properties to pages.create() and pages.update().

Reorganizing query tools in Notion MCP

Use notion-query-data-sources for both SQL queries and saved database views. To query a saved view, set mode to "view" and pass the same view_url.Existing notion-query-database-view calls continue to work and now include migration guidance. We plan to remove this older tool in a follow-up change.

Truncation metadata on notion-fetch

The notion-fetch MCP tool response now includes truncated, unknown_block_ids, and unknown_block_count when a page is large enough that some subtrees could not be loaded. unknown_block_ids lists up to 50 omitted subtree root IDs, and unknown_block_count reports the total number of omitted subtree roots. Pass a returned ID back to notion-fetch to retrieve that subtree directly; treat an object_not_found error on retry as a signal that the caller does not have access to the subtree.

unsupported formula and rollup property values

The API can now return formula and rollup page property values and property item values with type set to "unsupported" and an empty unsupported object. This happens when a value depends on too many related pages or nested formulas and rollups. The response doesn’t include a partial value. Treat the property as unavailable. Rollups still include the function field. To make the value available, reduce the number of related pages or simplify the nested formulas and rollups.

JavaScript SDK 5.24.0

We released @notionhq/client v5.24.0. It adds client.blocks.meetingNotes.create() for creating a meeting note, typed unsupported formula and rollup values, and APIErrorCode.InvalidBeta for handling invalid_beta responses.

Notion MCP supports MCP protocol version 2026-07-28

The Notion MCP Streamable HTTP endpoint at https://mcp.notion.com/mcp now supports MCP protocol version 2026-07-28. Existing MCP clients that negotiate the earlier 2025-era protocol on the same endpoint continue to work unchanged, so no client updates are required.

Clearer per-tool access status

The current_tool_access status previously called limited_free_trial is now available_with_limit. The new name makes clear that a tool is available until the usage limit included with the workspace’s plan is reached. This is a naming and description update only; it does not change tool availability or usage limits.

Fetch documentation resources with the fetch tool

The Notion MCP fetch tool now accepts notion://docs/* URIs (for example, notion://docs/enhanced-markdown-spec) and returns the same content as the MCP resource of the same URI. This gives MCP clients that cannot read MCP resources a way to load the specs referenced in tool descriptions.

Per-tool access map in notion-fetch self

The notion-fetch MCP tool’s self response now includes a current_tool_access map, so clients can tell before making a call which tools will actually run on the connected workspace’s plan and which would only return an upgrade prompt. Each entry’s status is available, limited_free_trial (calls succeed via a free or metered trial allowance), upgrade_required (the entry also carries an upgrade_url into the workspace’s upgrade flow), or not_enabled. See Integrating your own MCP client.

New identity fields in OAuth token responses

User objects now include an email_verified boolean next to person.email, indicating whether Notion has verified that email address. The field appears anywhere person emails do, including the owner in OAuth token responses and List all users results.Notion MCP token responses now include top-level user_id, workspace_id, and email_domain fields on successful authorization-code exchanges, so MCP clients can associate a connection with a Notion user and workspace without an extra call. See Integrating your own MCP client.New response fields like these are backwards-compatible additions and appear on every API version. Parse responses leniently: ignore fields you don’t recognize rather than rejecting them.As part of Notion’s move from notion.so to notion.com, the links Notion generates for its own records changed in early June 2026: the url values returned for pages, databases, and data sources, and the href values for page and database mentions, now point at the Notion app domain with a page path prefix, https://app.notion.com/p/{page-id}, instead of https://www.notion.so/{page-id}. Existing notion.so links continue to open correctly.These values are links for people to open in Notion, not stable identifiers: their domain and path format may change again. To reference a record, use its id field rather than parsing the URL, and use a page’s public_url to link to its published site. Links authored by users, such as link.url in rich text and URL property values, and links to sites published on notion.site or custom domains are unchanged.

Search the trash and query archived pages

Search accepts a new filter.in_trash option to list trashed pages and data sources (databases on API versions before 2025-09-03). Query a data source accepts a top-level is_archived body parameter to return archived pages instead of the default non-archived set.SDK support: @notionhq/client v5.23.2 adds filter.in_trash support to client.search(). v5.23.1 exports rich text annotation types and fixes pagination helper type compatibility with endpoint methods under strictNullChecks.

Longer-lived Notion MCP access tokens

Notion MCP access tokens now last about eight hours, up from one hour. Clients must continue to rely on the token response’s expires_in value, but the longer lifetime reduces refresh frequency and makes connections more resilient to client-side refresh failures.
We released v5.23.0 of @notionhq/client, our SDK for JavaScript and TypeScript. Here’s what’s new:

Verify webhook signatures with one call

The new verifyWebhookSignature() helper confirms that a webhook event really came from Notion, so you no longer need to hand-write the HMAC check. Pass the raw request body, the X-Notion-Signature header, and your subscription’s verification_token; the helper compares signatures in constant time and returns false instead of throwing on malformed input. It works without configuration in Node.js 18+, Bun, Deno, Cloudflare Workers, Vercel Edge Functions, and browsers. A companion signWebhookPayload() generates signatures for testing your handler.

Read every row in a large data source

A single data source query returns at most 10,000 results, so plain pagination can silently miss rows. The new iterateAllDataSourceRows() and collectAllDataSourceRows() helpers page past the limit using the windowing approach from the Query large data sources guide, de-duplicating rows along the way. Stream rows with the iterator, or collect them into an array when the full result fits in memory.

Start and poll async page writes

notion.asyncTasks.retrieve({ task_id }) adds typed support for the Retrieve an async task endpoint, and the page create and markdown update methods now accept allow_async: true. Together they let you run large markdown writes asynchronously: start the write without holding a request open, then poll until the task succeeds or fails.

Reliability and fixes

  • The client now automatically retries service_overload (HTTP 529) responses, respecting the Retry-After header as described in Request limits. Thanks to @RyanBillard for contributing this.
  • The relevance sort in search parameters now has the correct type, { property: "relevance" }.
  • Pagination parameters accept start_cursor: null, so you can pass a response’s next_cursor straight through without a null check.

HTML blocks via the API

You can now create HTML blocks with the API. Upload an .html file with the File Upload API and attach it to an embed block via embed.file_upload when appending block children, creating a page, or updating a block. The Notion app renders the file’s contents interactively in a sandboxed iframe — the same HTML block the app creates with the /html command and that agents create through Notion MCP.

Choose an expiration when creating a personal access token

When creating a personal access token in the Developer portal, you can now pick an Expiration of 7 days, 30 days, 90 days, 180 days, or 1 year. The default stays at 1 year, matching the previous behavior. The create dialog previews the exact expiration date, and the reveal step shows the same date next to the token value.The workspace admin view under Settings & members → Connections now also surfaces an Expired status and filter for PATs whose expiration has passed. Expired tokens stop authenticating and return an unauthorized error, and can still be revoked from the admin view or the Developer portal.

Icon names and database icons

When setting a native icon, name now also accepts the icon picker name, so values like "token" and "star circle" can set the same Notion icon.databases.retrieve now returns the icon set in the Notion UI, matching the icon surfaced by dataSources.retrieve.

Async page markdown writes

You can now opt into async responses for large page markdown create and update requests. Set allow_async: true when creating a page with POST /v1/pages and the markdown body parameter, or when updating page content with PATCH /v1/pages/:page_id/markdown. Notion returns an async_task handle with status_url and poll_after_seconds, which you can poll until the task succeeds or fails.Notion MCP also supports async page create and update flows through allow_async: true on notion-create-pages and notion-update-page, plus the notion-get-async-task polling tool. See Working with markdown content for examples.

Get workspace and user identity with notion-fetch

The notion-fetch MCP tool now accepts the special id self, returning the connected workspace and user identity instead of an entity. The response includes a self object with the workspace’s ID and name and the authenticated user’s ID, name, type, and email, letting MCP clients label a connection after OAuth without the public REST API. See Integrating your own MCP client.

Your AI assistant now has a complete, consistent view of Notion

We’ve expanded which Notion features are available when using AI assistants like Claude, ChatGPT, or any third-party agent connected to Notion via MCP.Expanded access for Business + Notion AI plansTeams on a Business plan with Notion AI can now query a single database or view directly from their AI assistant. This previously required Enterprise + Notion AI. Querying across multiple databases in a single query still requires Enterprise + Notion AI.Your assistant always knows what’s possiblePreviously, if a Notion feature wasn’t included in your plan, your AI assistant simply didn’t know it existed. This sometimes led to bad outcomes. For example, your assistant might repeatedly try to search for database properties, unaware that the right tool simply wasn’t visible to it.Now your assistant has a complete picture of what Notion can do. If a feature requires a higher plan, it will say so and point you toward an upgrade rather than silently attempting the wrong approach.

Status option groups

Status property option objects now accept an optional group field when creating or updating a database or data source schema. Use group to assign a custom status option to To-do, In progress, or Complete. When group is omitted on update, existing options keep their current group, and new options use To-do when present or the first existing group otherwise.

Workspace-level rate limits

The Notion API now applies a rate limit per workspace, in addition to the existing per-connection limit. This limit is shared across all of a workspace’s connections and scaled to the workspace’s plan, so requests can be rate limited even when a single connection is within the per-connection limit. As with other rate limits, respect the Retry-After header on HTTP 429 responses. See Request limits.

Bots in people properties and user mentions

Bots that appear as user objects in API responses can now be assigned to people page property values and referenced in user rich text mentions. You can set a people property when you create a page or update page properties. Previously these writes returned a validation_error, even though the same bots were already returned when reading those fields. Some bots never appear as user objects, including integrations Notion uses internally to power features like database automations and Custom Agents. Assigning one of those still returns a validation_error.

Unique access tokens per OAuth authorization

New public connections now mint a fresh access_token and refresh_token for each successful OAuth authorization instead of returning the existing active token. Existing connections keep their previous behavior. Store the token pair from every successful response — including re-authorizations of the same connection — as described in the Authorization guide.

Markdown page insertion positions

The Update page markdown endpoint now supports insert_content.position, letting integrations prepend markdown to the start of a page or explicitly append it to the end without rewriting the full page. See Working with markdown content for examples.

Developer portal and personal access tokens

The new Developer portal is now available as a single place to manage developer tools for Notion, including connections, Workers, and personal access tokens.Personal access tokens (PATs) are user-scoped tokens for scripts, CLI workflows, Workers, and trusted tools that should act with one Notion user’s permissions. PATs can be granted Notion API access, Workers access, or both.Workspace admins can now view and revoke PATs created in their workspace. On supported plans, admins can also configure who may create PATs with Notion API access. Defaults vary by plan: Free workspaces default to workspace owners only, Plus workspaces default to all workspace members, Business workspaces default to workspace owners only, and Enterprise workspaces default to workspace owners and selected groups.

Query meeting notes endpoint

The new Query meeting notes endpoint (POST /v1/blocks/meeting_notes/query) returns AI meeting notes for the integration’s user with optional filter, sort, and limit. The attendees alias is normalized server-side so filters round-trip cleanly.

agent_id parent type

Pages and blocks parented by an agent now serialize their parent as { "type": "agent_id", "agent_id": "..." } instead of being rejected or rewritten. See Parent object for the full list of parent types.SDK support: @notionhq/client v5.21.0 adds typed support for notion.blocks.meetingNotes.query() and the agent_id parent variant.
Improvements to pagination reliability for the Query a data source endpoint:
  • Pagination cursors now embed a session identifier, eliminating intermittent 400 validation_error (“The start_cursor provided is invalid”) errors that could occur when multiple pagination sessions for the same query overlapped.
  • The start_cursor parameter now accepts opaque string values in addition to UUIDs. Existing UUID-based cursors continue to work. As documented in our versioning policy, cursors should always be treated as opaque — pass next_cursor values back as start_cursor without parsing or validating their format.

Data source and view query pagination limit

The Query a data source, Create a view query, and Get view query results endpoints now enforce a maximum pagination depth of 10,000 results per query. When a query matches more rows than this limit, the response includes a new request_status field:
Integrations that polled these endpoints to iterate through all matching rows in a large data source should check for request_status.type === "incomplete" and adapt accordingly. The limit improves reliability for all API users by bounding the server-side resources consumed by each query.If your integration needs to process all pages in a large data source, we recommend:SDK support: @notionhq/client v5.20.0 adds typed support for the request_status field on affected list responses.

Update and delete comment endpoints

The Update a comment (PATCH /v1/comments/:comment_id) and Delete a comment (DELETE /v1/comments/:comment_id) endpoints are now generally available. Non-DLP integrations can only modify or delete comments they created.

Multi-value filters for select, status, and multi_select properties

Database and data source filters now accept an array of values for equals / does_not_equal on select and status properties, and for contains / does_not_contain on multi_select properties, matching the multi-value conditions available in the Notion UI. The same schema is used by view filters and quick filters. Person filters set via the API also now round-trip cleanly on read without extra combinator nesting.

Notion MCP improvements

  • The search tool no longer drops Slack DMs and private channel results when the connected workspace has the Slack integration enabled.
  • The fetch tool now accepts any first-party Notion domain for the current environment (both notion.so and notion.com), fixing cases where pasted links fell through as generic webpages.
  • Page resources returned by the fetch tool now include is_archived so agents can tell when a page is in the trash.
  • The enhanced Markdown guidance the MCP presents to LLMs now documents <br> as the correct way to break lines inside inline code, preventing retry loops when agents write multi-line inline code via update_page.
  • The Notion MCP OAuth server adds Client ID Metadata Document (CIMD) support per MCP spec 2025-11-25, letting clients use an HTTPS URL as their client_id instead of going through Dynamic Client Registration.

Comment markdown formatting clarification

The Create a comment and Update a comment references now explicitly document that the markdown body parameter supports inline formatting only — fenced code blocks, headings, lists, tables, and blockquotes do not render as structured blocks in comments.SDK support: @notionhq/client v5.18.0 adds typed support for multi-value select, status, and multi_select filters. v5.19.0 adds notion.comments.update() and notion.comments.delete().

Markdown body parameter for comments

The Create comment endpoint now accepts an optional markdown string body parameter as an alternative to rich_text. Exactly one of rich_text or markdown must be provided. See the endpoint reference for supported formatting and usage details.SDK support: @notionhq/client v5.17.0 includes typed support for the markdown comment body parameter.

What’s new

The Developer Terms have been updated with clarifications to scope, revisions to the Feedback provision, and other minor revisions.

Heading 4 block type

heading_4 is now a supported block type. You can create, read, and update heading 4 blocks through the Append block children, Retrieve a block, and Update a block endpoints, matching the existing heading_1, heading_2, and heading_3 block types.

Tab item icons

Paragraph blocks that are direct children of tab blocks now support an optional icon field. You can set icons on tab items when creating tabs via Append block children or Create a page, and update them via Update a block. Icons on paragraphs that are not tab items are rejected with a validation error.

”me” relative filter for people properties

People filter conditions now accept "me" as a value for contains and does_not_contain, in addition to user UUIDs. For public integrations, "me" resolves to the user who authorized the connection. For internal integrations, "me" does not resolve to a user — a contains: "me" filter will return no results and a does_not_contain: "me" filter will match all entries. Works across database queries, data source queries, view filters, and quick filters.

Relative date filter values

Date filter conditions that accept an ISO 8601 date string (equals, before, after, on_or_before, on_or_after) now also accept the following relative date values: "today", "tomorrow", "yesterday", "one_week_ago", "one_week_from_now", "one_month_ago", "one_month_from_now". These are resolved at query time relative to the current date. See the date filter reference for details.

View API fixes

Several fixes to the views API:
  • Percent-encoded property IDs: Property IDs returned by the API (e.g. %7DUlu) are now correctly resolved when used in view filters, sorts, group-by, and other property references.
  • width: 0 rejected: Column widths must now be at least 1. A width of 0 was previously accepted but had no effect.
  • Partial properties list: Specifying a subset of properties in a view now correctly hides unlisted properties instead of showing all properties.
SDK support: @notionhq/client v5.16.0 includes typed support for heading 4, tab item icons, and the "me" person filter value.

Tab block support

Tab blocks are now a supported block type in the API. Use tabs to organize content into labeled sections within a page.
  • Read: Retrieve a block and Retrieve block children return tab blocks with type: "tab" and an empty tab: {} object. Each tab within the container is a paragraph block — the rich_text is the tab label, the icon is the tab icon, and the children contain the tab’s content.
  • Create: Append block children accepts type: "tab" blocks. Each tab is a paragraph block with nested children and an optional icon. Only paragraph blocks can be direct children of a tab block.

Writable verification property

The verification property on wiki database pages can now be set and updated via the Create page and Update page endpoints. Set state to "verified" or "unverified", with an optional date object for expiration. The verified_by field is automatically set to the acting integration and cannot be overridden.

Native icons and custom emoji listing

Two icon-related improvements:
  • Native Notion icons: A new type: "icon" variant is available on all icon fields (pages, databases, callout blocks). Specify an icon by name and optional color (defaults to "gray"). Previously, native icons were returned as type: "external" with SVG URLs — they are now returned in the structured icon format.
  • Custom emoji listing: A new List custom emojis endpoint (GET /v1/custom_emojis) retrieves workspace custom emojis with cursor pagination and an optional name filter for exact-match lookups.
SDK support: @notionhq/client v5.15.0 adds notion.customEmojis.list() and typed support for tab blocks, verification writes, and native icons.

Views API

We’ve launched the /v1/views API. Eight new endpoints let integrations programmatically manage database views — the same view presets that users create in the Notion UI:Supported view types include table, board, calendar, timeline, gallery, list, form, chart, map, and dashboard. Views can be configured with filters, sorts, quick filters, and type-specific layout settings like grouping, cover images, subtasks, and chart options.Dashboard views support a full grid layout with widget placement — add, position, and remove widget views within rows.Three new webhook events (view.created, view.updated, view.deleted) are available on API version 2025-09-03 and later.SDK support: @notionhq/client v5.14.0 adds notion.views.* and notion.views.queries.* methods.

Status property support

You can now create and update status properties through the Notion API and Notion MCP. Previously, status properties were read-only — they could be queried but not created or modified via the API.
  • Create: pass { status: {} } in a Create database or Create data source request to add a status property with default options (Not started, In progress, Done). Custom initial options are also supported.
  • Update: add new options to an existing status property via Update data source, following the same pattern as select and multi_select.
  • MCP: the notion-create-database and notion-update-data-source tools now support the STATUS column type in their schema definitions.

New API version: 2026-03-11

We’ve released Notion API version 2026-03-11 with three breaking changes that simplify and modernize the API surface:
  • after replaced by position: The Append block children endpoint now uses a position object instead of a flat after string parameter, enabling more flexible block placement (including start and end positioning).
  • archived replaced by in_trash: All endpoints now use in_trash instead of archived in both request parameters and response bodies. The archived field was deprecated in April 2024 and is now fully removed in this version.
  • transcription renamed to meeting_notes: The transcription block type has been renamed to meeting_notes across all block endpoints.
Most integrations only need simple find-and-replace updates. See the upgrade guide for step-by-step instructions.SDK support: @notionhq/client v5.12.0 adds support for 2026-03-11. Upgrade the SDK and set notionVersion: "2026-03-11" to opt in.

Notion MCP: new view tools

Two new tools are available in Notion MCP:
  • notion-create-view — Create new database views with filters, sorts, grouping, display properties, and layout-specific settings (calendar, timeline, etc.).
  • notion-update-view — Update an existing view’s configuration. Accepts view:// URIs, Notion URLs with ?v=, or bare UUIDs.
See Supported tools for details and example prompts.

Markdown content API improvements

The Update page markdown endpoint now supports two additional command types:
  • update_content — Make targeted edits with an array of search-and-replace operations (old_str / new_str). Recommended for precise, multi-site edits.
  • replace_content — Replace the entire page content with new markdown in a single operation.
We recommend update_content and replace_content over the older insert_content and replace_content_range commands. See Working with markdown content for usage examples.

Template timezone parameter

The Create page and Update page endpoints now accept an optional timezone field inside the template parameter. This controls how template variables like @now and @today resolve — for example, "America/New_York" ensures dates reflect Eastern Time instead of defaulting to UTC. See the Creating pages from templates guide for details.
  • The GET /v1/pages/:page_id/markdown endpoint is now available to internal integrations (workspace-level bots), in addition to public integrations.
  • Released v5.11.1 of our TS/JS SDK. UnsupportedBlockObjectResponse now includes a block_type string field indicating the underlying block type.
We released v5.10.0 and v5.11.0 of our SDK for JavaScript and TypeScript. Here’s what’s new in the Notion API:

Markdown content API

Three new endpoints let you create, read, and update page content using enhanced markdown instead of the block-based API:See Working with markdown content and the Enhanced markdown format reference for details.

AI meeting notes

  • The GET /v1/pages/:page_id/markdown endpoint supports an include_transcript query parameter to include full meeting note transcripts in the response.
  • Added support for the transcription block type, enabling integrations to read AI meeting notes metadata — including title, status, calendar event details, and pointers to summary, notes, and transcript content blocks.

SDK improvements

  • Automatic retry with exponential backoff — the SDK now retries failed requests automatically with configurable backoff (v5.10.0).
  • Markdown endpoint methods — pages.retrieveMarkdown() and pages.updateMarkdown() (v5.11.0).

Notion MCP improvements

Highlighting recent changes to Notion MCP:
  • Create and fetch comments on blocks, not just pages.
  • View Notion Sites pages via the fetch tool.
  • Fetch AI meeting transcripts and query meeting notes efficiently with the new notion-query-meeting-notes tool.
  • Fetch an individual data source by ID or URL within a database.
  • ~91% context token reduction in notion-create-database and notion-update-data-source tools by switching to SQL DDL-based schemas.
  • Added update_verification command to the notion-update-page tool.
  • Flattened notion-update-page tool parameters and fixed schema issues for improved compatibility with MCP clients.
  • Enterprise governance: audit logging for MCP tool usage and admin tool allowlisting.
We recommend reconnecting Notion MCP in your third-party AI tools to ensure you have the most up-to-date tools and resources.
We released v5.7.0 of our SDK for JavaScript and TypeScript. Since the last changelog entry, we’ve added the following fixes and improvements to the Notion API:Highlighting recent LLM-facing changes to Notion MCP, our remote Model Context Protocol (MCP) server for AI tools:
  • Released notion-query-data-sources tool to Enterprise Notion workspaces with access to Notion AI.
  • Tool consolidation: notion-get-user has been removed & its functionality has been rolled into notion-get-users.
  • Fixed a bug causing child content to be deleted by the notion-update-page tool when using replace_content and replace_content_range modes.
  • Removed Notion-flavored Markdown specification from notion-create-pages tool to conserve context tokens, since it exists behind a dedicated MCP Resource as well.
We recommend reconnecting Notion MCP in your third-party AI tools to ensure you have the most up-to-date tools and resources.
We released v5.1.0 of @notionhq/client, our SDK for JavaScript and TypeScript. This includes the following fixes and improvements:
  • Add support for is_locked boolean parameter on update page and database APIs (to update whether a page is locked in the Notion app UI)
  • dataSource.update: add support for changing a data source’s parent database
  • Remove page_id as a possible parent for CreateDataSourceBodyParameters
  • Add request_id to Client log lines
As noted in the library’s README, v5 and above of the SDK isn’t compatible with API versions older than 2025-09-03. See the upgrade guide to learn more.

Important API update coming September 3rd

We’re introducing multi-source databases to Notion! Our new API version 2025-09-03 separates “databases” (containers) from “data sources” (tables), unlocking powerful new organizational capabilities.

What you need to know:

  • Current integrations continue working with single-source databases
  • Update to the new API version to support multi-source databases
  • We’re introducing the concept of API versioning to integration webhooks as well
Start upgrading your integrations now to ensure a smooth transition when users begin creating additional data sources starting from September 3rd.Full details and migration guide: Upgrading to 2025-09-03General information about API versioning: Versioning

What’s new

  • Revised Section 1.1 to refine the scope of application of the Developer Terms.
  • Revised Section 3.1 to clarify prohibited uses of the API and created a new Section 3.2 for formatting purposes

What’s new

We are excited to announce an update to our Notion Public API token format.Starting September 25, 2024, newly generated Public API tokens will automatically use the ntn_ prefix instead of the**secret_** prefix.

Why the change?

This change is part of our ongoing efforts to improve the security of our API. By introducing the ntn_ prefix, we aim to:
  • Enhance compatibility with secret scanners and other security tools, making it easier to identify and manage Notion API tokens.
  • Provide a clearer distinction between Notion API tokens and other types of secrets, reducing the risk of misconfiguration and improving overall security.

What do you need to do?

  • New Integrations: For any new integrations, the tokens will be automatically generated with the ntn_ prefix. Simply generate your tokens as usual through the Notion API settings page.
  • Existing Tokens: All existing tokens with the secret_ prefix will continue to work without any changes. There is no immediate need to update your existing integrations.
  • Token Format: We strongly advise against using regular expressions (regex) to identify or validate Notion Public API tokens. The token format may change over time, and relying on regex patterns could lead to false positives or negatives. Instead, treat the token as an opaque string and use it as provided.
  • Best Practices: To handle Notion API tokens securely:
    • Store tokens securely using appropriate encryption methods.
    • Use Notion’s official SDKs or libraries when available, as they handle token management correctly.
    • Validate tokens by making authenticated requests to Notion’s API rather than parsing the token itself.

Questions or concerns?

If you have any questions or need assistance with this transition, please feel free to reach out to our support team or visit our docs.

What’s new

Revised Section 3.1 of the Developer Terms to include additional security and data use restrictions.

What’s new

  • Added: New property in_trash to indicate whether a page/block/database has been deleted or placed in “Trash”.
  • in_trash is the preferred field going forward. The archived property is a deprecated alias for in_trash and may be removed in a future API version. New integrations should use in_trash exclusively.

What’s new

  • We added support for reading and writing names to file blocks in the public API. Read more here.
  • We fixed the types in the SDK to support appending table and column blocks as children of toggle blocks.
  • We updated the emoji and timezones available in the SDK.
  • We added support for australian_dollar in the format field of number database properties.

What’s new

  • The Examples page was updated with all our most recent demo code. We’ve organized these sample integrations by level of experience with the Public API to help developers who are newer to the Public API find introductory code more easily.
  • A note was added to all API endpoint documentation directing developers to review the Status codes page for a complete list of error codes that can be returned by API requests.
  • A clarification was added to the Request limits page and Append block children endpoint documentation to indicate the current limit for appending a list of block children per API request. Up to 100 block children can be appended at a time.

What’s new

Looking for older updates?Changelog entries from before September 2023 are now kept in a separate page: Historical changelog.