

How to Share Notion Meeting Notes to Slack with Pipedream
When a new page is created in a Notion database, Pipedream automatically posts the title, author, and a direct link to a designated Slack channel.
Steps and UI details are based on platform versions at time of writing — check each platform for the latest interface.
Best for
Engineering or ops teams that create meeting notes in a shared Notion database and need the rest of the team notified in Slack within minutes.
Not ideal for
Teams that create notes in personal Notion pages rather than a shared database — Pipedream can only poll databases, not arbitrary page trees.
Sync type
scheduledUse case type
notificationReal-World Example
A 20-person product team stores all meeting notes in a Notion database called 'Meeting Notes 2024.' Before this workflow, designers and engineers missed recaps because the note creator had to manually drop links in Slack. Now, within 15 minutes of a new page appearing in that database, Pipedream posts the title, creator name, and Notion URL to #product-updates automatically.
What Will This Cost?
Drag the slider to your expected monthly volume.
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
Import this workflow directly into Pipedream
Copy the pre-built Pipedream blueprint and paste it straight into Pipedream. 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.
Field Mapping
Map these fields between your apps.
| Field | API Name | |
|---|---|---|
| Required | ||
| Page Title | properties.Name.title[0].plain_text | |
| Page URL | url | |
| Created Time | created_time | |
| Database ID | parent.database_id | |
| Page ID | id | |
3 optional fields▸ show
| Created By | created_by.name |
| Meeting Type (custom property) | properties.MeetingType.select.name |
| Project / Team Tag (custom property) | properties.Team.multi_select[0].name |
Step-by-Step Setup
pipedream.com > Workflows > New Workflow
Create a new Pipedream workflow
Go to pipedream.com and sign in. Click 'New Workflow' in the top-right corner of the dashboard. You'll land on the workflow canvas with an empty trigger slot at the top. Give the workflow a name like 'Notion → Slack Meeting Notes' using the pencil icon next to the default title — this saves confusion when you have multiple workflows later.
- 1Click 'New Workflow' in the top-right
- 2Click the pencil icon next to the default workflow title
- 3Type 'Notion → Slack Meeting Notes' and press Enter
Workflow Canvas > Add a trigger > Notion > New Page in Database
Add the Notion 'New Page in Database' trigger
Click the 'Add a trigger' block on the canvas. Search for 'Notion' in the app search bar and select it. Choose the trigger called 'New Page in Database' — this polls your chosen Notion database every 15 minutes for newly created pages. You'll be prompted to connect your Notion account via Pipedream's Connected Accounts.
- 1Click 'Add a trigger'
- 2Type 'Notion' in the search bar and select the Notion app
- 3Select 'New Page in Database' from the trigger list
- 4Click 'Connect a new Notion account' and complete the OAuth flow
Trigger Config > Database ID dropdown
Select your Meeting Notes database
With Notion connected, a 'Database ID' dropdown appears in the trigger configuration panel. Click it to see the databases you granted access to. Select the database where meeting notes are created — for example, 'Meeting Notes 2024.' If you don't see it, your Notion OAuth grant didn't include that database. Set the polling interval to 15 minutes (the default) unless you need faster delivery, in which case 5 minutes is the minimum.
- 1Click the 'Database ID' dropdown
- 2Select your meeting notes database from the list
- 3Leave polling interval at 15 minutes or change to 5 minutes for faster delivery
- 4Click 'Save and continue'
Workflow Canvas > Trigger Step > Output panel (right side)
Inspect the trigger output
After generating a test event, click the trigger step to expand its output panel on the right. You'll see the raw Notion page object in JSON. Locate the fields you'll need: 'properties.Name.title[0].plain_text' for the page title, 'created_by.name' for the creator, and 'url' for the direct Notion link. These are the paths you'll reference in later steps. Take note of any custom properties in your database — meeting type, project tag, or assigned team — that you might want to include in the Slack message.
- 1Click on the trigger step block to expand the output
- 2Look for 'properties.Name.title[0].plain_text' in the JSON tree
- 3Look for 'created_by.name'
- 4Look for 'url'
Workflow Canvas > + Add Step > Run Node.js code
Add a Node.js code step to build the Slack message
Click the '+' button below the trigger to add a new step. Choose 'Run Node.js code' from the step type list. This step will extract the relevant fields from the Notion page object and format them into a clean Slack message. Using a code step here instead of going directly to the Slack action gives you control over the message format and lets you add conditional logic — for example, only notifying if the page has a specific tag or was created by a specific team.
- 1Click the '+' button below the trigger block
- 2Select 'Run Node.js code' from the step list
- 3Rename the step to 'Format Slack Message' using the step title field
Paste this into the 'Run Node.js code' step (step 5 on the canvas). It reads directly from the Notion trigger output at 'steps.trigger.event', formats a Block Kit message with a header, metadata section, and link button, and returns the blocks array for the Slack action to consume.
JavaScript — Code Stepexport default defineComponent({▸ Show code
export default defineComponent({
async run({ steps, $ }) {
// Pull fields from Notion trigger output... expand to see full code
export default defineComponent({
async run({ steps, $ }) {
// Pull fields from Notion trigger output
const page = steps.trigger.event;
// Safe title extraction with fallback
const title =
page?.properties?.Name?.title?.[0]?.plain_text ||
"Untitled Meeting Notes";
const createdBy = page?.created_by?.name || "Unknown";
const pageUrl = page?.url || "";
// Format the creation timestamp to something human-readable
const rawDate = page?.created_time;
const formattedDate = rawDate
? new Date(rawDate).toLocaleString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
timeZone: "America/New_York",
})
: "Unknown time";
// Optional: extract a custom 'MeetingType' select property if it exists
const meetingType =
page?.properties?.MeetingType?.select?.name || null;
const typeLabel = meetingType ? ` · ${meetingType}` : "";
// Build Slack Block Kit payload
const blocks = [
{
type: "header",
text: {
type: "plain_text",
text: `📝 ${title}`,
emoji: true,
},
},
{
type: "section",
text: {
type: "mrkdwn",
text: `*Posted by:* ${createdBy}${typeLabel}\n*Created:* ${formattedDate}`,
},
},
{
type: "actions",
elements: [
{
type: "button",
text: {
type: "plain_text",
text: "View Notes in Notion",
emoji: true,
},
url: pageUrl,
style: "primary",
},
],
},
{
type: "divider",
},
];
// Return blocks for the next Slack step to consume
return { blocks, title, createdBy, formattedDate, pageUrl };
},
});channel: {{channel}}
ts: {{ts}}
Workflow Canvas > Format Slack Message step > Code editor
Write the message formatting code
Paste the code from the Pro Tip section into the code editor, replacing the default content. This code reads from the Notion trigger output and builds a structured Slack Block Kit message with the page title, creator, creation time, and a link button. After pasting, click 'Test' to run the step against your test event and confirm the output object contains a formatted 'blocks' array ready for Slack.
- 1Select all default code in the editor and delete it
- 2Paste the Pro Tip code
- 3Click 'Test' in the step toolbar
- 4Expand the output panel and confirm 'blocks' is populated
Paste this into the 'Run Node.js code' step (step 5 on the canvas). It reads directly from the Notion trigger output at 'steps.trigger.event', formats a Block Kit message with a header, metadata section, and link button, and returns the blocks array for the Slack action to consume.
JavaScript — Code Stepexport default defineComponent({▸ Show code
export default defineComponent({
async run({ steps, $ }) {
// Pull fields from Notion trigger output... expand to see full code
export default defineComponent({
async run({ steps, $ }) {
// Pull fields from Notion trigger output
const page = steps.trigger.event;
// Safe title extraction with fallback
const title =
page?.properties?.Name?.title?.[0]?.plain_text ||
"Untitled Meeting Notes";
const createdBy = page?.created_by?.name || "Unknown";
const pageUrl = page?.url || "";
// Format the creation timestamp to something human-readable
const rawDate = page?.created_time;
const formattedDate = rawDate
? new Date(rawDate).toLocaleString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
timeZone: "America/New_York",
})
: "Unknown time";
// Optional: extract a custom 'MeetingType' select property if it exists
const meetingType =
page?.properties?.MeetingType?.select?.name || null;
const typeLabel = meetingType ? ` · ${meetingType}` : "";
// Build Slack Block Kit payload
const blocks = [
{
type: "header",
text: {
type: "plain_text",
text: `📝 ${title}`,
emoji: true,
},
},
{
type: "section",
text: {
type: "mrkdwn",
text: `*Posted by:* ${createdBy}${typeLabel}\n*Created:* ${formattedDate}`,
},
},
{
type: "actions",
elements: [
{
type: "button",
text: {
type: "plain_text",
text: "View Notes in Notion",
emoji: true,
},
url: pageUrl,
style: "primary",
},
],
},
{
type: "divider",
},
];
// Return blocks for the next Slack step to consume
return { blocks, title, createdBy, formattedDate, pageUrl };
},
});Workflow Canvas > + Add Step > Slack > Send Message to a Channel
Add the Slack 'Send Message' action
Click '+' below the code step and add a new step. Search for 'Slack' and select the action 'Send Message to a Channel.' Connect your Slack workspace via Connected Accounts — you'll need a Slack app with 'chat:write' scope or the standard Pipedream Slack OAuth app. In the 'Channel' field, type the exact channel name where meeting notes should be posted, such as '#product-updates'. For the message body, you'll pass the Block Kit blocks from the previous step.
- 1Click '+' below the code step
- 2Search 'Slack' and select 'Send Message to a Channel'
- 3Click 'Connect a new Slack account' and authorize via OAuth
- 4Set the 'Channel' field to your target channel name, e.g. '#product-updates'
- 5Set 'Blocks' to reference the code step output: '{{steps.Format_Slack_Message.$return_value.blocks}}'
Workflow Canvas > Test Workflow button (top toolbar)
Test the full workflow end-to-end
Click 'Test Workflow' at the top of the canvas. Pipedream will run the trigger's test event through every step in sequence. Watch each step turn green as it passes. Check your target Slack channel — you should see the formatted message appear within a few seconds. If any step shows a red error badge, click it to read the error message in the output panel.
- 1Click 'Test Workflow' in the top toolbar
- 2Watch each step block — they should turn green in sequence
- 3Open Slack and navigate to your target channel
- 4Confirm the meeting notes message appears with the correct title and link
Workflow Canvas > Settings (gear icon) > Error Handling
Add an error notification step
Add one more step after the Slack action: another Slack 'Send Message' action, but this time targeted at a private ops channel or your own DMs. Wrap the entire workflow's error path by clicking the 'Error' tab in the workflow settings — Pipedream lets you define a separate error workflow. Alternatively, add a try/catch in the code step so failures post a plain-text alert to a #workflow-errors channel instead of silently dying.
- 1Click the gear icon in the top-right of the workflow canvas
- 2Select 'Error Handling'
- 3Set 'On error, trigger workflow' to a separate error-notification workflow, or
- 4In the Node.js code step, wrap the main logic in a try/catch that calls $.send.http or a Slack message on failure
Workflow Canvas > Deploy button (top right)
Deploy and activate the workflow
Click 'Deploy' in the top-right of the canvas. Pipedream will activate the workflow and begin polling your Notion database on the schedule you set. The workflow status changes from 'Development' to 'Active' — you'll see this in your workflow list on the Pipedream dashboard. Create a test page in your Notion meeting notes database and wait up to 15 minutes (or 5 minutes if you set the shorter interval) for the Slack notification to appear.
- 1Click the 'Deploy' button in the top-right corner
- 2Confirm the modal asking you to deploy to production
- 3Navigate to pipedream.com > Workflows and confirm status shows 'Active'
- 4Create a new test page in your Notion database
- 5Wait up to 15 minutes and confirm the Slack message arrives
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
Use Pipedream for this if your team has a developer who can spend 20 minutes on it, or if you want to eventually add conditional routing logic without paying for a higher Make or Zapier tier. The Node.js code step is the real advantage here — building a Block Kit message with a fallback title, formatted timestamp, and optional meeting type label takes 10 lines of clean JavaScript. You can't do that cleanly in Zapier's Formatter or Make's text modules without ugly workarounds. The one scenario where you'd skip Pipedream: if nobody on your team codes and you just need a simple 'new Notion page → Slack message' with no custom formatting. In that case, Zapier gets you there in 8 minutes flat with no code.
Pipedream's free tier gives you 10,000 invocations per month. At a 15-minute polling interval, the trigger alone burns ~2,880 invocations per month just from polling — whether or not a new page exists. Add actual workflow runs on top: if your team creates 30 meeting notes per month, you're at ~2,910 total invocations. Well within the free tier. At 5-minute polling (paid plan), you're at ~8,640 polling invocations per month before counting actual runs — still under 10,000 if your team isn't prolific. Zapier charges per task: 30 notes/month = 30 tasks, which fits the free tier (100 tasks/month) easily but costs $19.99/month at the 750-task tier. Make's free tier gives 1,000 operations/month — each 3-step scenario costs 3 ops per run, so 30 notes = 90 ops. Make is cheapest at volume, but Pipedream is free for most teams at this use case's natural scale.
Make's biggest advantage here is its visual router module — you can branch to different Slack channels based on meeting type in a drag-and-drop interface without writing a single line of code. Zapier has a pre-built Notion trigger that's been stable for years and requires zero configuration beyond selecting the database. n8n lets you self-host, which matters if your meeting notes contain sensitive content you don't want passing through a third-party cloud. Power Automate connects natively to Teams rather than Slack, so it's wrong for this use case unless your company runs on Microsoft 365. Pipedream is still the right call here if you want the flexibility of code without the overhead of self-hosting — and the Block Kit formatting you get from the Node.js step makes the Slack message look genuinely useful, not like a raw data dump.
Two things you'll hit after setup. First, Notion's API occasionally returns pages where 'created_by.name' is an empty string rather than null — this happens for Notion automations or API-created pages, not human-created ones. Your code needs to handle that case or the Slack message shows 'Posted by: ' with nothing after it. Second, if your Notion database has a lot of properties, the trigger event payload can be large — Pipedream handles this fine, but if you ever add a 'content' property that stores the full meeting notes text, be aware that Notion returns page properties in the trigger but not the page body content. To get the actual note text, you need a separate Notion API call using the 'Retrieve block children' endpoint, which adds another step and another API call per run.
Ideas for what to build next
- →Route Notes to Different Channels by Team — Extend the code step to read a 'Team' multi-select property from the Notion page and map each value to a specific Slack channel. A product note goes to #product, an eng note goes to #engineering — same workflow, smarter routing.
- →Post a Weekly Digest Instead of Per-Note Alerts — Replace the 15-minute polling trigger with a scheduled trigger that runs every Monday at 9 AM. Query the Notion API in a code step to fetch all pages created in the past 7 days and bundle them into a single Slack message with a list of links.
- →Write Back a Slack Thread URL to Notion — The Slack 'Send Message' action returns the message timestamp and channel ID. Use a second Notion 'Update Page' action to write the Slack thread URL back to a property on the original Notion page — so anyone reading the notes can jump directly to the Slack discussion.
Related guides
How to Share Notion Meeting Notes to Slack with Power Automate
~15 min setup
How to Share Notion Meeting Notes to Slack with n8n
~20 min setup
How to Send Notion Meeting Notes to Slack with Zapier
~8 min setup
How to Share Notion Meeting Notes to Slack with Make
~12 min setup
How to Create Notion Tasks from Slack with Pipedream
~15 min setup
How to Create Notion Tasks from Slack with Power Automate
~15 min setup