AutomationFlowsSlack & Telegram › Automated Asteroid Alerts with Nasa Api, Slack & Google Calendar

Automated Asteroid Alerts with Nasa Api, Slack & Google Calendar

ByYusuke Yamamoto @yusuke-yamamoto on n8n.io

This n8n template creates an automated alert system that checks NASA's data for near-Earth asteroids twice a day. When it finds asteroids meeting specific criteria, it sends a summary alert to Slack and creates individual events in Google Calendar for each object. Automated…

Cron / scheduled trigger★★★★☆ complexity16 nodesSlackNasaGoogle Calendar
Slack & Telegram Trigger: Cron / scheduled Nodes: 16 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #9877 — we link there as the canonical source.

This workflow follows the Google Calendar → Slack 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 →

Download .json
{
  "id": "qxBmyFKAUjkuc2Wx",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "NASA Near-Earth Asteroid Alert System",
  "tags": [],
  "nodes": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        224,
        304
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 12
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "note1a2b3c4d-5678-90ab-cdef-1234567890ab",
      "name": "Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        16
      ],
      "parameters": {
        "color": 5,
        "width": 300,
        "height": 264,
        "content": "## NASA Asteroid Alert Workflow\n\nThis workflow automatically checks for near-Earth asteroids twice daily using NASA's API and sends alerts to Slack and Google Calendar.\n\n**Process:**\n1. Runs on a 12-hour schedule.\n2. Fetches asteroid data for the next 14 days.\n3. Filters for significant objects.\n4. Notifies via Slack & creates Calendar events."
      },
      "typeVersion": 1
    },
    {
      "id": "b2c3d4e5-f678-90ab-cdef-234567890abc",
      "name": "Calculate Date Range",
      "type": "n8n-nodes-base.code",
      "position": [
        464,
        304
      ],
      "parameters": {
        "jsCode": "// Calculate date range for API request\nconst today = new Date();\nconst nextWeek = new Date();\nnextWeek.setDate(today.getDate() + 14);\n\n// Format dates as YYYY-MM-DD\nconst formatDate = (date) => {\n  const year = date.getFullYear();\n  const month = String(date.getMonth() + 1).padStart(2, '0');\n  const day = String(date.getDate()).padStart(2, '0');\n  return `${year}-${month}-${day}`;\n};\n\nreturn [{\n  json: {\n    start_date: formatDate(today),\n    end_date: formatDate(nextWeek),\n    today: formatDate(today),\n    next_week: formatDate(nextWeek)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "note2b3c4d5e-6789-0abc-def1-234567890abc",
      "name": "API Key Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        16
      ],
      "parameters": {
        "color": 6,
        "width": 280,
        "height": 260,
        "content": "## \u2699\ufe0f NASA API Configuration\n\n**Action Required:** Replace the default `DEMO_KEY` with your own NASA API key in the 'Get an asteroid neo feed' node.\n\n1. **Get a free key at:** [api.nasa.gov](https://api.nasa.gov/)\n2. **Why?** The demo key has very strict rate limits and is not suitable for regular use."
      },
      "typeVersion": 1
    },
    {
      "id": "d4e5f678-90ab-cdef-1234-567890abcdef",
      "name": "Filter and Process Asteroids",
      "type": "n8n-nodes-base.code",
      "position": [
        992,
        304
      ],
      "parameters": {
        "jsCode": "// Get all individual asteroid items from the input\nconst allAsteroidItems = $input.all();\n\n// Configuration thresholds (\u30c6\u30b9\u30c8\u7528\u306e\u7de9\u3044\u5024)\nconst MAX_DISTANCE_KM = 75000000000; // 75 billion km\nconst MIN_DIAMETER_METERS = 1;       // 1 meter\n\nconst filteredAsteroids = [];\n\n// Loop through each asteroid item that was passed to this node\nfor (const item of allAsteroidItems) {\n  const asteroid = item.json; // Get the actual asteroid data from the item\n\n  // Ensure the necessary data exists before trying to process it\n  if (asteroid && asteroid.close_approach_data && asteroid.close_approach_data.length > 0) {\n    const missDistance = parseFloat(asteroid.close_approach_data[0].miss_distance.kilometers);\n    const maxDiameter = asteroid.estimated_diameter.meters.estimated_diameter_max;\n    const minDiameter = asteroid.estimated_diameter.meters.estimated_diameter_min;\n    const avgDiameter = (maxDiameter + minDiameter) / 2;\n\n    // Apply filters\n    if (missDistance <= MAX_DISTANCE_KM && avgDiameter >= MIN_DIAMETER_METERS) {\n      filteredAsteroids.push({\n        name: asteroid.name,\n        id: asteroid.id,\n        approach_date: asteroid.close_approach_data[0].close_approach_date,\n        approach_date_full: asteroid.close_approach_data[0].close_approach_date_full,\n        miss_distance_km: Math.round(missDistance),\n        miss_distance_lunar: parseFloat(asteroid.close_approach_data[0].miss_distance.lunar).toFixed(2),\n        diameter_min_m: Math.round(minDiameter),\n        diameter_max_m: Math.round(maxDiameter),\n        diameter_avg_m: Math.round(avgDiameter),\n        velocity_km_h: Math.round(parseFloat(asteroid.close_approach_data[0].relative_velocity.kilometers_per_hour)),\n        is_potentially_hazardous: asteroid.is_potentially_hazardous_asteroid,\n        nasa_jpl_url: asteroid.nasa_jpl_url,\n        absolute_magnitude: asteroid.absolute_magnitude_h\n      });\n    }\n  }\n}\n\n// Sort by closest approach distance\nfilteredAsteroids.sort((a, b) => a.miss_distance_km - b.miss_distance_km);\n\n// Return the final list of asteroids that met the criteria\nreturn filteredAsteroids.map(asteroid => ({ json: asteroid }));"
      },
      "typeVersion": 2
    },
    {
      "id": "note3c4d5e6f-7890-abcd-ef12-34567890abcd",
      "name": "Filter Settings",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -16
      ],
      "parameters": {
        "color": 3,
        "width": 280,
        "height": 280,
        "content": "## \u2699\ufe0f Filtering Criteria\n\nThis node filters asteroids to find only significant ones. **You should adjust these values.**\n\n**Default (Test) Values:**\n- `MAX_DISTANCE_KM = 75000000000` (very far)\n- `MIN_DIAMETER_METERS = 1` (very small)\n\n**Recommended Values:**\n- `MAX_DISTANCE_KM = 7500000` (7.5 million km)\n- `MIN_DIAMETER_METERS = 100` (100 meters)\n\n**Action:** Edit the code in this node to customize your alert sensitivity."
      },
      "typeVersion": 1
    },
    {
      "id": "e5f67890-abcd-ef12-3456-7890abcdef12",
      "name": "Check If Asteroids Found",
      "type": "n8n-nodes-base.if",
      "position": [
        1376,
        304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567891",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $items().length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "f6789012-3456-7890-abcd-ef1234567890",
      "name": "Format Alert Messages",
      "type": "n8n-nodes-base.code",
      "position": [
        1648,
        192
      ],
      "parameters": {
        "jsCode": "// Format message for Slack/Email\nconst asteroids = $input.all();\nconst messageLines = [];\n\nmessageLines.push('\ud83d\udea8 *NEAR-EARTH ASTEROID ALERT* \ud83d\udea8');\nmessageLines.push('');\nmessageLines.push(`Found ${asteroids.length} asteroid(s) meeting alert criteria:`);\nmessageLines.push('');\n\nasteroids.forEach((item, index) => {\n  const asteroid = item.json;\n  const hazardIcon = asteroid.is_potentially_hazardous ? '\u26a0\ufe0f' : '\u2713';\n  \n  messageLines.push(`*${index + 1}. ${asteroid.name}* ${hazardIcon}`);\n  messageLines.push(`   \u2022 Approach Date: ${asteroid.approach_date}`);\n  messageLines.push(`   \u2022 Distance: ${asteroid.miss_distance_km.toLocaleString()} km (${asteroid.miss_distance_lunar} lunar distances)`);\n  messageLines.push(`   \u2022 Size: ${asteroid.diameter_min_m}-${asteroid.diameter_max_m} meters`);\n  messageLines.push(`   \u2022 Speed: ${asteroid.velocity_km_h.toLocaleString()} km/h`);\n  messageLines.push(`   \u2022 Details: ${asteroid.nasa_jpl_url}`);\n  messageLines.push('');\n});\n\nmessageLines.push('_Data source: NASA Near Earth Object Web Service_');\n\nreturn [{\n  json: {\n    slackMessage: messageLines.join('\\n'),\n    emailSubject: `\ud83d\udea8 Asteroid Alert: ${asteroids.length} Near-Earth Object(s) Detected`,\n    emailBody: messageLines.join('\\n').replace(/\\*/g, '').replace(/_/g, ''),\n    asteroidCount: asteroids.length,\n    asteroids: asteroids.map(a => a.json)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "78901234-5678-90ab-cdef-123456789012",
      "name": "Send Slack Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        1840,
        64
      ],
      "parameters": {
        "text": "={{ $json.slackMessage }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09KTEYDKDY",
          "cachedResultName": "\u30b5\u30dd\u30fc\u30c8\u30c1\u30fc\u30e0"
        },
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "note4d5e6f78-90ab-cdef-1234-567890abcdef",
      "name": "Slack Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1504,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 280,
        "height": 244,
        "content": "## \u2699\ufe0f Slack Configuration\n\n**Setup Required:**\n1. Select the 'Send Slack Alert' node.\n2. Add your Slack OAuth2 credentials.\n3. Choose the channel for alerts (e.g., `#asteroid-alerts`).\n\nEnsure the n8n app has permission to post in the selected channel."
      },
      "typeVersion": 1
    },
    {
      "id": "90123456-7890-abcd-ef12-345678901234",
      "name": "Split Out Individual Asteroids",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1840,
        304
      ],
      "parameters": {
        "include": "selectedOtherFields",
        "options": {},
        "fieldToSplitOut": "asteroids",
        "fieldsToInclude": "emailSubject, slackMessage"
      },
      "typeVersion": 1
    },
    {
      "id": "note6f78901a-bcde-f123-4567-890abcdef123",
      "name": "Calendar Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1920,
        512
      ],
      "parameters": {
        "width": 280,
        "height": 264,
        "content": "## \u2699\ufe0f Google Calendar Setup\n\nThis branch creates a calendar event for *each* asteroid found.\n\n**Setup Required:**\n1. Select the 'Create an event' node.\n2. Add your Google Calendar OAuth2 credentials.\n3. Select your desired calendar.\n\n**Customization:** You can modify the event title, description, and even add color-coding based on hazard level."
      },
      "typeVersion": 1
    },
    {
      "id": "note7890abcd-ef12-3456-7890-abcdef123456",
      "name": "No Results Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        480
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 224,
        "content": "## No Asteroids Branch\n\nThis is the 'false' branch of the IF node. It's triggered when no asteroids meet the filtering criteria.\n\nThe **NoOp** node does nothing, ending the workflow silently.\n\n**Idea:** Replace this with a node that sends a daily \"All Clear\" message."
      },
      "typeVersion": 1
    },
    {
      "id": "8da8e937-6acf-43d7-8a7e-43635b7abfde",
      "name": "Get an asteroid neo feed",
      "type": "n8n-nodes-base.nasa",
      "position": [
        720,
        304
      ],
      "parameters": {
        "resource": "asteroidNeoFeed",
        "additionalFields": {}
      },
      "credentials": {
        "nasaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9c7340e9-6b56-4888-8180-373942e5d1d7",
      "name": "Create an event",
      "type": "n8n-nodes-base.googleCalendar",
      "position": [
        2064,
        304
      ],
      "parameters": {
        "start": "={{ $json.asteroids.approach_date_full }}",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "user@example.com",
          "cachedResultName": "user@example.com"
        },
        "additionalFields": {
          "summary": "\u5c0f\u60d1\u661f\u63a5\u8fd1\u30a2\u30e9\u30fc\u30c8",
          "description": "=\u63a5\u8fd1\u8ddd\u96e2: {{ $json.asteroids.miss_distance_km.toLocaleString() }} km \n\u76f4\u5f84: \u7d04{{ $json.asteroids.diameter_avg_m }} m \n\u901f\u5ea6: {{ $json.asteroids.velocity_km_h.toLocaleString() }} km/h \n\u8a73\u7d30URL: {{ $json.asteroids.nasa_jpl_url }}"
        }
      },
      "credentials": {
        "googleCalendarOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "89d59b68-b6a1-43c3-8968-c6710a561032",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1616,
        400
      ],
      "parameters": {},
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "timezone": "America/New_York",
    "errorWorkflow": "",
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "saveExecutionProgress": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "versionId": "80885207-ba21-410d-b306-fc5bc0e8e339",
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Calculate Date Range",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Date Range": {
      "main": [
        [
          {
            "node": "Get an asteroid neo feed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Alert Messages": {
      "main": [
        [
          {
            "node": "Send Slack Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "Split Out Individual Asteroids",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Asteroids Found": {
      "main": [
        [
          {
            "node": "Format Alert Messages",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get an asteroid neo feed": {
      "main": [
        [
          {
            "node": "Filter and Process Asteroids",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter and Process Asteroids": {
      "main": [
        [
          {
            "node": "Check If Asteroids Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Individual Asteroids": {
      "main": [
        [
          {
            "node": "Create an event",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This n8n template creates an automated alert system that checks NASA's data for near-Earth asteroids twice a day. When it finds asteroids meeting specific criteria, it sends a summary alert to Slack and creates individual events in Google Calendar for each object. Automated…

Source: https://n8n.io/workflows/9877/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

This workflow is designed for space enthusiasts, science educators, journalists, fact-checkers, and researchers who want to stay informed about near-Earth asteroid threats while filtering out media se

Nasa, @Apify/N8N Nodes Apify, OpenAI +4
Slack & Telegram

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

HTTP Request, Execute Workflow Trigger, Slack
Slack & Telegram

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

HTTP Request, Noco Db, Slack
Slack & Telegram

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

HTTP Request, Telegram, Google Sheets +1
Slack & Telegram

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

HTTP Request, Email Send, Google Sheets +1