When to Use
- Sync freshness check: Before syncing a page's data to an external system, call
page/get and compare last_edited_time against the last sync timestamp. Skip unchanged pages to avoid unnecessary writes.
- Workflow branching on property values: Retrieve a page to read its current
Status or Priority property, then use an IfCondition node to branch the workflow based on the value.
- Archive guard: Before updating a page, check the
archived field. If true, skip the update and log a warning — writing to an archived page will fail.
- URL extraction for notifications: Retrieve the
url field and include it in an email or Slack message so recipients can navigate directly to the Notion page.
- Property audit: Fetch individual pages from a list to audit whether required properties (e.g., Assignee, Due Date) are set. Flag missing values for follow-up.
Configuration
Authentication
| Field | Required | Description |
AuthenticationMethod | Required | "ApiToken" or "OAuth2". |
ApiToken | Required | Notion Internal Integration Token starting with secret_. |
ClientId | OAuth2 | OAuth2 client ID. |
ClientSecret | OAuth2 | OAuth2 client secret. |
AccessToken | OAuth2 | OAuth2 access token. |
Operation Fields
| Field | Required | Description |
Page | Required | Notion page UUID. Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. |
Simplify | Optional | When true, flattens property values to plain types (e.g., Status: "In Progress" instead of the full Notion property object). Default: false. |
Sample Configuration
{
"resource": "page",
"operation": "get",
"AuthenticationMethod": "ApiToken",
"ApiToken": "{{ $credentials.notionApiToken }}",
"Page": "{{ $json.pageId }}",
"Simplify": true
}
Validation Errors
| Error Code | Cause |
NOTION_VALIDATION_FAILED | Page field is empty or not a valid UUID format. |
NOTION_NOT_FOUND | No page exists with the given UUID, or the page has been permanently deleted. |
NOTION_PERMISSION_DENIED | Integration not shared with this page or its parent database. |
NOTION_UNAUTHORIZED | API token is invalid. |
NOTION_RATE_LIMITED | Rate limit exceeded. Add a Delay node when calling in a loop. |
Output
Success Port
| Field | Type | Description |
id | string | Page UUID. |
url | string | Full Notion URL to open the page. |
created_time | string | ISO 8601 creation timestamp. |
last_edited_time | string | ISO 8601 timestamp of the last edit. |
archived | boolean | true if the page is archived. |
parent | object | Parent reference — either database_id or page_id. |
properties | object | All property values. Structure depends on Simplify: raw Notion objects when false, flattened plain values when true. |
icon | object | Page icon. Contains type ("emoji" or "external") and the icon value. |
Error Port
On failure the error port receives errorCode, message, and httpStatus. Handle NOTION_NOT_FOUND gracefully when page IDs come from user input or external systems that may reference deleted pages.
Sample Output
{
"id": "b8c9d0e1-f2a3-4567-bcde-678901234567",
"url": "https://www.notion.so/b8c9d0e1f2a34567bcde678901234567",
"created_time": "2024-05-20T09:00:00.000Z",
"last_edited_time": "2024-06-10T15:30:00.000Z",
"archived": false,
"icon": { "type": "emoji", "emoji": "📋" },
"properties": {
"Name": {
"type": "title",
"title": [{ "plain_text": "Build login page" }]
},
"Status": {
"type": "select",
"select": { "name": "In Progress" }
},
"Assignee": {
"type": "people",
"people": [{ "name": "Sarah Chen", "id": "user-uuid-1" }]
},
"Due": {
"type": "date",
"date": { "start": "2024-06-15" }
}
},
"parent": {
"type": "database_id",
"database_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
Expression Reference
| Expression | Type | Use |
{{ $output.getPage.last_edited_time }} | string | Compare against last sync timestamp |
{{ $output.getPage.archived }} | boolean | Guard against writing to archived pages |
{{ $output.getPage.url }} | string | Include in notification messages |
{{ $output.getPage.properties.Status.select.name }} | string | Read select property for workflow branching |
{{ $output.getPage.properties.Assignee.people[0].name }} | string | Get assignee name for routing notifications |
{{ $output.getPage.properties.Due.date.start }} | string | Read due date for scheduling logic |
Node Policies & GuardRails
| Policy | Detail |
| Check archived before update | Always check archived === false before calling page/update on a page. Attempting to update an archived page returns an error. Use an IfCondition node to gate the update. |
| Use Simplify for expressions | Enable Simplify: true when reading property values in downstream expressions — it removes the deeply nested Notion property structure and returns plain string/number/date values, making expressions significantly shorter. |
| Null-safe people access | The people property returns an empty array when no assignee is set. Always check people.length > 0 before accessing people[0].name to avoid null reference errors. |
| page/get returns metadata only | This operation returns page properties and metadata — it does NOT return the page body content (blocks). Use block/getChildren to retrieve the page body. |
| Credentials in Credentials Manager | Always use {{ $credentials.notionApiToken }} — never hard-code the token. |
Workflow Examples
Example 1 — Sync Freshness Gate
Before exporting a page's data to an external system, check whether it has been edited since the last sync.
// Step 1: page/get
{ "Page": "{{ $json.pageId }}", "Simplify": true }
// Step 2: IfCondition
// Condition: {{ $output.getPage.last_edited_time }} > {{ $vars.lastSyncTime }}
// True: proceed to export
// False: StopWorkflow (no changes)
Example 2 — Status-Gated Update
Read the current page status. Only proceed with the update if the page is not already marked "Done" and is not archived.
// Step 1: page/get { "Page": "{{ $json.pageId }}", "Simplify": true }
// Step 2: IfCondition
// Condition 1: {{ $output.getPage.archived }} === false
// Condition 2: {{ $output.getPage.properties.Status }} !== "Done"
// Both true: proceed to page/update
// Otherwise: log and stop
Example 3 — Notification with Page URL
After a trigger fires on a page, fetch the page to get its title and URL, then send a Slack alert to the assignee.
// Step 1: page/get { "Page": "{{ $trigger.pageId }}" }
// Step 2: user/get to resolve assignee Slack ID
// Step 3: Slack/postMessage
{
"channel": "@{{ $json.assigneeSlackId }}",
"text": "Task updated: {{ $output.getPage.properties.Name.title[0].plain_text }}\n{{ $output.getPage.url }}"
}