Intermediate~20 min setupCommunication & ProductivityVerified April 2026
Slack logo
Notion logo

How to Share Notion Meeting Notes to Slack with n8n

Polls a Notion database for newly created meeting note pages and automatically posts a formatted message with the page title, date, and link to the correct Slack channel.

Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.

Best for

Teams who store meeting notes in a Notion database and need automatic Slack distribution without manually copying links each time.

Not ideal for

Teams who create notes in Notion pages outside a database — this workflow requires a structured Notion database to poll for new entries.

Sync type

scheduled

Use case type

notification

Real-World Example

💡

A 20-person product team at a B2B SaaS company runs daily standups, sprint reviews, and customer calls — all documented in a shared Notion database. Before this workflow, the note-taker had to manually paste the Notion link into #product-team or #engineering after every meeting, which got skipped 30-40% of the time. Now n8n polls the database every 5 minutes, detects new pages, and posts a structured Slack message to the right channel based on a 'Team' property in Notion — no manual sharing needed.

What Will This Cost?

Drag the slider to your expected monthly volume.

/mo
505005K50K

Each platform counts differently — Zapier: 1 task per trigger. Make: 1 operation per module per record. n8n: 1 execution per run.

Prices shown for annual billing. Based on published pricing as of April 2026.

Estimated ROI

1000

min saved/mo

$583

labor value/mo

Free

no platform cost

Based on ~2 min manual effort per operation at $35/hr fully loaded labor cost.

Implementation

Skip the setup

Import this workflow directly into n8n

Copy the pre-built n8n blueprint and paste it straight into n8n. All modules, filters, and field mappings are already configured — you just need to connect your accounts.

Before You Start

Make sure you have everything ready.

Notion account with a database set up for meeting notes (not just loose pages)
Notion Internal Integration Token with 'Read content' capability enabled
Slack workspace admin access to create and install a custom Slack app
Slack bot token (xoxb-) with chat:write and channels:read scopes
n8n instance running (cloud at n8n.cloud or self-hosted) with access to the Credentials and Workflows sections

Field Mapping

Map these fields between your apps.

FieldAPI Name
Required
Page Titleproperties.Name.title[0].plain_text
Page URLurl
Created Timecreated_time
5 optional fields▸ show
Created Bycreated_by.name
Teamproperties.Team.select.name
Meeting Dateproperties.Meeting Date.date.start
Attendeesproperties.Attendees.multi_select
Summaryproperties.Summary.rich_text[0].plain_text

Step-by-Step Setup

1

notion.so/my-integrations > + New integration > Capabilities

Create a Notion integration and share your database

Go to notion.so/my-integrations and click '+ New integration'. Name it something like 'n8n Meeting Notes', set the associated workspace, and copy the Internal Integration Token — you'll need it in n8n. Back in Notion, open the database you use for meeting notes, click the '...' menu in the top-right, scroll to 'Connections', and add the integration you just created. Without this step, n8n cannot read any pages in that database.

  1. 1Go to notion.so/my-integrations and click '+ New integration'
  2. 2Name the integration 'n8n Meeting Notes' and select your workspace
  3. 3Under Capabilities, enable 'Read content'
  4. 4Copy the Internal Integration Token
  5. 5Open your Notion meeting notes database, click '...' > Connections > add your new integration
What you should see: Your integration appears under Connections in the Notion database menu. The token is copied to your clipboard.
Common mistake — Notion integrations are scoped per-database. If your meeting notes live in multiple databases, you must share each one individually with the integration — there is no workspace-wide read permission.
2

api.slack.com/apps > Create New App > OAuth & Permissions > Scopes

Create a Slack app and get a bot token

Go to api.slack.com/apps and click 'Create New App', choose 'From scratch', name it 'Meeting Notes Bot', and select your workspace. Under 'OAuth & Permissions', add the bot scopes: chat:write and channels:read. Install the app to your workspace and copy the Bot User OAuth Token (starts with xoxb-). You'll also need to invite the bot to any Slack channel it should post in.

  1. 1Go to api.slack.com/apps and click 'Create New App' > 'From scratch'
  2. 2Name the app 'Meeting Notes Bot' and select your Slack workspace
  3. 3Navigate to OAuth & Permissions > Bot Token Scopes
  4. 4Add scopes: chat:write, channels:read
  5. 5Click 'Install to Workspace', authorize, and copy the Bot User OAuth Token
What you should see: You have an xoxb- token copied. The bot appears in your Slack workspace under Apps.
Common mistake — The bot cannot post to private channels unless you explicitly invite it with /invite @Meeting Notes Bot inside that channel — adding the scope alone is not enough.
3

n8n > Settings > Credentials > + Add Credential

Set up credentials in n8n

