This workflow corresponds to n8n.io template #11485 — we link there as the canonical source.
This workflow follows the HTTP Request → Notion recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "13859f9a-981b-471a-995f-a5c71ceca530",
"name": "Find Shared Holidays",
"type": "n8n-nodes-base.code",
"position": [
1824,
2144
],
"parameters": {
"jsCode": "// Get results from all loop iterations\nconst allItems = $('Filter Upcoming').all().map(i => i.json);\nconst dateMap = {};\n\n// 1. Group countries by Date\nfor (const item of allItems) {\n // Ensure strictly YYYY-MM-DD (remove time if present)\n // This ensures Notion treats it as \"All Day\"\n let dateStr = item.date;\n if (dateStr.includes('T')) {\n dateStr = dateStr.split('T')[0];\n }\n // Write back clean date\n item.date = dateStr;\n\n if (!dateMap[dateStr]) dateMap[dateStr] = [];\n \n // Avoid duplicates\n if (!dateMap[dateStr].includes(item.countryCode)) {\n dateMap[dateStr].push(item.countryCode);\n }\n}\n\n// 2. Add \"sharedWith\" info\nconst enrichedItems = allItems.map(item => {\n const dateStr = item.date;\n // Find countries sharing this date, excluding current one\n const shared = dateMap[dateStr].filter(c => c !== item.countryCode);\n \n // For Notion (String list)\n item.sharedWith = shared.length ? shared.join(', ') : '';\n \n // For Slack (Formatted message)\n item.sharedMsg = shared.length ? ` (Also in: ${shared.join(', ')})` : '';\n \n return { json: item };\n});\n\nreturn enrichedItems;"
},
"executeOnce": true,
"typeVersion": 2
},
{
"id": "81a9c2ce-55ae-4fd5-974b-e09b1a4f6a46",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1312,
1952
],
"parameters": {
"color": 7,
"width": 416,
"height": 352,
"content": "## 3. Fetch & Filter\nQueries the API for holidays and filters the results to keep only those falling within the \"lookahead\" window."
},
"typeVersion": 1
},
{
"id": "031d2784-7939-4353-8e44-34e91502c7e8",
"name": "Notify Slack",
"type": "n8n-nodes-base.slack",
"position": [
2256,
2144
],
"parameters": {
"text": "=\ud83d\udea2 *Team Alert:* \nNext {{ $json.countryCode }} Holiday: *{{ $json.name }}* is on {{ $json.date }}.{{ $json.sharedMsg }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": ""
},
"otherOptions": {}
},
"typeVersion": 2.1
},
{
"id": "6a40d30c-8be1-4ef5-a788-a7f0c9108f68",
"name": "Add to Notion",
"type": "n8n-nodes-base.notion",
"position": [
2032,
2144
],
"parameters": {
"options": {},
"resource": "databasePage",
"databaseId": {
"__rl": true,
"mode": "list",
"value": "2be13e5b-3669-80c7-a7de-c0b9f5c0748e",
"cachedResultUrl": "https://www.notion.so/2be13e5b366980c7a7dec0b9f5c0748e",
"cachedResultName": "nn"
},
"propertiesUi": {
"propertyValues": [
{
"key": "Name|title",
"title": "={{ $json.name }} ({{ $json.countryCode }})"
},
{
"key": "Date|date",
"date": "={{ $json.date }}"
},
{
"key": "Shared Countries|rich_text",
"textContent": "={{ $json.sharedWith }}"
}
]
}
},
"credentials": {
"notionApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "efc05b71-b31d-4d9e-b47f-da5d1bfdf93f",
"name": "Filter Upcoming",
"type": "n8n-nodes-base.code",
"position": [
1584,
2144
],
"parameters": {
"jsCode": "const daysAhead = $('Define Days to Lookahead').first().json.Days;\n\nconst items = $input.all();\nconst today = new Date();\nconst futureDate = new Date();\nfutureDate.setDate(today.getDate() + daysAhead);\n\nconst upcomingHolidays = items.filter(item => {\n const holidayDate = new Date(item.json.date);\n return holidayDate >= today && holidayDate <= futureDate;\n});\n\nreturn upcomingHolidays;"
},
"typeVersion": 2
},
{
"id": "b0280f18-8055-4564-934d-2b9b2d614545",
"name": "Get Public Holidays",
"type": "n8n-nodes-base.httpRequest",
"position": [
1376,
2144
],
"parameters": {
"url": "=https://date.nager.at/api/v3/publicholidays/{{ $json.year }}/{{ $json.countryCode }}",
"options": {}
},
"typeVersion": 4.1
},
{
"id": "d0a73365-b3a3-49c8-ac67-dc1f392476bb",
"name": "Define Days to Lookahead",
"type": "n8n-nodes-base.set",
"position": [
736,
2144
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "d6aaefad-0c24-4324-b4d4-9bb184cc7c61",
"name": "Days",
"type": "number",
"value": 50
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f21ada48-96e8-44c9-92c3-170c56e4a209",
"name": "Define Team Countries",
"type": "n8n-nodes-base.set",
"position": [
528,
2144
],
"parameters": {
"fields": {
"values": [
{
"name": "countries",
"type": "arrayValue",
"arrayValue": "['KR', 'MX', 'US']"
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "9b9bc13c-eea5-47e3-9262-725cb1698df2",
"name": "Weekly Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
288,
2144
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtDay": [
1
],
"triggerAtHour": 9
}
]
}
},
"typeVersion": 1.1
},
{
"id": "7ea579e1-b800-4315-8796-851528ca501b",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"disabled": true,
"position": [
1760,
1952
],
"parameters": {
"color": 7,
"width": 852,
"height": 350,
"content": "## 3. Compare & Sync\nAggregates all results to identify shared holidays, formats the date (YYYY-MM-DD), and updates Notion/Slack."
},
"typeVersion": 1
},
{
"id": "43375eb5-3ba6-44fa-833d-e1ccb206d49f",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"disabled": true,
"position": [
912,
1952
],
"parameters": {
"color": 7,
"width": 340,
"height": 360,
"content": "## 2. Query Preparation\nPrepares a list of `Country + Year` combinations (Current & Next Year) to ensure holidays aren't missed during year-end transitions."
},
"typeVersion": 1
},
{
"id": "186d23a6-fc63-4256-b006-b032829af4db",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"disabled": true,
"position": [
288,
2048
],
"parameters": {
"color": 7,
"width": 556,
"height": 264,
"content": "## 1. Schedule & Configuration\nThis section triggers the workflow every Monday and sets the configuration variables: the list of countries to track and the \"lookahead\" window (in days)."
},
"typeVersion": 1
},
{
"id": "8bcab344-0da5-4dd4-85ed-4e528ffcb58c",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"disabled": true,
"position": [
288,
1616
],
"parameters": {
"width": 546,
"height": 412,
"content": "## \ud83c\udf0d Global Holiday Sync\n\n## How it works\nThis workflow prevents scheduling conflicts by tracking distributed team holidays. It fetches public holidays from the **Nager.Date API** for your specific regions (e.g., KR, US), filters for upcoming dates, and calculates if a holiday is **shared** across countries. Finally, it syncs the schedule to **Notion** and **Slack**.\n\n## Setup steps\n1. **Define Countries:** Update 'Define Team Countries' with 2-letter codes.\n2. **Set Range:** In 'Define Days to Lookahead', set the forecast window (e.g., 50 days).\n3. **Notion:** Create a DB with properties: `Name` (Title), `Date` (Date), and `Shared Countries` (Text).\n4. **Credentials:** Map your Notion Database and Slack Channel in the final nodes."
},
"typeVersion": 1
},
{
"id": "3ab566e8-b1f1-415a-a981-2b8013a8e184",
"name": "Prepare Queries",
"type": "n8n-nodes-base.code",
"position": [
928,
2144
],
"parameters": {
"jsCode": "const countries = $('Define Team Countries').first().json.countries;\nconst currentYear = new Date().getFullYear();\nconst nextYear = currentYear + 1;\n\nconst results = [];\n\n// Loop through each country and add both years\nfor (const code of countries) {\n // Add Current Year\n results.push({\n json: {\n countryCode: code,\n year: currentYear\n }\n });\n \n // Add Next Year\n results.push({\n json: {\n countryCode: code,\n year: nextYear\n }\n });\n}\n\nreturn results;"
},
"typeVersion": 2
}
],
"connections": {
"Add to Notion": {
"main": [
[
{
"node": "Notify Slack",
"type": "main",
"index": 0
}
]
]
},
"Filter Upcoming": {
"main": [
[
{
"node": "Find Shared Holidays",
"type": "main",
"index": 0
}
]
]
},
"Prepare Queries": {
"main": [
[
{
"node": "Get Public Holidays",
"type": "main",
"index": 0
}
]
]
},
"Weekly Schedule": {
"main": [
[
{
"node": "Define Team Countries",
"type": "main",
"index": 0
}
]
]
},
"Get Public Holidays": {
"main": [
[
{
"node": "Filter Upcoming",
"type": "main",
"index": 0
}
]
]
},
"Find Shared Holidays": {
"main": [
[
{
"node": "Add to Notion",
"type": "main",
"index": 0
}
]
]
},
"Define Team Countries": {
"main": [
[
{
"node": "Define Days to Lookahead",
"type": "main",
"index": 0
}
]
]
},
"Define Days to Lookahead": {
"main": [
[
{
"node": "Prepare Queries",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
notionApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template is essential for Remote Operations Managers, HR Teams, and Project Leads managing distributed teams across different countries. It prevents scheduling conflicts by automatically flagging when a regional team is out of office and identifying when multiple teams are…
Source: https://n8n.io/workflows/11485/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow is designed for engineering teams, project managers, and IT operations who need consistent visibility into team availability across multiple projects. It’s perfect for organizations that
This workflow is an automated system that tracks End-of-Life (EOL) dates for software and technologies used across your projects. It eliminates the need to manually monitor EOL dates in spreadsheets o
This workflow continuously monitors the Meta Ads Library for new creatives from a specific competitor pages, logs them into Google Sheets, and sends a concise Telegram notification with the number of
Enhance financial oversight with this automated n8n workflow. Triggered every 5 minutes, it fetches real-time bank transactions via an API, enriches and transforms the data, and applies smart logic to
This workflow automates competitive price intelligence using Bright Data's enterprise web scraping API. On a scheduled basis (default: daily at 9 AM), the system loops through configured competitor pr