This workflow corresponds to n8n.io template #17286 — we link there as the canonical source.
This workflow follows the Error Trigger → Google Sheets 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 →
{
"id": "CAEfQY4DET2tw9ou",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI Hotel Guest Experience & Stay Management System",
"tags": [],
"nodes": [
{
"id": "08537cdd-994b-456a-970f-e98124a4d84f",
"name": "\ud83d\udccc Overview \u2013 How This Workflow Works",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1488,
5360
],
"parameters": {
"width": 1052,
"height": 712,
"content": "## \ud83c\udfe8 StayOS AI \u2013 Hotel Guest Concierge Bot\n\n### How it works\nGuests message the hotel's Telegram bot and GPT-4o-mini classifies their request into one of five intents: cab booking, stay extension, complaint, checkout, or escalation. Each intent routes to a dedicated pipeline that reads the guest's booking from Google Sheets, takes the right action (assigns a driver, checks room availability, raises a maintenance ticket, or sends a folio), and notifies both the guest and the relevant staff. A separate daily schedule handles post-stay outreach \u2014 sending a feedback request, crediting loyalty points, and offering a rebooking discount to every guest who checked out that day.\n\n### Setup steps\n1. Connect your **Telegram Bot API** credential to all Telegram nodes.\n2. Connect **OpenAI API** to the Classify Intent node.\n3. Connect **Google Sheets OAuth2** and create a single sheet with four tabs: `Bookings`, `Rooms`, `Drivers`, `Tickets` (see the Credentials sticky for column names).\n4. Replace `YOUR_GOOGLE_SHEET_ID` in every Google Sheets node.\n5. Replace `REPLACE_WITH_STAFF_CHAT_ID` in the urgent staff alert node with your hotel operations team's Telegram chat ID.\n6. Activate the Telegram trigger and the daily schedule trigger."
},
"typeVersion": 1
},
{
"id": "49781274-40bf-4399-9cc5-5890530b4b7a",
"name": "Section \u2013 Guest Message Intake & AI Classification",
"type": "n8n-nodes-base.stickyNote",
"position": [
-368,
6240
],
"parameters": {
"color": 7,
"width": 1560,
"height": 680,
"content": "## \ud83d\udce9 Guest Message Intake & AI Classification\nReceives every Telegram message, extracts the chat ID and guest name, then sends the text to GPT-4o-mini to classify intent and extract key details (e.g. pickup time, issue description). The parsed result is used by all downstream branches."
},
"typeVersion": 1
},
{
"id": "b0a32df6-fc7b-4550-ac99-7340b4535c71",
"name": "Section \u2013 Cab Booking",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
4864
],
"parameters": {
"color": 7,
"width": 1060,
"height": 456,
"content": "## \ud83d\ude95 Cab Booking\nFinds an available driver in the Drivers sheet, limits to one result, logs the booking to the Bookings sheet, and sends the driver's name, car number, and phone to the guest on Telegram."
},
"typeVersion": 1
},
{
"id": "7d70ad83-8459-4fce-b84b-55123eb25228",
"name": "Section \u2013 Stay Extension",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
5424
],
"parameters": {
"color": 7,
"width": 1580,
"height": 712,
"content": "## \ud83d\udecf\ufe0f Stay Extension\nLooks up the guest's current booking, checks whether their room is available for an extra night, calculates the price, and sends a Razorpay payment link. If unavailable, a polite fallback message is sent and front desk is notified."
},
"typeVersion": 1
},
{
"id": "75268200-0453-4635-80a9-48f657e80347",
"name": "Section \u2013 Complaints & Maintenance",
"type": "n8n-nodes-base.stickyNote",
"position": [
1616,
6240
],
"parameters": {
"color": 7,
"width": 1400,
"height": 616,
"content": "## \ud83d\udd27 Complaints & Maintenance\nLogs a ticket to the Tickets sheet with the extracted issue, priority, and department. High-priority tickets (e.g. AC failure, water issue) trigger an urgent staff Telegram alert. Normal-priority issues go to the standard queue. The guest receives a confirmation either way."
},
"typeVersion": 1
},
{
"id": "fb9e500a-a581-496f-9d2c-0ce942a00e1e",
"name": "Section \u2013 Checkout",
"type": "n8n-nodes-base.stickyNote",
"position": [
1600,
6960
],
"parameters": {
"color": 7,
"width": 1284,
"height": 504,
"content": "## \ud83e\uddfe Checkout\nRetrieves the guest's folio from Google Sheets, sends a digital bill on Telegram, then marks the booking as `checked_out`. The post-stay daily schedule picks it up from there."
},
"typeVersion": 1
},
{
"id": "8ce325ee-ea24-4ee5-941f-f394035d247e",
"name": "Section \u2013 Escalation & Fallback",
"type": "n8n-nodes-base.stickyNote",
"position": [
1360,
7488
],
"parameters": {
"color": 7,
"width": 948,
"height": 892,
"content": "## \ud83c\udd98 Escalation & Fallback\nBilling disputes, damage claims, and anything the AI flags as needing a human are logged as escalated tickets and routed to staff via Telegram with full context \u2014 so the guest doesn't have to repeat themselves. The fallback branch handles unclear messages with a clarification prompt."
},
"typeVersion": 1
},
{
"id": "7528c8e4-c592-40ba-a78f-a657180cedc6",
"name": "Section \u2013 Post-Stay Outreach",
"type": "n8n-nodes-base.stickyNote",
"position": [
128,
7040
],
"parameters": {
"color": 7,
"width": 876,
"height": 476,
"content": "## \ud83d\udcec Post-Stay Outreach\nRuns daily. Finds all guests marked `checked_out` and sends a combined Telegram message: a 1\u20135 star feedback request, 100 loyalty points credited, and a 10% rebooking offer valid for 30 days. Adjust the schedule trigger time to your property's checkout window."
},
"typeVersion": 1
},
{
"id": "93371c17-61a4-47d8-b86a-15a90a1ddc06",
"name": "\ud83d\udd11 Credentials & Sheet Setup",
"type": "n8n-nodes-base.stickyNote",
"position": [
2384,
7680
],
"parameters": {
"color": 3,
"width": 540,
"height": 404,
"content": "## \ud83d\udd11 Credentials & Sheet Setup\n- **Telegram Bot API** \u2014 guest bot + staff alerts\n- **OpenAI API** \u2014 intent classification\n- **Google Sheets OAuth2** \u2014 PMS substitute\n\n`Bookings`: guest_id, name, room_no, checkin, checkout, status, folio_total, chat_id\n`Rooms`: room_no, type, available_from, available, extra_night_price\n`Drivers`: driver_name, car_no, phone, status\n`Tickets`: ticket_id, room_no, issue, priority, department, status, created_at"
},
"typeVersion": 1
},
{
"id": "b70bf3d4-6f8e-4c70-9c12-58e021091c8c",
"name": "Guest Message via Telegram",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-224,
6576
],
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"typeVersion": 1.1
},
{
"id": "9697b7d7-1865-4e8d-ad41-478ca4d9e6ca",
"name": "Prepare Guest Input",
"type": "n8n-nodes-base.set",
"position": [
-16,
6576
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1",
"name": "chat_id",
"type": "string",
"value": "={{ $json.message.chat.id }}"
},
{
"id": "a2",
"name": "guest_name",
"type": "string",
"value": "={{ $json.message.from.first_name }}"
},
{
"id": "a3",
"name": "message_text",
"type": "string",
"value": "={{ $json.message.text }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "1cc4033d-a327-4ad0-af32-0df281113d8d",
"name": "Classify Intent",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
208,
6576
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {},
"messages": {
"values": [
{
"role": "system",
"content": "You are an intent classifier for a hotel guest concierge system. Read the guest's message and respond with ONLY valid JSON, no markdown fences, no extra text, in this exact shape:\n{\n \"intent\": \"cab_booking | extend_stay | complaint | checkout | escalation | other\",\n \"priority\": \"low | medium | high\",\n \"department\": \"housekeeping | maintenance | front_desk | none\",\n \"details\": \"short extracted detail relevant to the request, e.g. pickup time, extension nights, issue description\"\n}\nClassify as 'escalation' for billing disputes, damage claims, safety issues, or anything you are not confident resolving automatically."
},
{
"content": "={{ $json.message_text }}"
}
]
}
},
"typeVersion": 1.8
},
{
"id": "015824fd-7858-4fc7-ae76-c6342fa3a7f1",
"name": "Parse Intent JSON",
"type": "n8n-nodes-base.code",
"position": [
576,
6576
],
"parameters": {
"jsCode": "// Parse the OpenAI structured output.\n// NOTE (known pitfall): the LangChain OpenAI node returns the reply at $json.message.content, NOT $json.content.\nconst raw = $input.first().json.message.content;\n\nlet parsed;\ntry {\n parsed = JSON.parse(raw);\n} catch (e) {\n parsed = { intent: 'other', priority: 'low', department: 'none', details: raw };\n}\n\nreturn [{\n json: {\n chat_id: $('Prepare Guest Input').first().json.chat_id,\n guest_name: $('Prepare Guest Input').first().json.guest_name,\n message_text: $('Prepare Guest Input').first().json.message_text,\n intent: parsed.intent || 'other',\n priority: parsed.priority || 'low',\n department: parsed.department || 'none',\n details: parsed.details || ''\n }\n}];"
},
"typeVersion": 2
},
{
"id": "bd1b2d34-d2bc-4ffd-a500-c764285c7444",
"name": "Route by Intent",
"type": "n8n-nodes-base.switch",
"position": [
784,
6512
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1c3c6c25-+1234567890dd0-73f27f001a25",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.intent }}",
"rightValue": "cab_booking"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "07e23ce5-4146-4706-a520-2f125e58173a",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.intent }}",
"rightValue": "extend_stay"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9642772d-5272-4e26-b5c4-4cfd5db477e7",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.intent }}",
"rightValue": "complaint"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d440ea33-d329-4df2-b1cd-9d579733cc2d",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.intent }}",
"rightValue": "checkout"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4c6bfaf1-52e4-4b98-a35b-4e15a9e15c12",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.intent }}",
"rightValue": "escalation"
}
]
}
}
]
},
"options": {
"fallbackOutput": "extra",
"renameFallbackOutput": "other"
}
},
"typeVersion": 3.2
},
{
"id": "2c7f3fdf-33fb-457e-8818-70255eda96fd",
"name": "Get Available Driver",
"type": "n8n-nodes-base.googleSheets",
"position": [
1360,
5040
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "available",
"lookupColumn": "status"
}
]
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Drivers"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "a2201458-1930-4f32-b967-9ccc7b6c3323",
"name": "Log Cab Booking",
"type": "n8n-nodes-base.googleSheets",
"position": [
1728,
5040
],
"parameters": {
"columns": {
"value": {
"chat_id": "={{ $('Route by Intent').item.json.chat_id }}",
"guest_name": "={{ $('Route by Intent').item.json.guest_name }}"
},
"schema": [
{
"id": "guest_name",
"type": "string",
"display": true,
"required": false,
"displayName": "guest_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "chat_id",
"type": "string",
"display": true,
"required": false,
"displayName": "chat_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "room_no",
"type": "string",
"display": true,
"required": false,
"displayName": "room_no",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "checkin",
"type": "string",
"display": true,
"required": false,
"displayName": "checkin",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "checkout",
"type": "string",
"display": true,
"required": false,
"displayName": "checkout",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "folio_total",
"type": "string",
"display": true,
"required": false,
"displayName": "folio_total",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Bookings"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "7e616c85-fc71-4113-a20d-854da0ec3ca1",
"name": "Send Cab Confirmation",
"type": "n8n-nodes-base.telegram",
"position": [
1968,
5040
],
"parameters": {
"text": "=\ud83d\ude95 You're all set!\n\nPickup: {{ $('Parse Intent JSON').item.json.details }}\nDriver: {{ $('Get Available Driver').item.json.driver_name }}\nCar No: {{ $('Get Available Driver').item.json.car_no }}\nDriver Phone: {{ $('Get Available Driver').item.json.phone }}\n\nWe'll notify you when the driver is on the way.",
"chatId": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "d9eba9fe-9769-47b5-a7bb-ff9a115c9e07",
"name": "Check Room Availability",
"type": "n8n-nodes-base.googleSheets",
"position": [
1760,
5728
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $('Get Guest Current Booking1').item.json.room_no }}",
"lookupColumn": "room_no"
}
]
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Rooms"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "31e3be1a-5d66-41a7-aa34-a2242edf789b",
"name": "Is Room Available?",
"type": "n8n-nodes-base.if",
"position": [
2128,
5728
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cca48638-b660-4c17-97af-626bdab64e57",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.available }}",
"rightValue": "yes"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a060f6ba-60f0-4edc-88cd-6c69f9275641",
"name": "Calculate Extension Price",
"type": "n8n-nodes-base.set",
"position": [
2352,
5648
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "p1",
"name": "extra_night_price",
"type": "string",
"value": "={{ $json.extra_night_price }}"
},
{
"id": "p2",
"name": "payment_link",
"type": "string",
"value": "=https://rzp.io/i/demo-extend-stay-{{ $('Parse Intent JSON').item.json.chat_id }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "d394b7dd-d4db-4939-9fea-397db2a4b591",
"name": "Send Price & Payment Link",
"type": "n8n-nodes-base.telegram",
"position": [
2560,
5648
],
"parameters": {
"text": "=\u2705 Good news \u2014 an extra night is available!\n\nRoom: {{ $('Is Room Available?').item.json.room_no }}\nExtension: {{ $('Parse Intent JSON').item.json.details }}\nPrice: \u20b9{{ $json.extra_night_price }}\n\nConfirm and pay here: {{ $json.payment_link }}",
"chatId": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "7b0aa1c5-01b5-4b11-b280-81a632e25614",
"name": "Send Room Not Available",
"type": "n8n-nodes-base.telegram",
"position": [
2368,
5856
],
"parameters": {
"text": "=We're sorry \u2014 Room {{ $json.room_no }} doesn't have availability for an extra night right now. Our front desk team will reach out with alternatives.",
"chatId": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "5dc831b8-3f70-4cad-a7ed-99d1bdf2bd89",
"name": "Create Maintenance Ticket",
"type": "n8n-nodes-base.googleSheets",
"position": [
1744,
6560
],
"parameters": {
"columns": {
"value": {
"issue": "={{ $('Parse Intent JSON').item.json.details }}",
"status": "open",
"priority": "={{ $('Parse Intent JSON').item.json.priority }}",
"created_at": "={{ $now.toISO() }}",
"department": "={{ $('Parse Intent JSON').item.json.department }}",
"guest_name": "={{ $('Parse Intent JSON').item.json.guest_name }}"
},
"schema": [
{
"id": "guest_name",
"type": "string",
"display": true,
"required": false,
"displayName": "guest_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "room_no",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "room_no",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "issue",
"type": "string",
"display": true,
"required": false,
"displayName": "issue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "priority",
"type": "string",
"display": true,
"required": false,
"displayName": "priority",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "department",
"type": "string",
"display": true,
"required": false,
"displayName": "department",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "created_at",
"type": "string",
"display": true,
"required": false,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Tickets"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "42c825a7-22e9-40ed-950d-93f5f2e91e1b",
"name": "Is High Priority?",
"type": "n8n-nodes-base.if",
"position": [
1968,
6560
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Parse Intent JSON').item.json.priority }}",
"rightValue": "high"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "7664b5f2-0d83-47e4-8fce-8dbc4b8bfce7",
"name": "Notify Staff \u2013 Urgent",
"type": "n8n-nodes-base.telegram",
"position": [
2272,
6464
],
"parameters": {
"text": "=\ud83d\udea8 URGENT ticket\n\nGuest: {{ $('Parse Intent JSON').item.json.guest_name }}\nIssue: {{ $('Parse Intent JSON').item.json.details }}\nDepartment: {{ $('Parse Intent JSON').item.json.department }}\n\nPlease action immediately \u2014 guest has been notified a team is on the way.",
"chatId": "REPLACE_WITH_STAFF_CHAT_ID",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "173f3df6-17e9-4264-bbd4-722d42e9981e",
"name": "Notify Staff \u2013 Normal Queue",
"type": "n8n-nodes-base.telegram",
"position": [
2272,
6656
],
"parameters": {
"text": "=\ud83d\udee0\ufe0f New ticket (normal queue)\n\nGuest: {{ $('Parse Intent JSON').item.json.guest_name }}\nIssue: {{ $('Parse Intent JSON').item.json.details }}\nDepartment: {{ $('Parse Intent JSON').item.json.department }}",
"chatId": "REPLACE_WITH_STAFF_CHAT_ID",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "77b1633f-f98e-409f-ac2a-82d384ea789c",
"name": "Confirm Ticket to Guest",
"type": "n8n-nodes-base.telegram",
"position": [
2544,
6560
],
"parameters": {
"text": "=Thanks for letting us know! We've logged your request ({{ $('Parse Intent JSON').item.json.details }}) and our team is on it.",
"chatId": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "807c8ce6-b235-40ff-88b3-f28143a79ac4",
"name": "Get Folio Charges",
"type": "n8n-nodes-base.googleSheets",
"position": [
1664,
7184
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $('Parse Intent JSON').item.json.guest_name }}",
"lookupColumn": "guest_name"
}
]
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Bookings"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "ffe960ca-20e1-451e-b5c7-1211806063eb",
"name": "Send Digital Bill",
"type": "n8n-nodes-base.telegram",
"position": [
2080,
7184
],
"parameters": {
"text": "=\ud83e\uddfe Your digital bill\n\nRoom: {{ $json.room_no }}\nTotal: \u20b9{{ $json.folio_total }}\n\nThank you for staying with us! Would you like a cab arranged for drop-off?",
"chatId": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "23cfda28-92da-469f-96e1-d14bc560a76a",
"name": "Update Booking \u2013 Checked Out",
"type": "n8n-nodes-base.googleSheets",
"position": [
2304,
7184
],
"parameters": {
"columns": {
"value": {
"status": "checked_out",
"guest_name": "={{ $('Parse Intent JSON').item.json.guest_name }}",
"row_number": 0
},
"schema": [
{
"id": "guest_name",
"type": "string",
"display": true,
"required": false,
"displayName": "guest_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "chat_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "chat_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "room_no",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "room_no",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "checkin",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "checkin",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "checkout",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "checkout",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "folio_total",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "folio_total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"guest_name"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Bookings"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "cc9d85a9-0c69-47b7-934e-248c95f9865d",
"name": "Log Escalation",
"type": "n8n-nodes-base.googleSheets",
"position": [
1520,
7824
],
"parameters": {
"columns": {
"value": {
"issue": "={{ $('Parse Intent JSON').item.json.details }}",
"status": "escalated_to_human",
"priority": "high",
"created_at": "={{ $now.toISO() }}",
"department": "front_desk",
"guest_name": "={{ $('Parse Intent JSON').item.json.guest_name }}"
},
"schema": [
{
"id": "guest_name",
"type": "string",
"display": true,
"required": false,
"displayName": "guest_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "room_no",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "room_no",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "issue",
"type": "string",
"display": true,
"required": false,
"displayName": "issue",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "priority",
"type": "string",
"display": true,
"required": false,
"displayName": "priority",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "department",
"type": "string",
"display": true,
"required": false,
"displayName": "department",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "created_at",
"type": "string",
"display": true,
"required": false,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Tickets"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "59946995-204b-476b-a8c9-3b149263e315",
"name": "Alert Human Staff",
"type": "n8n-nodes-base.telegram",
"position": [
1744,
7824
],
"parameters": {
"text": "=\ud83d\udc64 Human needed\n\nGuest: {{ $('Parse Intent JSON').item.json.guest_name }}\nFull message: {{ $('Parse Intent JSON').item.json.message_text }}\nAI read: {{ $('Parse Intent JSON').item.json.details }}\n\nThis needs a real person \u2014 full context attached, guest won't have to repeat themselves.",
"chatId": "REPLACE_WITH_STAFF_CHAT_ID",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "2084fafc-886a-4533-8d45-03fc3684ee03",
"name": "Confirm to Guest \u2013 Connecting",
"type": "n8n-nodes-base.telegram",
"position": [
1968,
7824
],
"parameters": {
"text": "Thanks for your patience \u2014 I'm connecting you with a member of our team who can help with this directly. They'll have full context, so you won't need to repeat anything.",
"chatId": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "f9865947-2630-4ec1-8222-a3691ad29ede",
"name": "Send Clarification Request",
"type": "n8n-nodes-base.telegram",
"position": [
1552,
8096
],
"parameters": {
"text": "I want to make sure I get this right \u2014 could you tell me a bit more about what you need? (e.g. cab booking, extending your stay, reporting an issue, or checkout)",
"chatId": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "652aacf2-06b1-49de-a241-6f9db898ab86",
"name": "Daily Post-Stay Check",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
224,
7296
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"typeVersion": 1.2
},
{
"id": "a3330bfa-a788-40e0-81fb-c2dc5d11128e",
"name": "Get Today's Checked-Out Guests",
"type": "n8n-nodes-base.googleSheets",
"position": [
448,
7296
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "checked_out",
"lookupColumn": "status"
}
]
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Bookings"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "2daff180-5003-488b-890e-f31feef60660",
"name": "Send Feedback, Loyalty & Rebooking Nudge",
"type": "n8n-nodes-base.telegram",
"position": [
672,
7296
],
"parameters": {
"text": "=Thanks for staying with us, {{ $json.guest_name }}! \u2b50 We'd love your feedback: could you rate your stay 1-5?\n\nAs a thank-you, 100 loyalty points have been credited to your account \u2014 and here's 10% off your next booking if you rebook within 30 days. Hope to host you again soon!",
"chatId": "={{ $json.chat_id }}",
"additionalFields": {}
},
"typeVersion": 1.2
},
{
"id": "ea14d31a-428d-4cfe-987f-cd27bd3c1181",
"name": "Keep Only 1 Driver1",
"type": "n8n-nodes-base.limit",
"position": [
1520,
5040
],
"parameters": {},
"typeVersion": 1
},
{
"id": "3b5f7a0f-601a-4d27-85c0-6cc9bed10881",
"name": "Get Guest Current Booking1",
"type": "n8n-nodes-base.googleSheets",
"position": [
1344,
5728
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $('Parse Intent JSON').item.json.chat_id }}",
"lookupColumn": "chat_id"
}
]
},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Bookings"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "7c588c86-a6a2-4502-aefe-dc6e2cb22888",
"name": "Keep Only 1 Booking1",
"type": "n8n-nodes-base.limit",
"position": [
1552,
5728
],
"parameters": {},
"typeVersion": 1
},
{
"id": "2d02169e-7a63-4ac4-a864-77c52da35a59",
"name": "Keep Only 1 Room Match1",
"type": "n8n-nodes-base.limit",
"position": [
1936,
5728
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bed38958-6784-4317-aaf7-7c55021ab99e",
"name": "Keep Only 1 Booking Record1",
"type": "n8n-nodes-base.limit",
"position": [
1872,
7184
],
"parameters": {},
"typeVersion": 1
},
{
"id": "f98866e8-8dce-4438-96a2-028332b8bba6",
"name": "Section \u2013 Error Handling",
"type": "n8n-nodes-base.stickyNote",
"position": [
256,
7648
],
"parameters": {
"color": 7,
"width": 748,
"height": 488,
"content": "## \u26a0\ufe0f Error Handling\nThree Slack alerts catch failures: a global error trigger covers the whole workflow, and the two AI nodes each have a dedicated error output wired to Slack. Update the channel ID and improve the alert message with context before going live."
},
"typeVersion": 1
},
{
"id": "d24f345b-709b-48e6-94e3-84f97b99f004",
"name": "On Workflow Error",
"type": "n8n-nodes-base.errorTrigger",
"position": [
416,
7888
],
"parameters": {},
"typeVersion": 1
},
{
"id": "bfdaa01b-3c25-401e-890e-f977edd85039",
"name": "Slack \u2013 Post Workflow Error Alert",
"type": "n8n-nodes-base.slack",
"position": [
688,
7888
],
"parameters": {
"text": "=\u26a0\ufe0f *DentalOS Workflow Error*\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}\n*Execution ID:* {{ $execution.id }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SLACK_CHANNEL_ID",
"cachedResultName": "your-alerts-channel"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"typeVersion": 2.3
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "78936100-0c39-4be6-9584-f77869f30a3a",
"nodeGroups": [],
"connections": {
"Log Escalation": {
"main": [
[
{
"node": "Alert Human Staff",
"type": "main",
"index": 0
}
]
]
},
"Classify Intent": {
"main": [
[
{
"node": "Parse Intent JSON",
"type": "main",
"index": 0
}
]
]
},
"Log Cab Booking": {
"main": [
[
{
"node": "Send Cab Confirmation",
"type": "main",
"index": 0
}
]
]
},
"Route by Intent": {
"main": [
[
{
"node": "Get Available Driver",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Guest Current Booking1",
"type": "main",
"index": 0
}
],
[
{
"node": "Create Maintenance Ticket",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Folio Charges",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Escalation",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Clarification Request",
"type": "main",
"index": 0
}
]
]
},
"Alert Human Staff": {
"main": [
[
{
"node": "Confirm to Guest \u2013 Connecting",
"type": "main",
"index": 0
}
]
]
},
"Get Folio Charges": {
"main": [
[
{
"node": "Keep Only 1 Booking Record1",
"type": "main",
"index": 0
}
]
]
},
"Is High Priority?": {
"main": [
[
{
"node": "Notify Staff \u2013 Urgent",
"type": "main",
"index": 0
}
],
[
{
"node": "Notify Staff \u2013 Normal Queue",
"type": "main",
"index": 0
}
]
]
},
"On Workflow Error": {
"main": [
[
{
"node": "Slack \u2013 Post Workflow Error Alert",
"type": "main",
"index": 0
}
]
]
},
"Parse Intent JSON": {
"main": [
[
{
"node": "Route by Intent",
"type": "main",
"index": 0
}
]
]
},
"Send Digital Bill": {
"main": [
[
{
"node": "Update Booking \u2013 Checked Out",
"type": "main",
"index": 0
}
]
]
},
"Is Room Available?": {
"main": [
[
{
"node": "Calculate Extension Price",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Room Not Available",
"type": "main",
"index": 0
}
]
]
},
"Keep Only 1 Driver1": {
"main": [
[
{
"node": "Log Cab Booking",
"type": "main",
"index": 0
}
]
]
},
"Prepare Guest Input": {
"main": [
[
{
"node": "Classify Intent",
"type": "main",
"index": 0
}
]
]
},
"Get Available Driver": {
"main": [
[
{
"node": "Keep Only 1 Driver1",
"type": "main",
"index": 0
}
]
]
},
"Keep Only 1 Booking1": {
"main": [
[
{
"node": "Check Room Availability",
"type": "main",
"index": 0
}
]
]
},
"Daily Post-Stay Check": {
"main": [
[
{
"node": "Get Today's Checked-Out Guests",
"type": "main",
"index": 0
}
]
]
},
"Check Room Availability": {
"main": [
[
{
"node": "Keep Only 1 Room Match1",
"type": "main",
"index": 0
}
]
]
},
"Keep Only 1 Room Match1": {
"main": [
[
{
"node": "Is Room Available?",
"type": "main",
"index": 0
}
]
]
},
"Notify Staff \u2013 Urgent": {
"main": [
[
{
"node": "Confirm Ticket to Guest",
"type": "main",
"index": 0
}
]
]
},
"Calculate Extension Price": {
"main": [
[
{
"node": "Send Price & Payment Link",
"type": "main",
"index": 0
}
]
]
},
"Create Maintenance Ticket": {
"main": [
[
{
"node": "Is High Priority?",
"type": "main",
"index": 0
}
]
]
},
"Get Guest Current Booking1": {
"main": [
[
{
"node": "Keep Only 1 Booking1",
"type": "main",
"index": 0
}
]
]
},
"Guest Message via Telegram": {
"main": [
[
{
"node": "Prepare Guest Input",
"type": "main",
"index": 0
}
]
]
},
"Keep Only 1 Booking Record1": {
"main": [
[
{
"node": "Send Digital Bill",
"type": "main",
"index": 0
}
]
]
},
"Notify Staff \u2013 Normal Queue": {
"main": [
[
{
"node": "Confirm Ticket to Guest",
"type": "main",
"index": 0
}
]
]
},
"Get Today's Checked-Out Guests": {
"main": [
[
{
"node": "Send Feedback, Loyalty & Rebooking Nudge",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs a Telegram concierge for hotel guests, uses OpenAI (gpt-4o-mini) to classify requests, and updates Google Sheets to manage drivers, room extensions, maintenance tickets, and checkout folios, while sending guest and staff notifications in Telegram and posting…
Source: https://n8n.io/workflows/17286/ — 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 handles customer order complaints submitted via Telegram by looking up order details in Google Sheets, using OpenAI to classify message sentiment, and routing each case to auto-approval,
This workflow handles COD order confirmation and abandoned-cart recovery by combining webhooks, Google Sheets logging, OpenAI message generation, and Telegram messaging with inline buttons, plus Slack
This workflow runs a Telegram restaurant ordering flow that uses OpenAI to parse orders and suggest an upsell, sends a Razorpay payment link, confirms paid orders via a Razorpay webhook, logs orders a
This workflow handles dental clinic patient conversations in Telegram, using OpenAI to answer treatment-plan and general questions, logging bookings and payment plans in Google Sheets, sending automat
This workflow listens for Telegram bot messages, uses OpenAI (gpt-4o-mini) to detect language and classify intent, then routes requests to either lead qualification, EMI calculation, or support handli