In n8n, go to Settings > Credentials and create two credentials. First, click '+ Add Credential', search for 'Notion API', select it, and paste your Internal Integration Token. Second, create another credential, search for 'Slack API', and paste your xoxb- Bot User OAuth Token. Name both clearly — 'Notion – Meeting Notes' and 'Slack – Meeting Notes Bot' — so you can identify them later.

  1. 1Open n8n and click Settings in the left sidebar
  2. 2Click Credentials > + Add Credential
  3. 3Search 'Notion API', select it, paste your Internal Integration Token, click Save
  4. 4Click + Add Credential again, search 'Slack API', paste your xoxb- token, click Save
What you should see: Both credentials appear in your credentials list with a green checkmark confirming they authenticated successfully.
4

n8n > Workflows > + New Workflow > + Add Node > Schedule Trigger

Create a new workflow and add the Schedule trigger

In n8n, click '+ New Workflow'. Click the canvas to add your first node and search for 'Schedule Trigger'. Set the interval to every 5 minutes. This node fires your workflow on a timer — since Notion's API doesn't support real-time webhooks for database page creation, polling is the only approach. Five minutes is a reasonable balance between freshness and API rate limits.

  1. 1Click '+ New Workflow' from the n8n home screen
  2. 2Click the '+' node on the canvas and search for 'Schedule Trigger'
  3. 3Set 'Trigger Interval' to Every 5 Minutes
  4. 4Click the node header and rename it to 'Poll Every 5 Min'
  5. 5Click Save
What you should see: The Schedule Trigger node appears on the canvas showing '5 minutes' as the interval.
Common mistake — Notion's API has a rate limit of 3 requests per second per integration. At 5-minute intervals this workflow is well within limits, but if you duplicate this workflow for multiple databases, space the intervals out by at least 30 seconds.
n8n
+
click +
search apps
Slack
SL
Slack
Create a new workflow and ad…
Slack
SL
module added
5

Canvas > + Add Node > Notion > Database Page > Get Many

Add a Notion node to query the database

Add a new node after the Schedule Trigger and search for 'Notion'. Select the 'Get Many' operation under 'Database Page'. Connect it to your 'Notion – Meeting Notes' credential and enter your database ID (the 32-character string from your Notion database URL). Add a filter: set 'Created Time' is on or after a dynamic value. You'll set the exact dynamic timestamp in the next step — for now, confirm the node connects and returns results when you test it.

  1. 1Click '+' after the Schedule Trigger node and search 'Notion'
  2. 2Under Resource, select 'Database Page'; under Operation, select 'Get Many'
  3. 3Select your 'Notion – Meeting Notes' credential
  4. 4Paste your Notion database ID into the Database ID field
  5. 5Click 'Test step' to confirm the node returns pages
What you should see: The Notion node returns a list of pages from your meeting notes database in the output panel on the right.
Common mistake — Your Notion database ID is the 32-character string in the URL — not the page title. It looks like: 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d. If you copied the full URL including the workspace slug, strip everything except that ID.
6

Canvas > + Add Node > Code

Add a Code node to filter only new pages

Since n8n's Notion node doesn't have a native 'last run time' filter, you need a Code node to compare each page's created_time against the last execution time. Add a Code node after the Notion node. Paste the JavaScript below (see pro_tip_code). This code reads a static workflow variable for the last-run timestamp, filters pages created after that time, updates the variable, and passes only new pages downstream. Without this, every poll would re-send every page in the database.

  1. 1Click '+' after the Notion node and search 'Code'
  2. 2Select the Code node and set Mode to 'Run Once for All Items'
  3. 3Paste the full JavaScript from the Pro Tip section into the code editor
  4. 4Click 'Test step' — if no new pages exist, the output should show 0 items
What you should see: The Code node outputs only pages created since the last workflow run. On the first run it uses a 5-minute lookback window as a fallback.
Common mistake — The static workflow variables approach used here (using $workflow.staticData) persists between executions only when the workflow is active. If you test with the workflow inactive, staticData resets each run and you may get duplicates. Activate the workflow before running it in production.

This Code node runs after the Notion 'Get Many' node and does three things: reads the last-run timestamp from n8n's persistent staticData, filters the Notion pages to only those created after that timestamp, and updates the stored timestamp for the next run. Paste this into a Code node set to 'Run Once for All Items', placed between the Notion node and the IF node.

JavaScript — Code Node// Code node: filter Notion pages to only new ones since last run
▸ Show code
// Code node: filter Notion pages to only new ones since last run
// Mode: Run Once for All Items
const items = $input.all();

... expand to see full code

// Code node: filter Notion pages to only new ones since last run
// Mode: Run Once for All Items

const items = $input.all();

// Get persistent storage for this workflow
const staticData = $getWorkflowStaticData('global');

