Notion to Slack: Content Approvals Integration Guide
Integrating Notion with Slack replaces asynchronous bottleneck pings with an automated content approval pipeline. By coupling Notion database status updates with Slack interactive Block Kit notifications, editorial teams eliminate context switching, cut review cycles from days to minutes, and maintain a synchronous audit trail without leaving communication channels.
Explore: Databases & Spreadsheets · Team Communication
Comparison matrix
| Feature | Notion | Slack | Edge |
|---|---|---|---|
| Entry Pricing (Per User/Month) | $10 billed monthly ($8 billed annually) | $8.75 billed monthly ($7.25 billed annually) | Slack |
| API Rate Limits | 3 requests per second bottleneck | Tiered rate limits: Tier 1 (1 req/min) to Tier 4 (100+ req/min) | Slack |
| Authentication Protocol | Bearer Integration Token via Internal Integration | Bot User OAuth Token (xoxb-) with scoped permissions | Tie |
| Webhook Support | Native webhooks via developer portal or polling automations | Slack Events API with bi-directional interactive payloads | Slack |
| Interactive UI Elements | Static database properties and page comments | Dynamic Block Kit buttons, modals, and overflow menus | Slack |
| Document & Rich Text Storage | Hierarchical block-based relational docs and inline databases | Message threads with 90-day history cap on free tier | Notion |
| API Base URL | https://api.notion.com/v1 | https://slack.com/api | Tie |
| Pre-built Integrations | 300+ marketplace connectors | 2,600+ App Directory listings | Slack |
| Start free | Try Notion → | Try Slack → |
ROI metrics
Hours saved / mo
35
Notion / mo
$100
Slack / mo
$88
Break-even
1.9 wks
Annual savings
$18,650
Automating approvals across a 10-person team eliminates 35 monthly hours of manual tracking, generating over $18,000 in recovered capacity for an annual software investment of $2,250.
Step-by-step setup guide
1.Create Notion Internal Integration
Navigate to notion.so/my-integrations, click 'New integration', label it 'Content Approval Bot', and select the target workspace. Copy the generated Internal Integration Secret.
curl -X GET https://api.notion.com/v1/users/me \ -H "Authorization: Bearer secret_live_notion_api_token" \ -H "Notion-Version: 2022-06-28"
2.Configure Content Database Schema
In Notion, create a database named 'Editorial Pipeline'. Add properties: 'Title' (title), 'Author' (person), 'Status' (select: Draft, In Review, Approved, Rejected), and 'Slack_TS' (text). Share the database explicitly with the integration.
3.Provision Slack App with Incoming Webhooks and Scopes
Create an application at api.slack.com/apps. Under OAuth & Permissions, add 'chat:write' and 'incoming-webhook' bot scopes. Install the app to your workspace and extract the 'xoxb-' token and target channel ID (e.g., #content-reviews).
4.Dispatch Approval Card to Slack via Block Kit
When a Notion page status updates to 'In Review', trigger a POST request to Slack's chat.postMessage endpoint containing actionable review buttons referencing the Notion page ID.
curl -X POST https://slack.com/api/chat.postMessage \ -H "Authorization: Bearer xoxb-slack-bot-token" \ -H "Content-Type: application/json; charset=utf-8" \ -d '{"channel":"C0123456789","blocks":[{"type":"section","text":{"type":"mrkdwn","text":"*New Content Ready for Review:* <https://notion.so/p-123|Q3 Product Launch Brief>"}},{"type":"actions","block_id":"approval_actions","elements":[{"type":"button","text":{"type":"plain_text","text":"Approve"},"style":"primary","value":"approve_page_123"},{"type":"button","text":{"type":"plain_text","text":"Reject"},"style":"danger","value":"reject_page_123"}]}]}'5.Handle Slack Interaction and Update Notion Status
Set your Slack Interactive Request URL to your middleware listener. When an editor clicks 'Approve', parse the payload, extract the Notion Page ID, and update the Notion status property to 'Approved'.
curl -X PATCH https://api.notion.com/v1/pages/8a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d \ -H "Authorization: Bearer secret_live_notion_api_token" \ -H "Notion-Version: 2022-06-28" \ -H "Content-Type: application/json" \ -d '{"properties":{"Status":{"select":{"name":"Approved"}}}}'
Webhook payload example
POST https://api.yourdomain.com/webhooks/notion-approvals · event: page.created
{
"id": "evt_9b8a7c6d5e4f3a2b",
"event": "page.created",
"timestamp": 1698150400,
"data": {
"object": "page",
"id": "8a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"parent": {
"type": "database_id",
"database_id": "d3b07384-d113-40a2-9e28-1f6d338e55e8"
},
"url": "https://www.notion.so/Q3-Product-Launch-Brief-8a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d",
"properties": {
"Title": {
"title": [
{
"plain_text": "Q3 Product Launch Brief"
}
]
},
"Author": {
"people": [
{
"id": "usr_c9a1e0b2",
"name": "Sarah Chen",
"person": {
"email": "sarah@company.com"
}
}
]
},
"Status": {
"select": {
"id": "stat_in_review",
"name": "In Review",
"color": "yellow"
}
}
}
}
}Notion: pros & cons
- ✅ Unifies production drafts, metadata, and database statuses within a single document hierarchy
- ✅ Granular database properties allow detailed editorial stage tracking
- ✅ Flexible payload formatting handles text blocks, callouts, and inline media assets
- ⚠️ Strict 3 requests per second API rate limit triggers HTTP 429 during batch jobs
- ⚠️ Lacks native outbound webhooks without utilizing enterprise automations or external polling
Slack: pros & cons
- ✅ Interactive Block Kit allows direct approve/reject state changes directly inside messages
- ✅ Near-instant notification delivery minimizes approval pipeline idle time
- ✅ Comprehensive audit trails through channel history and thread responses
- ⚠️ Free tier limits searchable history to 90 days, truncating older approval logs
- ⚠️ Per-seat billing ($8.75/user/month) scales quickly across cross-functional marketing departments
FAQ
How do you handle Notion's 3 requests per second rate limit in this workflow?
Implement an exponential backoff retry mechanism (retrying on HTTP 429 responses with jitter) and decouple requests using a message queue like Redis BullMQ or AWS SQS to buffer outgoing API calls to Notion.
How do you verify incoming interactive requests from Slack?
Validate the `X-Slack-Signature` header on incoming requests using HMAC-SHA256 with your Slack Signing Secret, matching against the request timestamp (`X-Slack-Request-Timestamp`) and raw request body.
Can external freelance writers trigger Slack approval alerts without having Slack seats?
Yes. Freelancers edit documents directly in Notion. Once they update their database status property to 'In Review', your backend integration detects the change and dispatches the alert into internal Slack channels.
What happens if two editors click 'Approve' in Slack simultaneously?
Use a transactional locking pattern in your intermediate listener (e.g., Redis `SET NX`). Update the original Slack message via `chat.update` immediately on the first click to disable buttons and display which editor approved the asset.