Comparaison automatisée des prix des vols
Ceci est unMiscellaneousworkflow d'automatisation du domainecontenant 19 nœuds.Utilise principalement des nœuds comme If, Ssh, Code, Webhook, EmailSend. Comparer les prix des vols sur plusieurs plateformes de réservation et générer un rapport par e-mail
- •Point de terminaison HTTP Webhook (généré automatiquement par n8n)
Nœuds utilisés (19)
Catégorie
{
"id": "IuvYgHrzvtEck50d",
"meta": {
"instanceId": "dd69efaf8212c74ad206700d104739d3329588a6f3f8381a46a481f34c9cc281",
"templateCredsSetupCompleted": true
},
"name": "Automate flight Price Comparison",
"tags": [],
"nodes": [
{
"id": "d4a5235a-57c0-42f6-9841-8f45d04dfe1c",
"name": "Webhook - Receive Flight Request",
"type": "n8n-nodes-base.webhook",
"position": [
-1088,
432
],
"webhookId": "flight-price-webhook",
"parameters": {
"path": "flight-price-compare",
"options": {
"allowedOrigins": "*"
},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "81bb3dac-0cd3-4826-8436-573bc393f2c4",
"name": "Analyser et Valider la Demande de Vol",
"type": "n8n-nodes-base.code",
"position": [
-864,
432
],
"parameters": {
"jsCode": "// Enhanced Flight Request Parser with NLP\nconst body = $input.first().json.body || {};\nconst query = body.message || body.query || '';\n\n// Extract user details\nconst userEmail = body.email || body.user_email || '';\nconst userName = body.name || body.user_name || 'Traveler';\nconst notifyPriceDrop = body.notify_price_drop || false;\n\n// Greeting handler\nconst greetings = ['hi', 'hello', 'hey', 'start', 'help'];\nif (greetings.some(g => query.toLowerCase().includes(g)) && query.split(' ').length < 5) {\n return [{\n json: {\n status: 'greeting',\n response: `Hi ${userName}! ✈️ I'm your Flight Price Comparison Assistant.\\n\\nTell me:\\n✅ From city/airport\\n✅ To city/airport\\n✅ Departure date\\n✅ Trip type (one-way/round-trip)\\n\\nExample: \"Flight from New York to London on 25th March, one-way\"`,\n userEmail,\n userName\n }\n }];\n}\n\n// Airport/City codes mapping\nconst airportCodes = {\n 'new york': 'JFK', 'nyc': 'JFK', 'london': 'LHR', 'paris': 'CDG',\n 'dubai': 'DXB', 'singapore': 'SIN', 'tokyo': 'NRT', 'mumbai': 'BOM',\n 'delhi': 'DEL', 'bangalore': 'BLR', 'los angeles': 'LAX', 'chicago': 'ORD',\n 'san francisco': 'SFO', 'boston': 'BOS', 'miami': 'MIA', 'sydney': 'SYD',\n 'melbourne': 'MEL', 'hong kong': 'HKG', 'bangkok': 'BKK', 'amsterdam': 'AMS',\n 'frankfurt': 'FRA', 'toronto': 'YYZ', 'vancouver': 'YVR', 'seattle': 'SEA'\n};\n\nfunction getAirportCode(text) {\n const lower = text.toLowerCase().trim();\n if (/^[A-Z]{3}$/i.test(text)) return text.toUpperCase();\n return airportCodes[lower] || text.toUpperCase();\n}\n\n// Parse dates\nfunction parseDate(text) {\n const monthMap = {\n jan: 0, january: 0, feb: 1, february: 1, mar: 2, march: 2,\n apr: 3, april: 3, may: 4, jun: 5, june: 5,\n jul: 6, july: 6, aug: 7, august: 7, sep: 8, september: 8,\n oct: 9, october: 9, nov: 10, november: 10, dec: 11, december: 11\n };\n\n const dateRegex = /(\\d{1,2})(st|nd|rd|th)?\\s+(jan|january|feb|february|mar|march|apr|april|may|jun|june|jul|july|aug|august|sep|september|oct|october|nov|november|dec|december)|\\d{4}-\\d{2}-\\d{2}/gi;\n const matches = [...text.matchAll(dateRegex)];\n const dates = [];\n const currentYear = new Date().getFullYear();\n \n matches.forEach(match => {\n if (match[0].includes('-')) {\n dates.push(new Date(match[0]));\n } else {\n const day = parseInt(match[1]);\n const monthStr = match[3].toLowerCase();\n const month = monthMap[monthStr];\n if (day && month !== undefined) {\n dates.push(new Date(currentYear, month, day));\n }\n }\n });\n \n return dates.sort((a, b) => a - b);\n}\n\n// Extract origin and destination\nlet origin = '';\nlet destination = '';\n\nconst routePattern = /(?:from|leaving)?\\s*([a-z\\s]{3,25})\\s+to\\s+([a-z\\s]{3,25})/i;\nconst routeMatch = query.match(routePattern);\n\nif (routeMatch) {\n origin = routeMatch[1].trim();\n destination = routeMatch[2].trim();\n} else {\n origin = body.from || body.origin || body.departure_airport || '';\n destination = body.to || body.destination || body.arrival_airport || '';\n}\n\nconst originCode = getAirportCode(origin);\nconst destinationCode = getAirportCode(destination);\n\nconst dates = parseDate(query + ' ' + (body.departure_date || ''));\nlet departureDate = dates[0] || null;\nlet returnDate = dates[1] || null;\n\nlet tripType = 'one-way';\nif (query.match(/round[\\s-]?trip|return/i) || returnDate) {\n tripType = 'round-trip';\n}\nif (body.trip_type) {\n tripType = body.trip_type.toLowerCase();\n}\n\nconst passengers = body.passengers || 1;\nconst cabinClass = body.class || body.cabin_class || 'economy';\n\nconst errors = [];\nif (!originCode || originCode.length < 3) errors.push('departure city/airport');\nif (!destinationCode || destinationCode.length < 3) errors.push('arrival city/airport');\nif (!departureDate) errors.push('departure date');\nif (tripType === 'round-trip' && !returnDate) errors.push('return date');\n\nif (errors.length > 0) {\n return [{\n json: {\n status: 'missing_info',\n response: `I need more information: ${errors.join(', ')}.\\n\\nExample: \"Flight from Mumbai to Dubai on 15th March, round-trip returning 20th March\"`,\n userEmail,\n userName\n }\n }];\n}\n\nconst formatDate = (date) => {\n if (!date) return null;\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}`;\n};\n\nconst formatDateISO = (date) => {\n if (!date) return null;\n return date.toISOString().split('T')[0];\n};\n\nreturn [{\n json: {\n status: 'ready',\n origin: originCode,\n destination: destinationCode,\n originCity: origin,\n destinationCity: destination,\n departureDate: formatDate(departureDate),\n returnDate: returnDate ? formatDate(returnDate) : null,\n departureDateISO: formatDateISO(departureDate),\n returnDateISO: formatDateISO(returnDate),\n tripType,\n passengers,\n cabinClass,\n userEmail,\n userName,\n notifyPriceDrop,\n originalQuery: query\n }\n}];"
},
"typeVersion": 2
},
{
"id": "3f5bb362-ca6a-4c1d-a959-9f194fcc7e99",
"name": "Vérifier si la Demande est Valide",
"type": "n8n-nodes-base.if",
"position": [
-640,
432
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"value2": "ready"
}
]
}
},
"typeVersion": 1
},
{
"id": "07df7d09-a38d-4540-b8f8-0e81405e086b",
"name": "Scraper Kayak",
"type": "n8n-nodes-base.ssh",
"onError": "continueErrorOutput",
"position": [
-416,
48
],
"parameters": {
"cwd": "/home/oneclick-server2/",
"command": "=python3 /home/oneclick-server2/flight_scraper.py {{ $json.origin }} {{ $json.destination }} {{ $json.departureDateISO }} {{ $json.returnDateISO || '' }} {{ $json.tripType }} {{ $json.passengers }} {{ $json.cabinClass }} kayak",
"authentication": "privateKey"
},
"credentials": {
"sshPrivateKey": {
"id": "ilPh8oO4GfSlc0Qy",
"name": "SSH Password account - test "
}
},
"typeVersion": 1
},
{
"id": "2acab75d-4d75-49d7-8c37-dc36740e7636",
"name": "Scraper Skyscanner",
"type": "n8n-nodes-base.ssh",
"onError": "continueErrorOutput",
"position": [
-416,
240
],
"parameters": {
"cwd": "/home/oneclick-server2/",
"command": "=python3 /home/oneclick-server2/flight_scraper.py {{ $json.origin }} {{ $json.destination }} {{ $json.departureDateISO }} {{ $json.returnDateISO || '' }} {{ $json.tripType }} {{ $json.passengers }} {{ $json.cabinClass }} skyscanner",
"authentication": "privateKey"
},
"credentials": {
"sshPrivateKey": {
"id": "ilPh8oO4GfSlc0Qy",
"name": "SSH Password account - test "
}
},
"typeVersion": 1
},
{
"id": "b74690a3-61b9-41df-967b-bf395fb6aade",
"name": "Scraper Expedia",
"type": "n8n-nodes-base.ssh",
"onError": "continueErrorOutput",
"position": [
-416,
432
],
"parameters": {
"cwd": "/home/oneclick-server2/",
"command": "=python3 /home/oneclick-server2/flight_scraper.py {{ $json.origin }} {{ $json.destination }} {{ $json.departureDateISO }} {{ $json.returnDateISO || '' }} {{ $json.tripType }} {{ $json.passengers }} {{ $json.cabinClass }} expedia",
"authentication": "privateKey"
},
"credentials": {
"sshPrivateKey": {
"id": "ilPh8oO4GfSlc0Qy",
"name": "SSH Password account - test "
}
},
"typeVersion": 1
},
{
"id": "76e69f7a-9683-47ce-bdf0-b673c504a4b2",
"name": "Scraper Google Flights",
"type": "n8n-nodes-base.ssh",
"onError": "continueErrorOutput",
"position": [
-416,
816
],
"parameters": {
"cwd": "/home/oneclick-server2/",
"command": "=python3 /home/oneclick-server2/flight_scraper.py {{ $json.origin }} {{ $json.destination }} {{ $json.departureDateISO }} {{ $json.returnDateISO || '' }} {{ $json.tripType }} {{ $json.passengers }} {{ $json.cabinClass }} googleflights",
"authentication": "privateKey"
},
"credentials": {
"sshPrivateKey": {
"id": "ilPh8oO4GfSlc0Qy",
"name": "SSH Password account - test "
}
},
"typeVersion": 1
},
{
"id": "020178b1-0de8-4cbc-812d-bec95ad92d8f",
"name": "Agréger et Analyser les Prix",
"type": "n8n-nodes-base.code",
"position": [
-64,
336
],
"parameters": {
"jsCode": "// Aggregate flight prices from all platforms\nconst items = $input.all();\nconst searchData = items[0].json;\n\nconst flights = [];\nconst errors = [];\n\nconst platforms = ['Kayak', 'Skyscanner', 'Expedia', 'Google Flights'];\n\nitems.slice(1).forEach((item, index) => {\n const platform = platforms[index];\n const output = item.json.stdout || '';\n \n if (item.json.stderr || !output) {\n errors.push(`${platform}: Unable to fetch`);\n return;\n }\n \n const lines = output.trim().split('\\n');\n \n lines.forEach(line => {\n if (line.includes('|')) {\n const parts = line.split('|');\n if (parts.length >= 6) {\n const price = parseFloat(parts[1].replace(/[^0-9.]/g, ''));\n \n if (price && price > 0) {\n flights.push({\n platform,\n airline: parts[0].trim(),\n price,\n currency: parts[1].match(/[A-Z₹$€£]/)?.[0] || '$',\n duration: parts[2].trim(),\n stops: parts[3].trim(),\n departureTime: parts[4].trim(),\n arrivalTime: parts[5].trim(),\n bookingUrl: parts[6]?.trim() || '#',\n cabinClass: searchData.cabinClass\n });\n }\n }\n }\n });\n});\n\nif (flights.length === 0) {\n return [{\n json: {\n status: 'no_results',\n message: 'No flights found for your search criteria.',\n errors,\n ...searchData\n }\n }];\n}\n\nflights.sort((a, b) => a.price - b.price);\n\nconst bestDeal = flights[0];\nconst avgPrice = flights.reduce((sum, f) => sum + f.price, 0) / flights.length;\nconst maxPrice = flights[flights.length - 1].price;\nconst savings = maxPrice - bestDeal.price;\n\nconst directFlights = flights.filter(f => f.stops === '0' || f.stops.toLowerCase().includes('non'));\nconst bestDirectFlight = directFlights.length > 0 ? directFlights[0] : null;\n\nreturn [{\n json: {\n status: 'success',\n ...searchData,\n results: flights,\n bestDeal,\n bestDirectFlight,\n avgPrice: Math.round(avgPrice),\n maxPrice: Math.round(maxPrice),\n savings: Math.round(savings),\n totalResults: flights.length,\n directFlightsCount: directFlights.length,\n errors,\n searchTimestamp: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
},
{
"id": "b195bb98-d48b-442d-8ceb-7809a2f65d15",
"name": "Formater le Rapport Email",
"type": "n8n-nodes-base.code",
"position": [
256,
336
],
"parameters": {
"jsCode": "// Format email report\nconst data = $input.first().json;\n\nif (data.status === 'no_results') {\n return [{\n json: {\n subject: `❌ No Flights - ${data.origin} to ${data.destination}`,\n text: `No flights found for ${data.origin} to ${data.destination} on ${data.departureDate}`,\n ...data\n }\n }];\n}\n\nconst { origin, destination, departureDate, returnDate, tripType, passengers, results, bestDeal, avgPrice, savings } = data;\n\nconst topResults = results.slice(0, 10);\nconst resultsText = topResults.map((f, i) => \n `${i + 1}. ${f.airline} - ${f.currency}${f.price} (${f.stops === '0' ? 'Non-stop' : f.stops + ' stop(s)'}) - ${f.platform}`\n).join('\\n');\n\nconst textReport = `\nFLIGHT PRICE COMPARISON\n${'='.repeat(50)}\n\nRoute: ${origin} → ${destination}\nDeparture: ${departureDate}\n${returnDate ? `Return: ${returnDate}\\n` : ''}Trip Type: ${tripType}\nPassengers: ${passengers}\n\n🏆 BEST DEAL\n${'-'.repeat(50)}\n${bestDeal.airline}\nPrice: ${bestDeal.currency}${bestDeal.price}\nDuration: ${bestDeal.duration}\nStops: ${bestDeal.stops === '0' ? 'Non-stop' : bestDeal.stops + ' stop(s)'}\nPlatform: ${bestDeal.platform}\n${savings > 0 ? `\\n💰 Save ${bestDeal.currency}${savings} vs highest price!` : ''}\n\n📊 ALL RESULTS (Top 10)\n${'-'.repeat(50)}\n${resultsText}\n\nAverage Price: ${bestDeal.currency}${avgPrice}\nTotal Results: ${results.length}\n\nPrices subject to availability.\nHappy travels! ✈️\n`;\n\nreturn [{\n json: {\n subject: `✈️ ${origin} → ${destination} - Best: ${bestDeal.currency}${bestDeal.price}`,\n text: textReport,\n ...data\n }\n}];"
},
"typeVersion": 2
},
{
"id": "994f5fa6-2e45-42f7-af12-f98026250c04",
"name": "Envoyer le Rapport par Email",
"type": "n8n-nodes-base.emailSend",
"position": [
480,
336
],
"webhookId": "7e60915f-7994-42f1-b850-dcb254a4d83c",
"parameters": {
"text": "={{$json.text}}",
"options": {},
"subject": "={{$json.subject}}",
"toEmail": "={{$json.userEmail}}",
"fromEmail": "flights@pricecomparison.com",
"emailFormat": "text"
},
"credentials": {
"smtp": {
"id": "G1kyF8cSWTZ4vouN",
"name": "SMTP -test"
}
},
"typeVersion": 2.1
},
{
"id": "8b3fbdb5-879f-4a02-8927-8632f944bd53",
"name": "Webhook Response (Success)",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
784,
336
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ {\n \"success\": true,\n \"message\": \"Flight comparison sent to \" + $json.userEmail,\n \"route\": $json.origin + \" → \" + $json.destination,\n \"bestPrice\": $json.bestDeal.price,\n \"airline\": $json.bestDeal.airline,\n \"totalResults\": $json.totalResults\n} }}"
},
"typeVersion": 1.1
},
{
"id": "d1d130de-f7f2-42ed-9f2b-591446329e6c",
"name": "Webhook Response (Error)",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-416,
624
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ {\n \"success\": false,\n \"message\": $json.response || \"Request failed\",\n \"status\": $json.status\n} }}"
},
"typeVersion": 1.1
},
{
"id": "35dd7ec1-cb14-4b34-9138-0d8e8af2380a",
"name": "Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1184,
-624
],
"parameters": {
"color": 4,
"width": 484,
"height": 476,
"content": "## 🎯 Workflow Purpose\n\n**Smart Flight Price Comparison**\n\nAutomatically compares flight prices across multiple booking platforms and sends detailed reports via email.\n\n### Key Features:\n✅ Natural language input\n✅ Multi-platform scraping\n✅ Best deal identification \n✅ Email reports\n✅ Real-time responses\n\n### Platforms Compared:\n- Kayak\n- Skyscanner\n- Expedia\n- Google Flights"
},
"typeVersion": 1
},
{
"id": "c312076a-7442-41fe-ac65-692581acde7d",
"name": "Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1408,
96
],
"parameters": {
"color": 5,
"width": 452,
"height": 516,
"content": "## 📥 INPUT STAGE\n\n**Webhook receives:**\n- Flight search query\n- User email\n- Alert preferences\n\n**Example:**\n```json\n{\n \"message\": \"NYC to London March 25\",\n \"email\": \"user@test.com\"\n}\n```"
},
"typeVersion": 1
},
{
"id": "f8aa3a61-314d-4b4e-83bb-477f50a7562a",
"name": "Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-928,
48
],
"parameters": {
"color": 5,
"width": 260,
"height": 612,
"content": "## 🧠 PARSE STAGE\n\n**Extracts:**\n- Airport codes\n- Dates (ISO format)\n- Trip type\n- Passengers\n\n**Validates:**\n- Required fields\n- Date formats\n- Airport codes"
},
"typeVersion": 1
},
{
"id": "32ea52fc-41ef-4f5c-bf12-c0b13b9a2866",
"name": "Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-508,
-280
],
"parameters": {
"color": 5,
"width": 280,
"height": 1224,
"content": "## 🔍 SCRAPE STAGE\n\n**Parallel scraping:**\n- All platforms simultaneously\n- Continue on failures\n- 30s timeout per scraper\n\n**Output format:**\nAIRLINE|PRICE|DURATION|STOPS|TIME|TIME|URL"
},
"typeVersion": 1
},
{
"id": "d503d1f7-06ca-4d75-96fc-b0a6d3fccb1a",
"name": "Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-112,
-32
],
"parameters": {
"color": 5,
"width": 260,
"height": 660,
"content": "## 📊 ANALYZE STAGE\n\n**Processes:**\n- Parse all results\n- Find best deals\n- Calculate stats\n- Sort by price\n\n**Outputs:**\n- Best overall\n- Best direct\n- Avg price\n- Savings"
},
"typeVersion": 1
},
{
"id": "b194c549-bdad-4f31-9ea3-5990caea9b84",
"name": "Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
224,
0
],
"parameters": {
"color": 5,
"width": 388,
"height": 628,
"content": "## 📧 REPORT STAGE\n\n**Email contains:**\n- Flight route & dates\n- Best deal highlight\n- Top 10 results\n- Price statistics\n- Booking links\n\n**Format:**\nPlain text (easy to read)"
},
"typeVersion": 1
},
{
"id": "0e963069-8538-431f-977b-9832b8905af4",
"name": "Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
688,
0
],
"parameters": {
"color": 5,
"width": 260,
"height": 612,
"content": "## ✅ RESPONSE STAGE\n\n**Success:**\n- Best price found\n- Airline name\n- Total results\n- Email sent confirmation\n\n**Error:**\n- Helpful message\n- What's missing\n- Example format"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "8562102b-7099-407b-ae1f-69da37f8da99",
"connections": {
"07df7d09-a38d-4540-b8f8-0e81405e086b": {
"main": [
[
{
"node": "020178b1-0de8-4cbc-812d-bec95ad92d8f",
"type": "main",
"index": 0
}
]
]
},
"b74690a3-61b9-41df-967b-bf395fb6aade": {
"main": [
[
{
"node": "020178b1-0de8-4cbc-812d-bec95ad92d8f",
"type": "main",
"index": 0
}
]
]
},
"2acab75d-4d75-49d7-8c37-dc36740e7636": {
"main": [
[
{
"node": "020178b1-0de8-4cbc-812d-bec95ad92d8f",
"type": "main",
"index": 0
}
]
]
},
"994f5fa6-2e45-42f7-af12-f98026250c04": {
"main": [
[
{
"node": "8b3fbdb5-879f-4a02-8927-8632f944bd53",
"type": "main",
"index": 0
}
]
]
},
"b195bb98-d48b-442d-8ceb-7809a2f65d15": {
"main": [
[
{
"node": "994f5fa6-2e45-42f7-af12-f98026250c04",
"type": "main",
"index": 0
}
]
]
},
"76e69f7a-9683-47ce-bdf0-b673c504a4b2": {
"main": [
[
{
"node": "020178b1-0de8-4cbc-812d-bec95ad92d8f",
"type": "main",
"index": 0
}
]
]
},
"3f5bb362-ca6a-4c1d-a959-9f194fcc7e99": {
"main": [
[
{
"node": "07df7d09-a38d-4540-b8f8-0e81405e086b",
"type": "main",
"index": 0
},
{
"node": "2acab75d-4d75-49d7-8c37-dc36740e7636",
"type": "main",
"index": 0
},
{
"node": "b74690a3-61b9-41df-967b-bf395fb6aade",
"type": "main",
"index": 0
},
{
"node": "76e69f7a-9683-47ce-bdf0-b673c504a4b2",
"type": "main",
"index": 0
}
],
[
{
"node": "d1d130de-f7f2-42ed-9f2b-591446329e6c",
"type": "main",
"index": 0
}
]
]
},
"020178b1-0de8-4cbc-812d-bec95ad92d8f": {
"main": [
[
{
"node": "b195bb98-d48b-442d-8ceb-7809a2f65d15",
"type": "main",
"index": 0
}
]
]
},
"81bb3dac-0cd3-4826-8436-573bc393f2c4": {
"main": [
[
{
"node": "3f5bb362-ca6a-4c1d-a959-9f194fcc7e99",
"type": "main",
"index": 0
}
]
]
},
"d4a5235a-57c0-42f6-9841-8f45d04dfe1c": {
"main": [
[
{
"node": "81bb3dac-0cd3-4826-8436-573bc393f2c4",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - Divers
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Oneclick AI Squad
@oneclick-aiThe AI Squad Initiative is a pioneering effort to build, automate and scale AI-powered workflows using n8n.io. Our mission is to help individuals and businesses integrate AI agents seamlessly into their daily operations from automating tasks and enhancing productivity to creating innovative, intelligent solutions. We design modular, reusable AI workflow templates that empower creators, developers and teams to supercharge their automation with minimal effort and maximum impact.
Partager ce workflow