// Use stored lastRun time, or fall back to 6 minutes ago on first run
// 6 min covers the 5-min poll interval with buffer for clock drift
const lastRun = staticData.lastNotionPollTime
  ? new Date(staticData.lastNotionPollTime)
  : new Date(Date.now() - 6 * 60 * 1000);

console.log(`Filtering pages created after: ${lastRun.toISOString()}`);

// Filter only pages created since last poll
const newPages = items.filter(item => {
  const createdAt = new Date(item.json.created_time);
  return createdAt > lastRun;
});

console.log(`Found ${newPages.length} new page(s) out of ${items.length} total`);

// Update the stored timestamp to now before returning
// This ensures the next run only sees pages created after this moment
staticData.lastNotionPollTime = new Date().toISOString();

// If no new pages, return empty array — downstream nodes won't fire
if (newPages.length === 0) {
  return [];
}

// Return new pages with a cleaned-up display date added
return newPages.map(item => {
  const rawDate = item.json.created_time;
  const displayDate = new Date(rawDate).toLocaleDateString('en-US', {
    weekday: 'short',
    month: 'short',
    day: 'numeric',
    year: 'numeric'
  });

  return {
    json: {
      ...item.json,
      display_date: displayDate,
      page_title: item.json.properties?.Name?.title?.[0]?.plain_text ?? 'Untitled',
      team: item.json.properties?.Team?.select?.name ?? 'General',
      summary: item.json.properties?.Summary?.rich_text?.[0]?.plain_text ?? ''
    }
  };
});
Slack
SL
trigger
filter
Condition
= "New"
yes — passes through
no — skipped
Notion
NO
notified
7

Canvas > + Add Node > IF

Add an IF node to route by team or meeting type

If your Notion database has a 'Team' or 'Category' property, add an IF node to route notes to different Slack channels. Add the IF node after the Code node. Set Condition 1: the Notion property 'Team' equals 'Engineering' — this branch posts to #engineering. The false branch handles all other teams and posts to a general #meeting-notes channel. You can chain multiple IF nodes for more teams.

  1. 1Click '+' after the Code node and search 'IF'
  2. 2Set Value 1 to the Notion 'Team' property using the expression: {{ $json.properties.Team.select.name }}
  3. 3Set Condition to 'equals'
  4. 4Set Value 2 to 'Engineering'
  5. 5Connect the True output to an Engineering Slack node; connect False to a general Slack node
What you should see: The IF node shows two output branches: True (Engineering) and False (everyone else). Test data routes correctly based on the Team property value.
8

Canvas > + Add Node > Slack > Message > Send

Add Slack nodes to post the message

