trigger/pageAdded
Polling trigger that fires for each new page added to a Notion database since the last poll. Checks the database on a configured schedule and emits one workflow execution per new page found.
Polling-based trigger: Notion does not natively push webhooks for new database records. This trigger polls the database using
database/query internally, comparing new created_time values against the cursor stored from the last poll. The minimum polling resolution is determined by your workflow's polling interval setting.
When to Use
- New form submission processing: When users submit a BizFirst Form or a third-party form that writes to a Notion database, this trigger starts a workflow for each new submission row — enabling routing, validation, and downstream system integration.
- Employee onboarding kickoff: When HR adds a new employee page to the onboarding database, trigger an automated onboarding workflow that provisions accounts, sends welcome emails, and schedules check-in meetings.
- New project notifications: Notify the team in Slack when a new project page is added to the project tracking database, including key fields like project lead, start date, and priority.
- CRM-to-external system sync: Sync each new Notion CRM record to Salesforce or HubSpot as a new lead, running deduplication and enrichment steps before writing to the external system.
- Content pipeline initiation: When a new content brief is added to the editorial calendar database, trigger a workflow that assigns a writer, sets deadlines, and notifies stakeholders.
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 new pages. |
PollingInterval | Optional | Cron expression for the polling schedule. Example: "*/5 * * * *" (every 5 minutes). Default: every minute. |
Polling latency: This trigger checks the database on a schedule — it is not real-time. With a 1-minute polling interval, a new page may not trigger the workflow for up to 60 seconds after it appears in Notion. Reduce the interval for time-sensitive use cases, but note that more frequent polling consumes more API quota against the 3 req/s limit.
Sample Configuration
{
"resource": "trigger",
"operation": "pageAdded",
"AuthenticationMethod": "ApiToken",
"ApiToken": "{{ $credentials.notionApiToken }}",
"Database": "{{ $vars.submissionsDatabaseId }}",
"PollingInterval": "*/2 * * * *"
}
Validation Errors
| Error Code | Cause |
|---|---|
NOTION_VALIDATION_FAILED | Database field 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 too frequently or database is large. Increase the polling interval. |
Output
Trigger Output (per new page)
| Field | Type | Description |
|---|---|---|
id | string | UUID of the new page. |
url | string | Notion URL for the new page. |
created_time | string | ISO 8601 timestamp when the page was created. |
last_edited_time | string | ISO 8601 timestamp of last edit at trigger time. |
properties | object | All property values of the new page in Notion property object format. |
parent | object | Parent database reference containing database_id. |
Error Port
On poll failure the error port receives errorCode, message, and httpStatus. Wire to a notification node to alert on persistent authentication or permission failures.
Sample Output
{
"id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"url": "https://www.notion.so/e5f6a7b8c9d01234efab345678901234",
"created_time": "2024-06-11T10:45:00.000Z",
"last_edited_time": "2024-06-11T10:45:00.000Z",
"properties": {
"Name": {
"type": "title",
"title": [{ "plain_text": "New Support Request: Login Issue" }]
},
"Status": {
"type": "select",
"select": { "name": "Open" }
},
"Email": {
"type": "email",
"email": "customer@example.com"
},
"Priority": {
"type": "select",
"select": { "name": "High" }
}
},
"parent": {
"type": "database_id",
"database_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
Expression Reference
| Expression | Type | Use |
|---|---|---|
{{ $trigger.id }} | string | New page UUID — pass to page/update or block/appendChildren |
{{ $trigger.properties.Name.title[0].plain_text }} | string | Extract page title for notifications |
{{ $trigger.properties.Status.select.name }} | string | Read initial status for workflow routing |
{{ $trigger.created_time }} | string | Log or display the record creation time |
{{ $trigger.url }} | string | Include in notification messages as a direct link |
Node Policies & GuardRails
| Policy | Detail |
|---|---|
| Polling is not real-time | Minimum latency equals the polling interval. For latency-sensitive workflows, set the interval to 1 minute (the minimum). For non-urgent processing (e.g., end-of-day batch), use a longer interval to conserve API quota. |
| Each new page = one execution | The trigger fires one workflow execution per new page found in a single poll. If 10 new pages appear between polls, 10 executions start in parallel. Design downstream logic to handle parallel executions safely. |
| Cursor persistence | The trigger stores the last-seen page cursor between polls. If the workflow is restarted or redeployed, new pages created during the downtime will be detected on the first poll after restart. |
| Rate limit awareness | Each poll uses one API call. At 1-minute intervals, this is 60 calls/hour — well within limits for a single integration. At 30-second intervals with a large database, watch for rate limiting. |
| Credentials in Credentials Manager | Always use {{ $credentials.notionApiToken }} — never hard-code the token. |
Workflow Examples
Example 1 — New Support Ticket Routing
When a support request is added to the Notion support database, route it by priority to the appropriate Slack channel.
// Trigger: trigger/pageAdded (Support Requests DB)
// Step 1: IfCondition
// Condition: {{ $trigger.properties.Priority.select.name }} === "High"
// True: Slack #p1-support channel
// False: Slack #general-support channel
// Slack message:
{
"text": "New support ticket: {{ $trigger.properties.Name.title[0].plain_text }}\nEmail: {{ $trigger.properties.Email.email }}\n{{ $trigger.url }}"
}
Example 2 — New Employee Onboarding Kickoff
Trigger an onboarding workflow when HR adds a new employee record to the Notion HR database.
// Trigger: trigger/pageAdded (HR Employees DB)
// Step 1: user/getMany — build manager lookup map
// Step 2: EmailSmtp — welcome email to new employee
// Step 3: Jira issue/create — provision access request ticket
// Step 4: page/update — set Status to "Onboarding In Progress"
Example 3 — Notion-to-CRM Sync on New Record
Each new CRM contact added to Notion is synced to an external CRM system after deduplication.
// Trigger: trigger/pageAdded (Contacts DB)
// Step 1: HttpRequest — check if email already exists in CRM
// Step 2: IfCondition — exists in CRM?
// False: HttpRequest POST → create contact in CRM
// page/update → set NotionSynced = true
// True: log duplicate and stop