Notion Action
Create and update Notion pages, read their content as Markdown, and query rows out of a database — as a step in a pipeline. Twelve operations against Notion's REST API, with the page body handled as plain Markdown instead of a hand-built block tree.
Overview
The Notion Action node runs one operation per event. It appears on the canvas in a warm grey card — Notion's own brand is monochrome.
··· › Connections), every picker in this node comes back empty and every call 404s. It is the number one cause of "I set it up and nothing happens".Credential
Two ways in, and they coexist. Both are created either inline on the node or in Settings › Credentials.
Connect Notion (recommended)
Click Connect Notion, authorize, and pick which pages and databases the connection can reach — right there on Notion's consent screen. Nothing to copy, and no integration for the user to create. Stored as notion_oauth.
Your own integration
Prefer to run against a single workspace with your own app? Create an internal integration at notion.so/profile/integrations and paste its secret — it starts with ntn_. Stored as notion_internal. It works the same minute you create it and needs nothing published on our side.
Operations
Twelve, grouped by the Notion object they work against. The dropdown shows each one's endpoint next to its name, so you can cross-check it against Notion's own documentation.
| Operation | Endpoint | What it does |
|---|---|---|
| Create page | POST /pages | A row in a database, or a subpage. Body goes in as Markdown. |
| Get page | GET /pages/{id} | The page object and its properties — not its content. |
| Get page as Markdown | GET /pages/{id}/markdown | The whole body as one Markdown string. |
| Update page properties | PATCH /pages/{id} | Status, dates, relations. Only what you list is touched. |
| Update page content | PATCH /pages/{id}/markdown | Replace the body, or find-and-replace inside it. |
| Append content | PATCH /pages/{id}/markdown | Add at the top or the end without touching what is there. |
| Archive page | PATCH /pages/{id} | To the trash, or back out of it. Recoverable for 30 days. |
| Query data source | POST /data_sources/{id}/query | Rows matching a filter. Output is iterable. |
| Get data source schema | GET /data_sources/{id} | Which properties exist and what type each one is. |
| Get block children | GET /blocks/{id}/children | The raw block tree, one level down. iterable |
| Search | POST /search | By title only, not content. iterable |
| Add comment | POST /comments | On a page, or as a reply in an existing thread. |
Content is Markdown, not blocks
Writing content to Notion used to mean building a block tree by hand: every paragraph, heading and list item as its own typed object. It is the most expensive part of that API, and it is where most integrations stop at "create an empty page".
This node uses Notion's Markdown endpoints instead, so writing a page is sending text. Templates work inside it like anywhere else:
## Incident {{payload.id}}
Reported by **{{payload.reporter}}** at {{payload.timestamp}}.
- Severity: {{payload.severity}}
- Service: {{payload.service}}Databases and data sources
Since Notion's 2025-09-03 API version, a database holds one or more data sources, and rows live in the data source — not in the database. Most databases have exactly one, and the picker resolves it for you. Anything you read online that queries databases/{id}/query is written against the previous API.
A row is a page in Notion — same object, different parent. That is why "Create page" is also how you add a row.
Filtering a query
The three filter fields — property, condition, value — cover the common case. Behind them the node fetches the data source schema first, because Notion has no generic filter: the key inside a filter clause is the type of the property, and the same "equals" is spelled differently for a select, a date and a number. That is one extra request, and it is the difference between a filter that works and a 400 that does not name the field.
Page and database ids
Pick from the list when you can. When you cannot — because the target comes from the event — paste a URL, an id, or a template like {{payload.pageId}}. All three work: the node normalizes whatever you give it.
?v= is also a 32-character id. The node trims the query first, so it takes the page and not the view.Rate limits
Notion allows about three requests per second on average per connection, plus a per-workspace ceiling that scales with the workspace's plan. A 429 here is ordinary, not an incident.
The node retries on 429, 529 and the usual gateway errors, waiting as long as Notion asks in its Retry-After header. Failures that are ours — a missing credential, malformed JSON, a property that does not exist — come back as 400 and are not retried, because they will not improve.
Firing a pipeline from Notion
This node is the write side. To have Notion start a pipeline, use the Trigger node with its Notion service — it polls a database or the workspace and fires on pages added or edited.
Cost
Notion's API is free on every plan, with no per-call charge. The only paid piece in Notion's own product is the no-code webhook action inside their automations, which this node does not use.