trigger/pageUpdated
Polling trigger that fires for each page in a Notion database whose last_edited_time has changed since the last poll. Detects any property or content change on existing pages and emits one execution per updated page.
Polling-based — not real-time: This trigger polls the database on a schedule and compares
last_edited_time values against those seen in the previous poll. It cannot identify which specific property changed — only that the page was edited. Use a page/get call downstream to read current property values and apply conditional logic.
When to Use
- Notion-to-Jira status sync: When a task's Status property is updated in Notion, detect the change and call the Jira node to transition the corresponding issue to the matching state, keeping both systems in sync.
- Edit notification: Notify a team member or Slack channel when a specific database page is edited — useful for review workflows where editors need to be notified when content is changed.
- Auto-archive on terminal status: When a page's Status changes to "Done" or "Cancelled", automatically archive the page using
page/archiveto clean up the active database view. - Content publishing detection: Trigger downstream processing when a content review page's status moves to "Approved" — for example, pushing the content to a CMS or publishing channel.
- Conditional downstream sync: When any page in a contact database is updated, re-sync the record to Salesforce to ensure the external CRM always reflects the latest Notion data.
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. |
Trigger Fields
| Field | Required | Description |
|---|---|---|
Database | Required | UUID of the database to monitor for page updates. |
PollingInterval | Optional | Cron expression. Example: "*/5 * * * *" (every 5 minutes). Default: every minute. |
Simplify | Optional | When true, flattens property values for easier downstream expression access. Default: false. |
No field-level change detection: This trigger detects that a page was edited but does not identify which properties changed. To determine whether a specific field (e.g., Status) changed, read the current value via
page/get or use Simplify: true and compare property values against cached state in a workflow variable.
Sample Configuration
{
"resource": "trigger",
"operation": "pageUpdated",
"AuthenticationMethod": "ApiToken",
"ApiToken": "{{ $credentials.notionApiToken }}",
"Database": "{{ $vars.tasksDatabaseId }}",
"PollingInterval": "*/5 * * * *",
"Simplify": true
}
Validation Errors
| Error Code | Cause |
|---|---|
NOTION_VALIDATION_FAILED | Database is empty or not a valid UUID. |
NOTION_PERMISSION_DENIED | Integration not shared with the target database. |
NOTION_NOT_FOUND | Database UUID does not exist. |
NOTION_UNAUTHORIZED | API token is invalid. |
NOTION_RATE_LIMITED | Polling interval is too frequent for the database size. Increase the interval. |
Output
Trigger Output (per updated page)
| Field | Type | Description |
|---|---|---|
id | string | UUID of the updated page. |
url | string | Notion URL for the updated page. |
created_time | string | Original creation timestamp. |
last_edited_time | string | ISO 8601 timestamp of the edit that caused this trigger to fire. |
properties | object | Current property values. Structure depends on Simplify setting. |
parent | object | Parent database reference. |
Error Port
On poll failure the error port receives errorCode, message, and httpStatus.
Sample Output
{
"id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"url": "https://www.notion.so/e5f6a7b8c9d01234efab345678901234",
"created_time": "2024-06-01T08:00:00.000Z",
"last_edited_time": "2024-06-11T15:20:00.000Z",
"properties": {
"Name": {
"type": "title",
"title": [{ "plain_text": "Build login page" }]
},
"Status": {
"type": "select",
"select": { "name": "Done" }
},
"Assignee": {
"type": "people",
"people": [{ "name": "Sarah Chen", "id": "user-uuid-1" }]
}
},
"parent": {
"type": "database_id",
"database_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
Expression Reference
| Expression | Type | Use |
|---|---|---|
{{ $trigger.id }} | string | Updated page UUID — pass to page/update or page/archive |
{{ $trigger.last_edited_time }} | string | Store as new sync timestamp |
{{ $trigger.properties.Status.select.name }} | string | Read new status value for conditional routing |
{{ $trigger.properties.Name.title[0].plain_text }} | string | Include page title in notifications |
{{ $trigger.url }} | string | Link to updated page in Slack or email alert |
Node Policies & GuardRails
| Policy | Detail |
|---|---|
| No previous-value access | The trigger provides only the current page state — not a before/after diff. If you need to detect a specific property change (e.g., Status from "Review" to "Done"), cache the last known value in a workflow variable and compare on each execution. |
| Rapid edits may be batched | If a page is edited multiple times between polls, only one trigger fires — the most recent state is returned. Multiple edits do not produce multiple executions. |
| Self-update loop prevention | If this workflow updates the same page it just triggered on (e.g., setting a "Processed" property), the next poll will detect that update and re-fire. Use an IfCondition to check whether the triggering edit came from automation before processing: e.g., Processed !== true. |
| Use Simplify for cleaner expressions | Enable Simplify: true to get plain string/number values from properties instead of the nested Notion structure. This significantly reduces expression complexity in downstream conditions. |
| Credentials in Credentials Manager | Always use {{ $credentials.notionApiToken }} — never hard-code the token. |
Workflow Examples
Example 1 — Sync Notion Status to Jira
When a task status is updated in Notion, find the corresponding Jira issue and execute the matching transition.
// Trigger: trigger/pageUpdated (Sprint Tasks DB, Simplify: true)
// Step 1: IfCondition — Status changed to "Done"
// (Check: properties.Status === "Done")
// Step 2: Function node — get Jira key from JiraKey property
// Step 3: Jira issue/gettransitions { IssueKey: jiraKey }
// Step 4: Jira issue/executetransition { TransitionId: doneTransitionId }
Example 2 — Auto-Archive on Done Status
Automatically archive completed project pages when they are marked Done in the database.
// Trigger: trigger/pageUpdated (Projects DB, Simplify: true)
// Step 1: IfCondition
// Condition: {{ $trigger.properties.Status }} === "Done"
// True: page/archive { "Page": "{{ $trigger.id }}" }
// Slack message: "Archived: {{ $trigger.properties.Name }}"
Example 3 — Content Publishing Pipeline
When content review status moves to "Approved", push content to the CMS and notify the content team.
// Trigger: trigger/pageUpdated (Editorial Calendar DB, Simplify: true)
// Step 1: IfCondition — ReviewStatus === "Approved"
// Step 2: block/getChildren — read the content body
// Step 3: Function node — build CMS payload from blocks
// Step 4: HttpRequest POST — publish to CMS API
// Step 5: page/update — set PublishedAt date
// Step 6: Slack #content-team notification with page URL