AutomationFlowsData & Sheets › Track Flight Fares with Amadeus & Skyscanner - Alerts, Refunds & Trends

Track Flight Fares with Amadeus & Skyscanner - Alerts, Refunds & Trends

ByOneclick AI Squad @oneclick-ai on n8n.io

This automated n8n workflow tracks booked flight fares post-purchase using Amadeus and Skyscanner APIs to detect drops for refund or credit opportunities. It streamlines fare monitoring, updates booking statuses, and notifies users via SMS or email. Fare Check Trigger -…

Cron / scheduled trigger★★★★☆ complexity17 nodesPostgresHTTP Request
Data & Sheets Trigger: Cron / scheduled Nodes: 17 Complexity: ★★★★☆ Added:

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

This workflow follows the HTTP Request → Postgres 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": "Imsit8rJhCw7DEeD",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Post-Booking Fare Tracker \u2013 Auto Alerts & Refund Checks via Amadeus & Skyscanner",
  "tags": [],
  "nodes": [
    {
      "id": "bd086b06-0407-47a6-8589-a3352a6d974d",
      "name": "Fare Check Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1760,
        100
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "cadfad91-fbb4-4067-9b11-e851e4961850",
      "name": "Get Tracked Bookings",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -1540,
        100
      ],
      "parameters": {
        "query": "SELECT \n  b.booking_id,\n  b.passenger_name,\n  b.email,\n  b.phone,\n  b.flight_number,\n  b.departure_date,\n  b.origin,\n  b.destination,\n  b.airline,\n  b.booking_class,\n  b.original_fare,\n  b.booking_date,\n  b.confirmation_code,\n  b.tracking_enabled,\n  b.last_checked,\n  COALESCE(ft.lowest_fare, b.original_fare) as current_lowest_fare,\n  COALESCE(ft.fare_trend, 'stable') as trend\nFROM bookings b\nLEFT JOIN fare_tracking ft ON b.booking_id = ft.booking_id\nWHERE b.departure_date > CURRENT_DATE + INTERVAL '1 day'\n  AND b.departure_date <= CURRENT_DATE + INTERVAL '90 days'\n  AND b.tracking_enabled = true\n  AND b.booking_status = 'confirmed'\n  AND (b.last_checked IS NULL OR b.last_checked < NOW() - INTERVAL '6 hours')\nORDER BY b.departure_date ASC\nLIMIT 50",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "130d2cfc-85d9-4666-b456-28d6bdb3b82c",
      "name": "Prepare Fare Search",
      "type": "n8n-nodes-base.code",
      "position": [
        -1320,
        100
      ],
      "parameters": {
        "jsCode": "// Process bookings for fare tracking\nconst bookings = $input.all()[0].json;\nconst processedBookings = [];\n\nfor (const booking of bookings) {\n  // Format dates and create search parameters\n  const departureDate = new Date(booking.departure_date).toISOString().split('T')[0];\n  const searchParams = {\n    booking_id: booking.booking_id,\n    origin: booking.origin,\n    destination: booking.destination,\n    departure_date: departureDate,\n    airline: booking.airline,\n    flight_number: booking.flight_number,\n    booking_class: booking.booking_class,\n    original_fare: parseFloat(booking.original_fare),\n    passenger_name: booking.passenger_name,\n    email: booking.email,\n    phone: booking.phone,\n    confirmation_code: booking.confirmation_code,\n    current_lowest_fare: parseFloat(booking.current_lowest_fare || booking.original_fare),\n    booking_date: booking.booking_date,\n    last_checked: new Date().toISOString()\n  };\n  \n  processedBookings.push(searchParams);\n}\n\nreturn processedBookings.map(booking => ({ json: booking }));"
      },
      "typeVersion": 2
    },
    {
      "id": "c1f499d6-e616-4da3-a4dc-1bbaa7492048",
      "name": "Search Current Fares",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1100,
        100
      ],
      "parameters": {
        "url": "https://api.amadeus.com/v2/shopping/flight-offers",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 5,
              "batchInterval": 2000
            }
          }
        },
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{ $credentials.amadeus.access_token }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "480dfb10-9c5c-4685-9681-403a49bcc48f",
      "name": "Search Skyscanner Fares",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1100,
        260
      ],
      "parameters": {
        "url": "https://api.skyscanner.com/browse/v1.0/US/USD/en-US/{{ $json.origin }}/{{ $json.destination }}/{{ $json.departure_date }}",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 3,
              "batchInterval": 3000
            }
          }
        },
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "{{ $credentials.skyscanner.api_key }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "e7d9abc5-d372-48d9-821d-cc535e3be820",
      "name": "Analyze Fare Drops",
      "type": "n8n-nodes-base.code",
      "position": [
        -880,
        100
      ],
      "parameters": {
        "jsCode": "// Analyze fare data and detect drops\nconst bookingData = $('prepare-fare-search').item.json;\nconst amadeusFares = $('search-current-fares').item.json.data || [];\nconst skyscannerFares = $('search-skyscanner-fares').item.json.Quotes || [];\n\nconst originalFare = bookingData.original_fare;\nconst currentLowestFare = bookingData.current_lowest_fare;\nlet newLowestFare = originalFare;\nlet fareSource = 'original';\nlet availableFares = [];\n\n// Process Amadeus fares\namadeusFares.forEach(offer => {\n  if (offer.price && offer.price.total) {\n    const fare = parseFloat(offer.price.total);\n    availableFares.push({\n      source: 'amadeus',\n      fare: fare,\n      airline: offer.validatingAirlineCodes?.[0] || 'Unknown',\n      flight_number: offer.itineraries?.[0]?.segments?.[0]?.number || 'N/A',\n      booking_class: offer.travelerPricings?.[0]?.fareDetailsBySegment?.[0]?.class || 'Unknown'\n    });\n    \n    if (fare < newLowestFare) {\n      newLowestFare = fare;\n      fareSource = 'amadeus';\n    }\n  }\n});\n\n// Process Skyscanner fares\nskyscannerFares.forEach(quote => {\n  if (quote.MinPrice) {\n    const fare = parseFloat(quote.MinPrice);\n    availableFares.push({\n      source: 'skyscanner',\n      fare: fare,\n      airline: 'Various',\n      flight_number: 'Multiple',\n      booking_class: 'Economy'\n    });\n    \n    if (fare < newLowestFare) {\n      newLowestFare = fare;\n      fareSource = 'skyscanner';\n    }\n  }\n});\n\n// Calculate savings and determine action\nconst originalSavings = originalFare - newLowestFare;\nconst currentSavings = currentLowestFare - newLowestFare;\nconst savingsPercentage = ((originalFare - newLowestFare) / originalFare * 100).toFixed(1);\n\n// Determine fare trend\nlet trend = 'stable';\nif (newLowestFare < currentLowestFare * 0.95) trend = 'dropping';\nelse if (newLowestFare > currentLowestFare * 1.05) trend = 'rising';\n\n// Determine notification priority\nlet priority = 'low';\nlet actionRecommended = false;\n\nif (originalSavings >= 100 || savingsPercentage >= 15) {\n  priority = 'high';\n  actionRecommended = true;\n} else if (originalSavings >= 50 || savingsPercentage >= 8) {\n  priority = 'medium';\n  actionRecommended = true;\n}\n\n// Check airline-specific refund policies\nconst refundEligible = checkRefundEligibility(bookingData.airline, originalSavings, bookingData.booking_date);\n\nfunction checkRefundEligibility(airline, savings, bookingDate) {\n  const daysSinceBooking = Math.floor((new Date() - new Date(bookingDate)) / (1000 * 60 * 60 * 24));\n  \n  // Airline-specific policies (simplified)\n  const policies = {\n    'AA': { min_savings: 50, max_days: 24 }, // American Airlines\n    'DL': { min_savings: 75, max_days: 24 }, // Delta\n    'UA': { min_savings: 50, max_days: 24 }, // United\n    'SW': { min_savings: 25, max_days: 365 }, // Southwest (more flexible)\n    'JB': { min_savings: 50, max_days: 24 }, // JetBlue\n  };\n  \n  const policy = policies[airline] || { min_savings: 75, max_days: 24 };\n  \n  return savings >= policy.min_savings && daysSinceBooking <= policy.max_days;\n}\n\nreturn [{\n  json: {\n    ...bookingData,\n    new_lowest_fare: newLowestFare,\n    fare_source: fareSource,\n    original_savings: Math.round(originalSavings * 100) / 100,\n    current_savings: Math.round(currentSavings * 100) / 100,\n    savings_percentage: parseFloat(savingsPercentage),\n    fare_trend: trend,\n    priority: priority,\n    action_recommended: actionRecommended,\n    refund_eligible: refundEligible,\n    available_fares: availableFares.sort((a, b) => a.fare - b.fare).slice(0, 5),\n    check_timestamp: new Date().toISOString(),\n    days_until_departure: Math.ceil((new Date(bookingData.departure_date) - new Date()) / (1000 * 60 * 60 * 24))\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "bae0410f-8047-4da1-a6ee-fd65bc0c3e04",
      "name": "Update Fare Tracking",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -660,
        100
      ],
      "parameters": {
        "query": "INSERT INTO fare_tracking \n  (booking_id, check_date, lowest_fare, fare_source, savings_amount, savings_percentage, fare_trend, priority_level, action_recommended, refund_eligible, available_fares_json)\nVALUES \n  ($1, NOW(), $2, $3, $4, $5, $6, $7, $8, $9, $10)\nON CONFLICT (booking_id) \nDO UPDATE SET \n  check_date = NOW(),\n  lowest_fare = $2,\n  fare_source = $3,\n  savings_amount = $4,\n  savings_percentage = $5,\n  fare_trend = $6,\n  priority_level = $7,\n  action_recommended = $8,\n  refund_eligible = $9,\n  available_fares_json = $10,\n  updated_at = NOW()",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "82e08313-a74f-43d2-8546-fadac8905ad4",
      "name": "Update Booking Status",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -440,
        100
      ],
      "parameters": {
        "query": "UPDATE bookings SET \n  last_checked = NOW(),\n  current_lowest_fare = $1\nWHERE booking_id = $2",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "84deb9be-4d7c-4a71-8d35-dd4b7de81250",
      "name": "Check if Notification Needed",
      "type": "n8n-nodes-base.if",
      "position": [
        -220,
        100
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-significant-savings",
              "operator": {
                "type": "boolean",
                "operation": "equal"
              },
              "leftValue": "={{ $json.action_recommended }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "999513d1-0494-4555-8106-c5e6beff8e71",
      "name": "Send Fare Drop Email",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        0,
        0
      ],
      "parameters": {
        "url": "https://api.sendgrid.com/v3/mail/send",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "personalizations",
              "value": "={{ [{ \"to\": [{ \"email\": $json.email, \"name\": $json.passenger_name }], \"dynamic_template_data\": { \"passenger_name\": $json.passenger_name, \"flight_number\": $json.flight_number, \"route\": $json.origin + \" to \" + $json.destination, \"departure_date\": $json.departure_date, \"original_fare\": $json.original_fare, \"new_lowest_fare\": $json.new_lowest_fare, \"savings_amount\": $json.original_savings, \"savings_percentage\": $json.savings_percentage, \"refund_eligible\": $json.refund_eligible, \"confirmation_code\": $json.confirmation_code, \"priority\": $json.priority, \"available_fares\": $json.available_fares, \"days_until_departure\": $json.days_until_departure } }] }}"
            },
            {
              "name": "from",
              "value": "{ \"email\": \"user@example.com\", \"name\": \"Flight Fare Tracker\" }"
            },
            {
              "name": "template_id",
              "value": "d-fare-drop-alert"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{ $credentials.sendgrid.api_key }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "cc92b941-e37f-4e2d-8f2b-e40eb5bc08ce",
      "name": "Check if SMS Needed",
      "type": "n8n-nodes-base.if",
      "position": [
        0,
        200
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-high-priority",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.priority }}",
              "rightValue": "high"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "4159d4b7-c371-49ca-8529-74c20f82b3ac",
      "name": "Send SMS Alert",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        220,
        300
      ],
      "parameters": {
        "url": "https://api.twilio.com/2010-04-01/Accounts/{{ $credentials.twilio.account_sid }}/Messages.json",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "To",
              "value": "={{ $json.phone }}"
            },
            {
              "name": "From",
              "value": "{{ $credentials.twilio.phone_number }}"
            },
            {
              "name": "Body",
              "value": "\ud83d\udd25 FARE DROP ALERT! Your flight {{ $json.flight_number }} ({{ $json.departure_date }}) dropped by ${{ $json.original_savings }} ({{ $json.savings_percentage }}%). {{ $json.refund_eligible ? 'You may be eligible for a refund!' : 'Consider rebooking.' }} Check email for details."
            }
          ]
        },
        "genericAuthType": "httpBasicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "73850d25-94e4-4843-9781-7cba5dcb6b00",
      "name": "Notify Slack Team",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        220,
        100
      ],
      "parameters": {
        "url": "https://api.slack.com/api/chat.postMessage",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "channel",
              "value": "#fare-alerts"
            },
            {
              "name": "text",
              "value": "\ud83d\udcb0 *High-Value Fare Drop Detected*\\n\\n\u2708\ufe0f *Flight:* {{ $json.flight_number }}\\n\ud83d\udc64 *Passenger:* {{ $json.passenger_name }}\\n\ud83d\udeeb *Route:* {{ $json.origin }} \u2192 {{ $json.destination }}\\n\ud83d\udcc5 *Date:* {{ $json.departure_date }}\\n\\n\ud83d\udcb5 *Original Fare:* ${{ $json.original_fare }}\\n\ud83d\udd3b *New Low:* ${{ $json.new_lowest_fare }}\\n\ud83d\udcb8 *Savings:* ${{ $json.original_savings }} ({{ $json.savings_percentage }}%)\\n\\n{{ $json.refund_eligible ? '\u2705 *Refund Eligible*' : '\u274c *Refund Not Available*' }}\\n\ud83d\udd14 *Priority:* {{ $json.priority.toUpperCase() }}"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{ $credentials.slack.token }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "d1110183-fd41-478a-8a2f-3190a8a9578b",
      "name": "Check Refund Eligible",
      "type": "n8n-nodes-base.if",
      "position": [
        440,
        100
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "refund-eligible",
              "operator": {
                "type": "boolean",
                "operation": "equal"
              },
              "leftValue": "={{ $json.refund_eligible }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "e0b7f2b0-b5d0-4b94-8eb3-17514aa61f02",
      "name": "Initiate Refund Process",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        660,
        200
      ],
      "parameters": {
        "url": "https://api.airline-booking-system.com/refund/initiate",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "confirmation_code",
              "value": "={{ $json.confirmation_code }}"
            },
            {
              "name": "passenger_email",
              "value": "={{ $json.email }}"
            },
            {
              "name": "reason",
              "value": "fare_drop_detected"
            },
            {
              "name": "original_fare",
              "value": "={{ $json.original_fare }}"
            },
            {
              "name": "current_fare",
              "value": "={{ $json.new_lowest_fare }}"
            },
            {
              "name": "savings_amount",
              "value": "={{ $json.original_savings }}"
            },
            {
              "name": "automated_request",
              "value": true
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer {{ $credentials.airline_system.api_token }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "669f4e48-28cf-45f3-941d-d6c13da22990",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1520,
        -420
      ],
      "parameters": {
        "color": 5,
        "width": 740,
        "height": 380,
        "content": "\n## Fundamental Aspects\n- **Fare Check Trigger** - Initiates the workflow\n- **Get Tracked Bookings** - Retrieves existing booking data\n- **Prepare Fare Query** - Prepares query parameters\n- **Search Current Fares** - Queries Skyscanner for current fares\n- **Analyze Fare Drops** - Identifies significant fare reductions\n- **Update Fare Tracking** - Updates fare tracking records\n- **Update Booking Status** - Updates status based on fare changes\n- **Check if Notification Needed** - Determines if alerts are required\n- **Send Fare Drop Email** - Notifies users via email\n- **Notify Slack Team** - Alerts the team via Slack\n- **Check Refund Eligible** - Assesses refund eligibility\n- **Initiate Refund Process** - Starts refund procedure if eligible\n- **Check if SMS Needed** - Decides if SMS alert is necessary\n- **Send SMS Alert** - Sends SMS notification"
      },
      "typeVersion": 1
    },
    {
      "id": "7e9c2094-55fb-4004-8f08-79ce3288cf00",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -460,
        -300
      ],
      "parameters": {
        "width": 420,
        "height": 180,
        "content": "## Required Resources\n- Amadeus API credentials\n- Skyscanner API credentials\n- Email/SMS service integration (e.g., Twilio, SMTP)\n- Slack webhook URL\n- n8n instance with internet access"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "8457773b-5566-49ec-9c37-a3f097504269",
  "connections": {
    "Notify Slack Team": {
      "main": [
        [
          {
            "node": "Check Refund Eligible",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Fare Drops": {
      "main": [
        [
          {
            "node": "Update Fare Tracking",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fare Check Trigger": {
      "main": [
        [
          {
            "node": "Get Tracked Bookings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if SMS Needed": {
      "main": [
        [
          {
            "node": "Send SMS Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Fare Search": {
      "main": [
        [
          {
            "node": "Search Current Fares",
            "type": "main",
            "index": 0
          },
          {
            "node": "Search Skyscanner Fares",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Tracked Bookings": {
      "main": [
        [
          {
            "node": "Prepare Fare Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Current Fares": {
      "main": [
        [
          {
            "node": "Analyze Fare Drops",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Fare Tracking": {
      "main": [
        [
          {
            "node": "Update Booking Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Refund Eligible": {
      "main": [
        [
          {
            "node": "Initiate Refund Process",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Booking Status": {
      "main": [
        [
          {
            "node": "Check if Notification Needed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Skyscanner Fares": {
      "main": [
        [
          {
            "node": "Analyze Fare Drops",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Notification Needed": {
      "main": [
        [
          {
            "node": "Send Fare Drop Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Check if SMS Needed",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notify Slack Team",
            "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 automated n8n workflow tracks booked flight fares post-purchase using Amadeus and Skyscanner APIs to detect drops for refund or credit opportunities. It streamlines fare monitoring, updates booking statuses, and notifies users via SMS or email. Fare Check Trigger -…

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

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

Disparador 1.8. Uses itemLists, postgres, emailSend, httpRequest. Scheduled trigger; 85 nodes.

Item Lists, Postgres, Email Send +1
Data & Sheets

공유회_알림톡_크론. Uses postgres, httpRequest, n8n-nodes-solapi. Scheduled trigger; 39 nodes.

Postgres, HTTP Request, N8N Nodes Solapi
Data & Sheets

QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.

Postgres, Postgres Trigger, HTTP Request
Data & Sheets

QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.

Postgres, Postgres Trigger, HTTP Request
Data & Sheets

QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.

Postgres, Postgres Trigger, HTTP Request