Add a Slack node on each IF branch. Select Resource: Message, Operation: Send. Connect your 'Slack – Meeting Notes Bot' credential. Set the Channel to the appropriate channel ID (e.g. C04XXXXXXX — use the channel's ID, not its name, to avoid breakage if someone renames the channel). In the Text field, build your message using Notion data: include the page title, creator name, created date, and the Notion URL. Use Block Kit for a cleaner layout if your team prefers it.

  1. 1Click '+' on the True branch output and search 'Slack'
  2. 2Set Resource to 'Message', Operation to 'Send'
  3. 3Select your 'Slack – Meeting Notes Bot' credential
  4. 4Set Channel to the Slack channel ID (right-click channel in Slack > Copy link to extract ID)
  5. 5Set Text to: 📝 New meeting notes: *{{ $json.properties.Name.title[0].plain_text }}* 🔗 {{ $json.url }} 👤 {{ $json.created_by.name }} 🗓 {{ $json.created_time }}
What you should see: When you click 'Test step', a message appears in your Slack channel with the note title, link, author, and date.
Common mistake — Using a channel name (like #engineering) instead of a channel ID will silently fail if the channel is ever renamed. Always use the channel ID — it starts with C0 and never changes.
message template
🔔 New Record: {{text}} {{user}}
channel: {{channel}}
ts: {{ts}}
#sales
🔔 New Record: Jane Smith
Company: Acme Corp
9

Slack Node > Settings > Continue on Fail > Error Output > + Add Node

Add error handling with a fallback node

In n8n, click the Slack node, go to Settings, and enable 'Continue on Fail'. Then add an Error Trigger workflow or connect an email/Slack fallback node to catch failures. A simple approach: add a second Slack node connected to the error output of your main Slack node that posts to a #n8n-alerts channel. This ensures you know when a note fails to distribute — otherwise failures are silent.

  1. 1Click your Slack node, then click Settings in the node panel
  2. 2Toggle 'Continue on Fail' to ON
  3. 3Hover over the Slack node — you'll see a red error output handle appear
  4. 4Connect a second Slack node to that error handle
  5. 5Set it to post to #n8n-alerts with text: '⚠️ Meeting notes distribution failed for: {{ $json.error.message }}'
What you should see: Your workflow now has a visible error path. If Slack rejects a message, the error node fires instead of the workflow silently stopping.
10

n8n > Workflow Editor > Active toggle (top right) > Executions tab

Activate the workflow and verify the first live run

Click 'Save' in the top-right, then toggle the workflow from Inactive to Active using the toggle in the top-right corner. Wait 5 minutes (or create a new test page in your Notion database). Go to the Executions tab in n8n and watch for a new execution row to appear. Click into it to confirm the Notion node returned your test page, the Code node passed it through, and the Slack node shows a success status.

  1. 1Click Save in the top-right of the workflow editor
  2. 2Toggle the workflow status from Inactive to Active
  3. 3Create a new page in your Notion meeting notes database
  4. 4Wait up to 5 minutes for the next poll to fire
  5. 5Click the Executions tab and open the latest execution to inspect each node's output
What you should see: The Executions tab shows a green success row. The Slack node output shows status: ok and the message appears in your Slack channel.
Common mistake — If you activate the workflow and immediately check executions, you may see 0 items from the Code node — that's correct if no new pages were created in the last 5 minutes. Create a test page first, then wait for the next poll cycle.
n8n
▶ Run once
executed
Slack
Notion
Notion
🔔 notification
received

Going live

Production Checklist

Before you turn this on for real, confirm each item.

Troubleshooting

Common errors and how to fix them.

Frequently Asked Questions

Common questions about this workflow.

Analysis

VerdictWhy n8n for this workflow

Use n8n for this if your team self-hosts or has privacy requirements that make cloud automation tools a non-starter. Notion and Slack both handle auth over standard OAuth and API tokens — n8n handles both without exposing your tokens to a third-party platform. The second reason to pick n8n here is the Code node: the deduplication logic this workflow requires (tracking last-run timestamps with staticData) is trivial in JavaScript but painful to hack together in Zapier's Formatter or Make's flow control. One scenario where you'd skip n8n: if nobody on your team has any comfort with JSON or reading node output panels, Make is faster to configure for this exact workflow.

Cost

Cost math: this workflow executes once every 5 minutes. That's 288 executions per day, roughly 8,640 per month. On n8n cloud's Starter plan ($20/month), you get 2,500 executions — you'll hit the limit in under 9 days. You need the Pro plan at $50/month for 10,000 executions, which covers you with margin. Self-hosted n8n is free with no execution limits, just your server cost. Compare that to Zapier: at 288 zaps/day this workflow burns through the free tier in 4 days, and the Team plan ($69/month) gives you 2,000 tasks — not enough either. Make's Core plan ($10.59/month) includes 10,000 operations and would handle this easily at around 1,700 operations per month (6 ops per execution × 288 runs). Make is cheaper by $39/month on cloud. Self-hosted n8n is cheaper than everything.

Tradeoffs

Zapier has no native Notion trigger for 'new database page' — it polls too, but the minimum interval on paid plans is 1 minute and the Notion integration lags. Make has a cleaner Notion module with built-in filter support that avoids needing a custom deduplication script. Power Automate has no official Notion connector — you'd be using HTTP actions throughout, which means building every Notion API call manually. Pipedream has a Notion 'New Page in Database' source that wraps the polling in a managed event source, reducing the code you write yourself. n8n is still the right call if you're self-hosting (cost) or if you want the deduplication and channel-routing logic living in one visible, version-controllable workflow file rather than spread across a SaaS platform's UI.

Three things you'll hit after setup. First, Notion's created_by.name field returns the integration name (e.g. 'n8n Meeting Notes'), not a human name, for pages created via API. For pages created by real users in the Notion UI it works fine — but if anyone creates notes programmatically, the author field will look wrong. Second, if your Notion database has a title column named anything other than 'Name', the path properties.Name.title[0].plain_text returns undefined and your Slack message shows nothing. Check the exact property name in the raw node output and update the Code node accordingly. Third, Slack's chat.postMessage API silently succeeds (returns HTTP 200) even when the bot is not in the channel — it just doesn't show the message. Always verify delivery by checking the ts timestamp in the Slack node output, not just the HTTP status code.

Ideas for what to build next

  • Add a daily digest instead of per-note alertsChange the Schedule Trigger to run once at 5pm, collect all notes created that day, and post a single bulleted Slack digest. This reduces noise for teams with 10+ meetings per day.
  • Post a Slack thread summary using the Notion page bodyUse the Notion 'Get Block Children' operation to pull the actual content of the page and post it as a Slack thread reply under the main notification — so teammates can read the key points without opening Notion.
  • Tag relevant Slack users based on the Notion Attendees propertyMap the Notion Attendees multi-select or people property to Slack user IDs using a lookup table in a Code node, then include @mentions in the Slack message so the right people are notified directly.

Related guides

Was this guide helpful?
Slack + Notion overviewn8n profile →