
Implementation Guide: Trigger housekeeping workflows based on checkout times and room status
Step-by-step implementation guide for deploying AI to trigger housekeeping workflows based on checkout times and room status for Hospitality clients.
Hardware Procurement
Samsung Galaxy A25 5G Smartphone
$230 per unit (MSP cost) / $350 suggested resale
Dedicated mobile devices for housekeeping staff to receive real-time task assignments, update room status, and communicate with supervisors via the Flexkeeping or housekeeping app. One device per housekeeper plus two spares.
Samsung Galaxy Tab A9 Tablet
$180 per unit (MSP cost) / $280 suggested resale
Supervisor dashboard tablets mounted at housekeeping office and front desk for real-time room status board, task queue management, and shift overview. 8.7-inch display provides adequate screen real estate for the dashboard view.
OtterBox Commuter Series Case (Galaxy A25)
$30 per unit (MSP cost) / $55 suggested resale
Drop protection for housekeeping staff smartphones. Hotel housekeeping environments involve frequent device handling with wet hands, cart vibration, and potential drops on hard flooring.
OtterBox Defender Series Case (Galaxy Tab A9)
$40 per unit (MSP cost) / $70 suggested resale
Rugged protection for supervisor tablets including built-in screen protector and kickstand for desk/wall mounting.
Ubiquiti UniFi U6 Pro Access Point
$160 per unit (MSP cost) / $280 suggested resale
Wi-Fi 6 access points providing full-property wireless coverage for housekeeping devices, including hallways, back-of-house areas, and laundry. Coverage estimate: 1 AP per 8–12 rooms depending on building construction. Six APs cover a typical 50-room property.
Ubiquiti UniFi Switch 24 PoE
$450 per unit (MSP cost) / $680 suggested resale
24-port PoE switch to power all UniFi access points via single Ethernet cable runs, eliminating the need for individual power adapters at each AP location. Also provides wired connectivity for the Monnit IoT gateway if IoT sensors are deployed in Phase 2.
Ubiquiti UniFi Cloud Gateway Ultra
$129 per unit (MSP cost) / $220 suggested resale
Network gateway and UniFi controller appliance for managing the wireless network, creating VLAN segmentation between guest Wi-Fi, staff operations, and IoT networks, and providing firewall rules to keep the housekeeping system out of PCI DSS scope.
Software Procurement
Mews PMS (Starter or Pro Plan)
Starting ~€300/month (Starter); €500–€800/month (Pro) — client pays directly
Cloud-based Property Management System serving as the single source of truth for guest reservations, checkout events, and room status. Mews provides the webhook-based Connector API that fires real-time events when guests check out, which is the core trigger for the entire automation workflow.
Flexkeeping (via Mews)
Starting ~$1.70–$2.00/user/month (approximately $15–$20/month for 8–10 housekeeping staff)
Purpose-built housekeeping operations platform now natively integrated into Mews. Provides automated task scheduling, multilingual voice-to-task input, room attendant mobile app, supervisor dashboard, cleaning checklists, and performance analytics. Receives automated task assignments from the n8n workflow engine.
n8n Community Edition (Self-Hosted)
$0 software cost; MSP charges $1,500–$2,500 for deployment + $250/month for ongoing management
Workflow automation engine that receives PMS webhook events (checkout, room status change), applies business logic (priority rules, assignment routing, time-based delays), and triggers downstream actions (create Flexkeeping task, send push notification, update room status, log event). Self-hosted gives full data control and zero per-execution costs.
Hexnode UEM (Mobile Device Management)
$2.40/device/month (billed annually) — approximately $24/month for 10 devices
Mobile Device Management platform to manage all housekeeping smartphones and tablets remotely. Enforces app whitelisting (lock devices to Flexkeeping app + essential apps only), enables remote wipe if device is lost, pushes Wi-Fi profiles and VPN configs, and monitors device health.
Uptime Kuma (Self-Hosted Monitoring)
$0 software cost; deployed alongside n8n on the same VPS
Lightweight, self-hosted uptime monitoring dashboard that watches the health of the n8n instance, Mews API connectivity, Flexkeeping API endpoint, and network gateway. Sends alerts to MSP NOC via webhook/email/Telegram if any component goes down.
Hetzner Cloud VPS (CPX21)
~$8.50/month (3 vCPU, 4GB RAM, 80GB SSD) — MSP charges client $50/month as part of managed services
Cloud virtual private server hosting the self-hosted n8n instance, Uptime Kuma monitoring, and PostgreSQL database. Hetzner provides EU and US data centers with excellent price-to-performance ratio. For EU properties requiring GDPR-compliant data residency, select the Falkenstein or Helsinki datacenter.
Prerequisites
- Active Mews PMS subscription with API access enabled — contact Mews support to enable the Connector API and obtain an Access Token and Client Token for the target property
- Flexkeeping module activated within the Mews account — this may require upgrading to Mews Pro plan or requesting Flexkeeping add-on activation through the Mews account manager
- Stable internet connection at the property: minimum 25 Mbps dedicated for operations (separate from guest Wi-Fi SSID) with less than 50ms latency to cloud services
- Existing Ethernet cabling infrastructure capable of supporting PoE access points — verify cable runs from IDF/MDF closet to hallway AP mounting locations (Cat5e minimum, Cat6 recommended)
- Property floor plan with room numbering scheme matching the PMS room configuration — obtain from hotel general manager or facilities team
- Complete list of housekeeping staff names, roles (room attendant, supervisor, inspector), preferred language, and mobile phone numbers for notification setup
- Defined housekeeping workflow rules from hotel operations manager: standard checkout cleaning time estimate per room type, priority rules (VIP, early check-in, suite vs. standard), inspection requirements, and shift schedules
- Hotel IT contact or existing MSP credentials for network infrastructure access — need ability to configure VLANs, firewall rules, and DHCP reservations on the property's network equipment
- Domain name or subdomain allocated for the n8n instance (e.g., automation.hotelname.com) with DNS management access for SSL certificate provisioning
- PCI DSS scope documentation from the hotel's payment processor or acquiring bank — needed to verify that the housekeeping automation system is architecturally separated from cardholder data environment
- Written approval from hotel general manager and housekeeping director authorizing the project, including agreement on device policy (dedicated vs. BYOD), notification preferences, and go-live timeline
Installation Steps
Step 1: Network Infrastructure Assessment and VLAN Configuration
Before deploying any software, audit the property's existing network infrastructure. Document all switch ports, cable runs, and current AP locations. Configure three VLANs on the Ubiquiti UniFi Cloud Gateway Ultra and USW-24-PoE switch to segregate traffic: VLAN 10 (Staff Operations — housekeeping devices, PMS terminals), VLAN 20 (Guest Wi-Fi — isolated from operations), VLAN 30 (IoT/Sensors — future-proofing for Phase 2 occupancy sensors). This VLAN segmentation is critical for PCI DSS compliance as it keeps the housekeeping automation system out of the cardholder data environment scope.
VLAN Network Definitions
# Create rule: Block Guest-WiFi → Staff-Ops (deny all)
# Create rule: Block Guest-WiFi → IoT-Sensors (deny all)
# Create rule: Block IoT-Sensors → Staff-Ops (allow only MQTT/HTTPS to gateway)# SSID: [HotelName]-Staff | Network: Staff-Ops | Security: WPA3-Personal
# SSID: [HotelName]-Guest | Network: Guest-WiFi | Security: WPA2-PersonalIf the property already has a managed network from another vendor (Cisco Meraki, Aruba, etc.), work within that existing infrastructure rather than replacing it. The VLAN configuration concepts are the same — just adapt the commands to the existing platform. The key requirement is network segmentation between guest, staff, and IoT traffic.
Step 2: Install and Mount UniFi Access Points
Physically mount the 6 UniFi U6 Pro access points throughout the property to ensure complete Wi-Fi coverage for housekeeping staff devices. Priority coverage areas: all guest room hallways (staff need connectivity while updating room status from the hallway or room), back-of-house areas (housekeeping office, laundry room, linen storage), and the front desk area. Each AP covers approximately 1,500–2,500 sq ft depending on wall construction. Run Cat6 Ethernet from the USW-24-PoE switch to each AP location. APs are powered via PoE — no separate power outlet needed at the AP.
For properties with concrete/steel construction (common in older hotels), expect to need more APs than the 1-per-12-rooms estimate. Budget for 1–2 additional APs. If the property has an existing modern Wi-Fi system with adequate BOH coverage, skip this step and simply create the Staff-Ops SSID on the existing infrastructure.
Step 3: Provision Cloud VPS and Deploy n8n Automation Engine
Deploy a Hetzner Cloud VPS to host the n8n workflow automation engine and Uptime Kuma monitoring. This server will receive webhook events from Mews PMS, process business logic, and dispatch housekeeping tasks. Self-hosting n8n gives the MSP full control over the automation layer with zero per-execution costs, enabling unlimited webhook processing for even the busiest properties.
ssh root@[SERVER_IP]
apt update && apt upgrade -y
apt install -y curl git ufw fail2banufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp comment 'SSH'
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
ufw allow 5678/tcp comment 'n8n webhook port'
ufw enablecurl -fsSL https://get.docker.com | sh
apt install -y docker-compose-plugin
systemctl enable dockermkdir -p /opt/hotel-automation
cd /opt/hotel-automationcat > .env << 'EOF'
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
N8N_HOST=automation.hotelname.com
N8N_PORT=5678
N8N_PROTOCOL=https
POSTGRES_DB=n8n
POSTGRES_USER=n8n
POSTGRES_PASSWORD=$(openssl rand -hex 16)
POSTGRES_NON_ROOT_USER=n8n
POSTGRES_NON_ROOT_PASSWORD=$(openssl rand -hex 16)
WEBHOOK_URL=https://automation.hotelname.com
GENERIC_TIMEZONE=America/New_York
EOFdocker compose up -dapt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install caddycat > /etc/caddy/Caddyfile << 'EOF'
automation.hotelname.com {
reverse_proxy localhost:5678
encode gzip
header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options nosniff
X-Frame-Options DENY
}
}
monitor.hotelname.com {
reverse_proxy localhost:3001
encode gzip
}
EOF
systemctl restart caddyReplace 'automation.hotelname.com' and 'monitor.hotelname.com' with actual subdomains. Create DNS A records pointing to the VPS IP address BEFORE starting Caddy (it needs to validate the domain for the SSL certificate). Store all passwords from the .env file in your MSP password manager (e.g., IT Glue, Hudu). The N8N_ENCRYPTION_KEY is especially critical — if lost, all stored credentials in n8n workflows become unrecoverable.
Step 4: Configure Mews PMS API Access and Webhooks
Enable and configure the Mews Connector API to send real-time webhook notifications when checkout events and room status changes occur. This is the foundational integration point — the Mews webhook is the trigger that starts the entire housekeeping automation workflow. You will need to work with the hotel's Mews account administrator to generate API credentials.
curl -X POST 'https://api.mews.com/api/connector/v1/resources/getAll' \
-H 'Content-Type: application/json' \
-d '{
"ClientToken": "[YOUR_CLIENT_TOKEN]",
"AccessToken": "[YOUR_ACCESS_TOKEN]",
"Client": "MSP Housekeeping Automation",
"Extent": {
"Resources": true,
"ResourceCategories": true
}
}'curl -X POST 'https://api.mews.com/api/connector/v1/reservations/getAll' \
-H 'Content-Type: application/json' \
-d '{
"ClientToken": "[YOUR_CLIENT_TOKEN]",
"AccessToken": "[YOUR_ACCESS_TOKEN]",
"Client": "MSP Housekeeping Automation",
"StartUtc": "2025-01-01T00:00:00Z",
"EndUtc": "2025-01-02T00:00:00Z",
"States": ["Processed"]
}'Mews API credentials are property-specific. If managing multiple hotel properties under a single hotel group, each property will have its own AccessToken. Store tokens securely in n8n's credential manager (encrypted at rest using the N8N_ENCRYPTION_KEY). The Mews sandbox/demo environment is available for testing before connecting to production — request sandbox access from your Mews partner contact.
Step 5: Build the Core n8n Checkout-to-Housekeeping Workflow
Create the primary n8n workflow that receives Mews checkout webhook events, parses the event data, applies business logic (room type priority, VIP status, early check-in requests), creates housekeeping tasks in Flexkeeping, and sends push notifications to assigned staff. This is the heart of the automation. The full workflow JSON is provided in the custom_ai_components section — import it into n8n and customize the parameters.
The n8n workflow should be designed to be idempotent — if Mews sends the same webhook event twice (which can happen during network issues), the workflow should not create duplicate housekeeping tasks. The workflow includes a deduplication check using the Mews event ID stored in an internal n8n static data cache. See the full implementation in custom_ai_components.
Step 6: Configure Flexkeeping Housekeeping Module
Set up the Flexkeeping platform within Mews to define room types, cleaning task templates, default time estimates, staff assignments, and inspection workflows. Flexkeeping is now natively integrated with Mews, so most configuration happens within the Mews Operations interface. This step establishes the task templates that the n8n workflow will trigger.
Work closely with the hotel's Head Housekeeper or Executive Housekeeper during this step — they know the actual cleaning standards, time estimates, and floor assignments. The time estimates directly impact the automation's task routing logic (e.g., if a housekeeper already has 6 hours of tasks in queue, new tasks route to the next available attendant). Get these numbers right at setup to avoid constant override.
Step 7: Provision and Configure Housekeeping Mobile Devices
Set up all Samsung Galaxy A25 smartphones and Galaxy Tab A9 tablets with the Flexkeeping app, MDM enrollment, Wi-Fi profiles, and protective cases. Each device should be configured as a dedicated housekeeping device locked to approved applications only (kiosk mode) to prevent personal use and ensure the device is always ready for work.
IMPORTANT LABOR LAW NOTE: Do NOT enable GPS location tracking on housekeeping devices unless explicitly required and disclosed to staff in writing. In many US states, tracking employee location without consent creates legal liability. The kiosk mode restriction is acceptable as these are employer-owned devices. Keep 2 spare devices pre-configured in the housekeeping office for immediate swap if a device breaks or gets lost.
Step 8: Build the Room Status Progression Workflow
Create a secondary n8n workflow that manages the complete room status lifecycle: Occupied → Dirty (triggered by checkout) → Cleaning In Progress (triggered by attendant starting task) → Cleaned (attendant completion) → Inspected (supervisor approval) → Clean/Available (synced back to Mews). This workflow ensures the PMS always reflects accurate, real-time room status, enabling the front desk to sell rooms faster.
curl -X POST 'https://api.mews.com/api/connector/v1/resources/update' \
-H 'Content-Type: application/json' \
-d '{
"ClientToken": "[CLIENT_TOKEN]",
"AccessToken": "[ACCESS_TOKEN]",
"Client": "MSP Housekeeping Automation",
"ResourceUpdates": [
{
"ResourceId": "[ROOM_RESOURCE_ID]",
"State": {
"Value": "Dirty"
}
}
]
}'The Mews resource states may vary by property configuration. Common states are: Clean, Dirty, Inspected, OutOfService, OutOfOrder. Map these exactly to the hotel's existing workflow. Some properties skip the inspection step for standard rooms (only inspect suites/VIP) — make this configurable in the n8n workflow using an IF node that checks room category.
Step 9: Configure Notification and Escalation Rules
Set up the notification layer that ensures housekeeping staff, supervisors, and front desk are alerted at the right time through the right channel. Configure push notifications via Flexkeeping app, SMS fallback for critical alerts, and escalation rules for overdue tasks.
In n8n, create workflow: 'Escalation Monitor'. This workflow runs on a 15-minute cron schedule.
To: {{$json.supervisor_phone}}
Body: 'ALERT: Room {{$json.room_number}} checkout clean overdue by {{$json.minutes_overdue}} min. Please reassign or investigate.'Push notifications via the Flexkeeping app are the primary channel and should work 99% of the time if Wi-Fi coverage is solid. Twilio SMS is a $5–$10/month fallback for critical escalations only. Do NOT over-notify staff — alert fatigue is real and will cause housekeepers to ignore notifications. Work with the Head Housekeeper to set realistic SLA thresholds (45 min for standard rooms, 30 min for urgent/VIP).
Step 10: Deploy Uptime Kuma Monitoring and MSP Alerting
Configure the Uptime Kuma instance (deployed alongside n8n in Step 3) to monitor all critical system components. This gives the MSP's NOC visibility into the health of the entire housekeeping automation stack and enables proactive issue resolution before the hotel even notices a problem.
{"ClientToken":"[TOKEN]","AccessToken":"[TOKEN]","Client":"Health Check"}Uptime Kuma is lightweight (~150MB RAM) and runs perfectly alongside n8n on the same VPS. The monitoring cadence should be: 60-second checks for n8n health (most critical — if n8n is down, no housekeeping tasks get created), 5-minute checks for external API connectivity. Set the alert threshold to 3 consecutive failures before notifying to avoid false alarms from momentary network blips.
Step 11: End-to-End Testing and Parallel Run
Before going live property-wide, run a comprehensive testing phase on a single floor or wing of the hotel. This parallel run allows housekeeping to continue their existing process (radio/paper) while simultaneously receiving automated task assignments, validating that the automation matches their real workflow without disrupting operations.
Run the parallel test for a MINIMUM of 5 business days (ideally covering one weekend with higher checkout volume). Have the Head Housekeeper compare automated task creation against their manual tracking to identify any discrepancies. Common issues found during testing: timezone mismatches (UTC vs. local in Mews webhooks), room name vs. room number mapping errors, and task assignment to off-duty staff. Fix all issues before expanding beyond the test floor.
Step 12: Staff Training and Full Property Go-Live
Conduct in-person training sessions for all housekeeping staff, supervisors, and front desk personnel. Training should be hands-on with the actual devices and workflows — not slide presentations. After training, expand the automation from the test floor to the entire property and decommission the legacy manual process.
Session 1: Housekeeping Attendants (45 minutes)
- Receiving and viewing task assignments on the phone
- Starting a task (tap 'Begin' when entering the room)
- Following the digital checklist
- Taking photos for deficiency reporting (broken fixtures, stains, etc.)
- Marking task as 'Completed'
- What to do if phone loses Wi-Fi or battery dies (use spare device)
- Practice: Each attendant processes 3 mock tasks on their device
Session 2: Supervisors / Inspectors (45 minutes)
- Viewing the real-time room status dashboard on tablet
- Receiving and processing inspection tasks
- Approving or rejecting a room with notes
- Reassigning tasks when a housekeeper calls out
- Viewing shift performance metrics
- Managing the escalation notifications
- Practice: Process 5 inspections including 1 rejection scenario
Session 3: Front Desk (30 minutes)
- How room status now updates automatically in Mews
- No longer need to call housekeeping to check if a room is ready
- How to see estimated room readiness time for early check-in requests
- How to flag a room as 'Rush' in Mews for the automation to reprioritize
Go-Live Procedure
Schedule training sessions at shift start times (e.g., 7:30 AM for morning shift). Provide the training in the housekeepers' native language — Flexkeeping supports multilingual interfaces including Spanish, which is critical for many US hotel housekeeping teams. Create a laminated quick-reference card for each housekeeper with: How to start/complete a task, how to report a problem, who to call for tech support (MSP helpdesk number). Leave these cards in the housekeeping office.
Custom AI Components
Docker Compose Stack for n8n and Monitoring
Type: integration
Complete Docker Compose configuration file that deploys the n8n workflow automation engine, PostgreSQL database, and Uptime Kuma monitoring on a single VPS. This is the infrastructure foundation for all housekeeping automation workflows.
Implementation
# Place in /opt/hotel-automation/docker-compose.yml
version: '3.8'
volumes:
n8n_data:
postgres_data:
uptime_kuma_data:
services:
postgres:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
interval: 10s
timeout: 5s
retries: 5
networks:
- automation-net
n8n:
image: docker.n8n.io/n8nio/n8n:latest
restart: always
ports:
- '5678:5678'
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- N8N_HOST=${N8N_HOST}
- N8N_PORT=${N8N_PORT}
- N8N_PROTOCOL=${N8N_PROTOCOL}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- WEBHOOK_URL=${WEBHOOK_URL}
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- N8N_METRICS=true
- N8N_DIAGNOSTICS_ENABLED=false
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
networks:
- automation-net
uptime-kuma:
image: louislam/uptime-kuma:latest
restart: always
ports:
- '3001:3001'
volumes:
- uptime_kuma_data:/app/data
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- automation-net
networks:
automation-net:
driver: bridgeMews Checkout Webhook to Housekeeping Task Workflow
Type: workflow
Primary n8n workflow that receives Mews PMS webhook events for checkout and reservation updates, parses the event data, determines the appropriate housekeeping task type and priority, creates the task in Flexkeeping, and sends notifications. This is the core automation component of the entire solution.
Implementation
NODE 1: Webhook Trigger
- Type: Webhook
- Name: 'Mews Checkout Webhook'
- HTTP Method: POST
- Path: mews-checkout
- Authentication: Header Auth
- Header Name: x-webhook-secret
- Header Value: [generate and store a 32-char random string, share with Mews webhook config]
- Response Mode: When Last Node Finishes
- Response Code: 200
NODE 2: Parse Mews Event
- Type: Code (JavaScript)
- Name: 'Parse & Validate Event'
const body = $input.first().json;
// Mews webhook payload structure
const events = body.Events || [body];
const results = [];
for (const event of events) {
// Only process ServiceOrderUpdated events with state 'Processed' (checked out)
if (event.Type === 'ServiceOrderUpdated' || event.Discriminator === 'ServiceOrderUpdated') {
const reservationId = event.Value?.Id || event.Id;
results.push({
eventType: 'checkout',
reservationId: reservationId,
enterpriseId: event.EnterpriseId || body.EnterpriseId,
timestamp: new Date().toISOString(),
eventId: event.Id || `${reservationId}-${Date.now()}`
});
}
}
if (results.length === 0) {
// Not a checkout event — stop processing
return [];
}
return results.map(r => ({ json: r }));NODE 3: Deduplication Check
- Type: Code (JavaScript)
- Name: 'Deduplicate Events'
const staticData = $getWorkflowStaticData('global');
if (!staticData.processedEvents) {
staticData.processedEvents = {};
}
// Clean events older than 1 hour
const oneHourAgo = Date.now() - 3600000;
for (const [key, timestamp] of Object.entries(staticData.processedEvents)) {
if (timestamp < oneHourAgo) {
delete staticData.processedEvents[key];
}
}
const eventId = $input.first().json.eventId;
if (staticData.processedEvents[eventId]) {
// Already processed — skip
return [];
}
staticData.processedEvents[eventId] = Date.now();
return $input.all();NODE 4: Fetch Reservation Details from Mews
- Type: HTTP Request
- Name: 'Get Reservation Details'
- Method: POST
- URL: https://api.mews.com/api/connector/v1/reservations/getAll
- Authentication: Predefined Credential (Mews API - HTTP Header Auth)
{
"ClientToken": "{{$credentials.mewsClientToken}}",
"AccessToken": "{{$credentials.mewsAccessToken}}",
"Client": "MSP Housekeeping Automation",
"ReservationIds": ["{{$json.reservationId}}"],
"Extent": {
"Reservations": true,
"Resources": true,
"ResourceCategories": true,
"Customers": true
}
}NODE 5: Extract Room & Guest Info
- Type: Code (JavaScript)
- Name: 'Extract Room Info'
const data = $input.first().json;
const reservation = data.Reservations?.[0];
const resource = data.Resources?.[0];
const category = data.ResourceCategories?.[0];
const customer = data.Customers?.[0];
if (!reservation || !resource) {
throw new Error('Reservation or room not found in Mews response');
}
// Determine if VIP
const isVip = customer?.Classifications?.includes('Vip') ||
customer?.Classifications?.includes('LoyaltyProgram') || false;
// Determine if there's an incoming reservation today (express turnover needed)
const today = new Date().toISOString().split('T')[0];
const hasIncomingToday = false; // Will be enriched by next node
return [{
json: {
roomNumber: resource.Name || resource.Number,
roomId: resource.Id,
roomCategory: category?.Name || 'Standard',
roomCategoryId: category?.Id,
guestName: customer ? `${customer.FirstName || ''} ${customer.LastName || ''}`.trim() : 'Unknown',
isVip: isVip,
checkoutTime: reservation.EndUtc || new Date().toISOString(),
reservationId: reservation.Id,
enterpriseId: $input.first().json?.enterpriseId
}
}];NODE 6: Check for Incoming Reservation
- Type: HTTP Request
- Name: 'Check Incoming Reservations'
- Method: POST
- URL: https://api.mews.com/api/connector/v1/reservations/getAll
- Body: Query for reservations starting today assigned to the same room
- Use the roomId from previous node to filter
NODE 7: Determine Task Type & Priority
- Type: Code (JavaScript)
- Name: 'Assign Task Type'
const room = $('Extract Room Info').first().json;
const incomingRes = $input.first().json;
let hasIncomingToday = false;
if (incomingRes.Reservations && incomingRes.Reservations.length > 0) {
const today = new Date().toISOString().split('T')[0];
hasIncomingToday = incomingRes.Reservations.some(r =>
r.StartUtc && r.StartUtc.startsWith(today) && r.AssignedResourceId === room.roomId
);
}
let taskType, priority, taskTemplate, estimatedMinutes;
if (hasIncomingToday && room.isVip) {
taskType = 'vip_express_turnover';
priority = 'urgent';
taskTemplate = 'VIP Express Turnover';
estimatedMinutes = getBaseTime(room.roomCategory);
} else if (hasIncomingToday) {
taskType = 'express_turnover';
priority = 'urgent';
taskTemplate = 'Express Turnover';
estimatedMinutes = getBaseTime(room.roomCategory) - 10;
} else if (room.isVip) {
taskType = 'vip_checkout_clean';
priority = 'high';
taskTemplate = 'VIP Checkout Clean';
estimatedMinutes = getBaseTime(room.roomCategory) + 15;
} else {
taskType = 'checkout_clean';
priority = 'normal';
taskTemplate = 'Checkout Clean';
estimatedMinutes = getBaseTime(room.roomCategory);
}
function getBaseTime(category) {
const times = {
'Standard Room': 30,
'Standard': 30,
'Deluxe Room': 35,
'Deluxe': 35,
'Suite': 50,
'Junior Suite': 45,
'Accessible Room': 40,
'Accessible': 40
};
return times[category] || 30;
}
return [{
json: {
...room,
taskType,
priority,
taskTemplate,
estimatedMinutes,
hasIncomingToday
}
}];NODE 8: Create Flexkeeping Task
- Type: HTTP Request
- Name: 'Create Housekeeping Task'
- Method: POST
- URL: https://api.flexkeeping.com/v2/tasks (or via Mews native integration endpoint)
- Headers: x-api-key: {{$credentials.flexkeepingApiKey}}
{
"room": "{{$json.roomNumber}}",
"template": "{{$json.taskTemplate}}",
"priority": "{{$json.priority}}",
"estimated_duration": {{$json.estimatedMinutes}},
"notes": "Auto-assigned: {{$json.taskType}}{{$json.isVip ? ' | VIP GUEST' : ''}}{{$json.hasIncomingToday ? ' | INCOMING CHECK-IN TODAY' : ''}}",
"source": "automation",
"reservation_id": "{{$json.reservationId}}"
}NODE 9: Log Event
- Type: Code (JavaScript)
- Name: 'Log to Console'
console.log(`[HOUSEKEEPING] Task created: Room ${$json.roomNumber} | Type: ${$json.taskType} | Priority: ${$json.priority} | Est: ${$json.estimatedMinutes}min`);
return $input.all();Error Handling
Add an Error Trigger node connected to a notification node. Use: Error Trigger → HTTP Request (Slack/Teams webhook) or Email. This ensures the MSP is notified if any workflow execution fails.
Node Connections
Room Status Sync Workflow
Type: workflow
Secondary n8n workflow that listens for Flexkeeping task status updates (started, completed, inspected) and syncs the room status back to Mews PMS in real time, ensuring the front desk always sees accurate room availability.
Implementation
// Status map and event normalization
const event = $input.first().json;
const statusMap = {
'task.started': 'Dirty', // Housekeeper entered room, cleaning in progress
'task.completed': 'Inspected', // Housekeeper finished, awaiting inspection
'task.inspection_passed': 'Clean', // Supervisor approved, room is ready
'task.inspection_failed': 'Dirty' // Inspection failed, needs re-clean
};
const eventType = event.event || event.type;
const newMewsStatus = statusMap[eventType];
if (!newMewsStatus) {
// Unknown event type, skip
return [];
}
return [{
json: {
roomNumber: event.room || event.data?.room,
roomId: event.room_id || event.data?.room_id,
mewsResourceId: event.metadata?.mews_resource_id || null,
eventType: eventType,
newMewsStatus: newMewsStatus,
taskId: event.task_id || event.data?.id,
timestamp: new Date().toISOString(),
notes: event.data?.notes || ''
}
}];{
"ClientToken": "[CLIENT_TOKEN]",
"AccessToken": "[ACCESS_TOKEN]",
"Client": "MSP Housekeeping Automation",
"ResourceUpdates": [{
"ResourceId": "{{$json.mewsResourceId}}",
"State": { "Value": "{{$json.newMewsStatus}}" }
}]
}Connections: Webhook → Parse → IF(has resource ID) → [Yes: Update Mews] / [No: Lookup → Update Mews] → IF(inspection failed) → [Yes: Alert] / [No: Log]
Escalation Monitor Cron Workflow
Type: workflow
Scheduled n8n workflow that runs every 15 minutes to check for overdue housekeeping tasks and trigger escalation notifications to supervisors and management. Ensures no checkout clean falls through the cracks.
Implementation
// JavaScript code node logic for classifying tasks as warning (>45 min) or
// critical (>90 min)
const tasks = $input.first().json.data || $input.first().json;
const now = Date.now();
const WARN_THRESHOLD = 45 * 60 * 1000; // 45 minutes
const CRITICAL_THRESHOLD = 90 * 60 * 1000; // 90 minutes
const overdueTasks = [];
for (const task of tasks) {
if (!task.created_at) continue;
const taskAge = now - new Date(task.created_at).getTime();
if (taskAge > CRITICAL_THRESHOLD) {
overdueTasks.push({
...task,
escalationLevel: 'critical',
minutesOverdue: Math.round(taskAge / 60000)
});
} else if (taskAge > WARN_THRESHOLD) {
overdueTasks.push({
...task,
escalationLevel: 'warning',
minutesOverdue: Math.round(taskAge / 60000)
});
}
}
if (overdueTasks.length === 0) return [];
return overdueTasks.map(t => ({ json: t }));Daily Housekeeping Performance Report
Type: workflow
Automated daily report workflow that runs at end of shift (default 6 PM), aggregates the day's housekeeping metrics, and emails a summary to hotel management and the MSP account manager. Provides ongoing value demonstration and optimization data.
Implementation
const tasks = $('Fetch Tasks').first().json.data || [];
const checkouts = $('Fetch Checkouts').first().json.Reservations || [];
const totalCheckouts = checkouts.length;
const totalTasksCompleted = tasks.filter(t => t.status === 'completed').length;
const avgTurnaroundMin = tasks.reduce((sum, t) => {
if (t.completed_at && t.created_at) {
return sum + (new Date(t.completed_at) - new Date(t.created_at)) / 60000;
}
return sum;
}, 0) / (totalTasksCompleted || 1);
const inspectionFailures = tasks.filter(t => t.inspection_result === 'failed').length;
const vipTasks = tasks.filter(t => t.priority === 'high' || t.priority === 'urgent').length;
const escalations = tasks.filter(t => t.was_escalated).length;
// Per-housekeeper stats
const staffStats = {};
for (const task of tasks) {
const assignee = task.assignee_name || 'Unassigned';
if (!staffStats[assignee]) staffStats[assignee] = { completed: 0, totalMinutes: 0 };
staffStats[assignee].completed++;
if (task.completed_at && task.started_at) {
staffStats[assignee].totalMinutes += (new Date(task.completed_at) - new Date(task.started_at)) / 60000;
}
}
return [{ json: {
date: new Date().toISOString().split('T')[0],
totalCheckouts,
totalTasksCompleted,
avgTurnaroundMinutes: Math.round(avgTurnaroundMin),
inspectionFailures,
inspectionPassRate: totalTasksCompleted > 0 ? Math.round((1 - inspectionFailures/totalTasksCompleted) * 100) : 100,
vipTasksCompleted: vipTasks,
escalations,
staffStats
}}];const m = $input.first().json;
let staffRows = '';
for (const [name, stats] of Object.entries(m.staffStats)) {
const avgMin = stats.completed > 0 ? Math.round(stats.totalMinutes / stats.completed) : 0;
staffRows += `<tr><td>${name}</td><td>${stats.completed}</td><td>${avgMin} min</td></tr>`;
}
const html = `
<h2>Daily Housekeeping Report — ${m.date}</h2>
<table border='1' cellpadding='8' style='border-collapse:collapse'>
<tr><td><b>Total Checkouts</b></td><td>${m.totalCheckouts}</td></tr>
<tr><td><b>Tasks Completed</b></td><td>${m.totalTasksCompleted}</td></tr>
<tr><td><b>Avg Turnaround Time</b></td><td>${m.avgTurnaroundMinutes} minutes</td></tr>
<tr><td><b>Inspection Pass Rate</b></td><td>${m.inspectionPassRate}%</td></tr>
<tr><td><b>VIP Tasks</b></td><td>${m.vipTasksCompleted}</td></tr>
<tr><td><b>Escalations</b></td><td>${m.escalations}</td></tr>
</table>
<h3>Staff Performance</h3>
<table border='1' cellpadding='8' style='border-collapse:collapse'>
<tr><th>Staff Member</th><th>Rooms Cleaned</th><th>Avg Time</th></tr>
${staffRows}
</table>
<p><i>Generated automatically by the housekeeping automation system.</i></p>
`;
return [{ json: { html, subject: `Housekeeping Report — ${m.date} — ${m.totalTasksCompleted} rooms cleaned` }}];Testing & Validation
- NETWORK TEST: From a Samsung Galaxy A25 on the Staff-Ops SSID, verify Wi-Fi signal strength is ≥ -65 dBm on every floor, in every hallway, in the housekeeping office, and in the laundry room. Use the 'WiFi Analyzer' app to measure. Walk the entire property with a continuous ping to 8.8.8.8 — zero packet loss required.
- VLAN ISOLATION TEST: From a device on the Guest-WiFi VLAN (10.10.20.x), attempt to ping devices on Staff-Ops VLAN (10.10.10.x) and confirm that ALL pings are blocked. Repeat from IoT VLAN to Staff VLAN. This validates PCI DSS network segmentation.
- MEWS API CONNECTIVITY TEST: From the n8n VPS, execute the Mews 'configuration/get' API call and verify a 200 response with the correct Enterprise name. Then call 'resources/getAll' and verify the room count matches the physical property room inventory.
- WEBHOOK DELIVERY TEST: In the n8n workflow, activate the Mews Checkout webhook. In Mews Operations, process a test checkout for a test room. Within the n8n execution log, verify the webhook was received within 30 seconds. Check that the payload contains the correct ReservationId, ResourceId, and Enterprise context.
- DEDUPLICATION TEST: Copy the webhook payload from the previous test and manually POST it to the n8n webhook URL using curl or Postman. Verify that n8n processes it but does NOT create a duplicate housekeeping task (the deduplication code node should filter it out).
- TASK CREATION TEST: Process a standard checkout and verify a 'Checkout Clean' task appears in Flexkeeping within 60 seconds. Verify task properties: correct room number, 'Normal' priority, appropriate cleaning time estimate, and correct task template checklist.
- VIP TASK PRIORITY TEST: In Mews, flag a test guest as VIP (Classification: Vip). Process their checkout. Verify that the Flexkeeping task is created with 'High' priority and uses the 'VIP Checkout Clean' template with the extended checklist and +15 minute time estimate.
- EXPRESS TURNOVER TEST: Create two reservations for the same room: one checking out today and one checking in today. Process the checkout. Verify the automation creates an 'Express Turnover' task with 'Urgent' priority and reduced time estimate.
- ROOM STATUS LIFECYCLE TEST: Starting from a checkout event, follow the complete status cycle: (1) Checkout triggers Dirty status in Mews, (2) Housekeeper taps 'Start' in Flexkeeping → verify no status change visible or 'InProgress' note in Mews, (3) Housekeeper taps 'Complete' → verify Mews shows 'Inspected', (4) Supervisor taps 'Approve' → verify Mews shows 'Clean'. The front desk should be able to see the room as available.
- INSPECTION FAILURE TEST: After a housekeeper completes a task, have the supervisor reject the inspection with a note ('Bathroom mirror has streaks'). Verify the task is re-opened and re-assigned to the original housekeeper with the inspection notes visible on their device.
- ESCALATION TEST: Create a housekeeping task and intentionally leave it unstarted for 50 minutes. Verify the supervisor receives a push notification at the 45-minute mark. Leave it for another 50 minutes (total 95 min) and verify the operations manager receives an email alert and SMS is sent to the supervisor phone.
- BULK STRESS TEST: Process 10 checkouts within a 5-minute window (simulating a busy Sunday morning). Verify all 10 tasks are created in Flexkeeping with correct room numbers, no duplicates, and appropriate distribution across available housekeepers.
- DEVICE FAILURE RECOVERY TEST: While a housekeeper has active tasks, power off their device for 5 minutes. Power it back on and reconnect to Wi-Fi. Verify all pending notifications arrive and the task list is current. Also verify that the supervisor can reassign tasks from an unresponsive device to another housekeeper.
- MONITORING TEST: Stop the n8n Docker container (docker compose stop n8n). Verify Uptime Kuma detects the outage within 2 minutes and sends an alert to the MSP NOC email/Slack channel. Restart n8n and verify Uptime Kuma reports the recovery.
- DAILY REPORT TEST: Manually trigger the daily performance report workflow. Verify the email arrives at all configured recipients with accurate metrics matching the day's actual task completions. Check that staff names, room counts, and average times are correct.
Client Handoff
Conduct a formal 90-minute handoff meeting with the hotel General Manager, Director of Housekeeping, and Front Office Manager. Cover the following topics:
1. System Overview & Architecture (15 min)
Walk through the system diagram showing how checkout events flow from Mews → n8n → Flexkeeping → staff devices → back to Mews. Explain that this is a deterministic automation (rules-based, not AI guessing) so the hotel has full control over the logic.
2. Live Demonstration (20 min)
Process a real checkout during the meeting and show the task appearing on a housekeeper's device in real time. Walk through the complete lifecycle from checkout to room-ready-for-sale.
3. Role-Specific Training Recap (15 min)
Confirm each role understands their part:
- Housekeepers know how to use the Flexkeeping app
- Supervisors can manage the dashboard and handle escalations
- Front Desk understands the new real-time room status visibility
4. Escalation & Support Procedures (10 min)
Provide the MSP support contact information: phone number, email, and ticketing portal URL. Define response SLAs:
- P1 (system down, no tasks being created) = 30-minute response
- P2 (intermittent issues, some tasks delayed) = 2-hour response
- P3 (cosmetic issues, report formatting) = next business day
5. Documentation Handoff (10 min)
Leave behind a printed and digital copy of the following:
6. Success Metrics Review (10 min)
Establish baseline KPIs to track over the first 90 days:
- Average checkout-to-room-ready time (target: reduce by 15–30 min)
- Rooms cleaned per attendant per shift (target: increase by 10–20%)
- Inspection pass rate (target: >95%)
- Escalation rate (target: <5% of tasks)
- Guest complaints about room readiness (target: reduce by 30–45%)
7. Phase 2 Discussion (10 min)
Briefly introduce Phase 2 opportunities:
- IoT occupancy sensors for real-time vacancy detection ($100–$150/room)
- Predictive cleaning schedules based on historical patterns
- Energy management integration
- Guest messaging integration (notify guests when their room is ready for early check-in)
Maintenance
Monthly MSP Maintenance Tasks
- Review n8n workflow execution logs for errors or failed webhook deliveries (target: <1% failure rate)
- Verify Uptime Kuma monitoring shows >99.5% uptime for all components
- Check Mews API token expiration and rotate credentials if approaching expiry
- Review and update Flexkeeping staff profiles (add new hires, deactivate departed staff, update floor assignments)
- Push any pending Android OS and Flexkeeping app updates to housekeeping devices via Hexnode MDM
- Verify VPS disk usage is below 70% (PostgreSQL logs and n8n execution data can accumulate)
- Run monthly backup of n8n workflows and credentials
docker compose exec n8n n8n export:workflow --all --output=/backup/workflows.jsonQuarterly MSP Optimization Review ($500–$1,000/quarter)
- Analyze the daily performance reports for trends: Is average turnaround time improving? Are certain room types consistently slower?
- Review escalation patterns to identify systemic issues (e.g., one floor always has overdue tasks due to understaffing)
- Tune automation rules based on seasonal patterns (e.g., summer may need different time estimates due to heavier room usage)
- Meet with Head Housekeeper and GM to discuss pain points and optimization opportunities
- Update task templates if the hotel has changed cleaning standards or amenity packages
- Review Mews and Flexkeeping release notes for new features that could enhance the workflow
Annual Maintenance
- Full device hardware audit: replace any damaged phones/tablets, refresh battery-degraded devices
- Renew SSL certificates (Caddy auto-renews, but verify)
- Review and update network infrastructure firmware (UniFi APs, switch, gateway)
- Conduct PCI DSS scope review to confirm the housekeeping system remains out of cardholder data environment
- Re-negotiate software licensing costs (Mews, Hexnode) and evaluate alternatives if pricing has changed unfavorably
- Present annual ROI report to hotel ownership showing labor savings, turnaround improvements, and guest satisfaction impact
SLA Considerations
- P1 (System Down — no housekeeping tasks being generated): 30-minute MSP response, 2-hour resolution target
- P2 (Degraded — tasks delayed, some notifications failing): 2-hour MSP response, 8-hour resolution target
- P3 (Minor — report formatting, non-critical feature request): Next business day response
- After-hours P1 support should be included in the managed services agreement for 24/7 hotel operations
- Escalation path: Level 1 MSP helpdesk → Level 2 MSP engineer → Mews/Flexkeeping vendor support → Level 3 MSP architect
Disaster Recovery
- If the n8n VPS goes down: Flexkeeping still functions as a standalone app — supervisors can manually assign tasks until automation is restored
- n8n workflow JSON exports should be stored in the MSP's documentation system (IT Glue/Hudu) for rapid redeployment
- VPS snapshots should be scheduled weekly via Hetzner Cloud console (included in VPS cost)
- If Mews has an outage: Front desk can manually update room status in Flexkeeping; n8n will auto-process any queued webhooks when Mews recovers
Alternatives
PMS-Native Housekeeping Only (No Middleware)
Use the Mews + Flexkeeping native integration without deploying n8n middleware. Flexkeeping, now owned by Mews, can receive checkout events directly from the Mews platform without an external webhook processor. Housekeeping tasks are auto-created within the Mews-Flexkeeping ecosystem with built-in rules for priority and assignment.
- PROS: Simplest possible architecture — zero external components to manage, no VPS cost, no Docker maintenance, fastest deployment (1–2 weeks).
- CONS: Less customizable business logic (limited to Flexkeeping's built-in rules), no ability to integrate with non-Mews systems (e.g., external SMS, custom escalation, third-party reporting), vendor lock-in to Mews ecosystem.
- RECOMMEND WHEN: The hotel uses Mews as their PMS, has straightforward housekeeping workflows, and the MSP wants to minimize ongoing management overhead. This is the best option for properties under 30 rooms.
Cloudbeds PMS + Zapier Automation
For hotels using Cloudbeds instead of Mews, use Zapier as the middleware automation layer instead of self-hosted n8n. Cloudbeds has a Zapier integration that can trigger on reservation status changes. Zapier then creates tasks in a housekeeping app (or sends notifications via email/SMS/Slack). Use Cloudbeds' built-in housekeeping module for task management.
- PROS: No server to manage, Zapier is extremely user-friendly for non-technical hotel staff to modify, Cloudbeds pricing is very competitive for independent hotels ($108–$180/month).
- CONS: Zapier costs $19.99–$29.99/month and has execution limits (750–2,000 tasks/month on lower tiers — may not be enough for a busy 100+ room hotel processing 50+ checkouts/day), less granular control than n8n, ongoing per-task costs reduce margin.
- RECOMMEND WHEN: The hotel is already on Cloudbeds, has fewer than 75 rooms, and the MSP prefers a fully cloud-managed stack with no server administration.
Oracle OPERA Cloud + Optii Solutions (Enterprise)
For larger hotels or hotel chains using Oracle OPERA Cloud, deploy Optii Solutions as the dedicated AI-powered housekeeping optimization platform. Optii integrates with OPERA via the OHIP (Oracle Hospitality Integration Platform) and uses predictive algorithms to optimize room attendant routes, estimate cleaning times dynamically, and auto-assign tasks based on real-time workload balancing.
PROS: Most sophisticated automation — Optii's AI learns from historical patterns and dynamically adjusts (true predictive optimization, not just deterministic rules), deeply integrated with Oracle ecosystem, scales to hundreds/thousands of rooms across multi-property portfolios.
CONS: Significantly higher cost (OPERA Cloud starts at $230+/month, Optii pricing is custom/enterprise-tier), longer implementation timeline (8–12 weeks), requires OHIP developer certification for the MSP or a certified Oracle integration partner, overkill for properties under 100 rooms.
RECOMMEND WHEN: The client is a hotel group with 150+ room properties or multiple locations, already on Oracle OPERA, and has budget for enterprise-grade optimization.
Low-Cost DIY: Hotelogix + Google Sheets + SMS
For ultra-budget-conscious small properties (under 30 rooms), use Hotelogix as the PMS ($3.99/room/month), connect checkout events via Hotelogix API or Zapier to a Google Sheets log, and send SMS notifications to housekeepers via Twilio. Room status is tracked in the Google Sheet and manually updated. No dedicated housekeeping app or mobile devices needed — staff use personal phones.
Tradeoffs
- PROS: Lowest possible cost (PMS ~$120/month for 30 rooms, Zapier free tier or $19.99/month, Twilio ~$5/month for SMS, Google Sheets free)
- PROS: No hardware procurement needed
- PROS: Can be deployed in 1–2 days
- CONS: No real-time room status board
- CONS: No checklist enforcement
- CONS: No inspection workflow
- CONS: No performance metrics
- CONS: Relies on staff personal phones (BYOD challenges)
- CONS: Does not scale beyond 30 rooms
- CONS: Minimal MSP recurring revenue opportunity
RECOMMEND WHEN: The client is a very small independent hotel or bed-and-breakfast with extreme budget constraints, is currently using paper/whiteboard for housekeeping, and needs to take the first step toward automation.
IoT-Enhanced Automation with Monnit Sensors (Phase 2 Upgrade)
Add Monnit ALTA Wireless PIR motion sensors to each guest room to detect physical occupancy in real time. This enhances the checkout trigger by confirming the guest has actually left the room (not just processed a digital checkout from bed). The Monnit gateway feeds occupancy data to iMonnit cloud, which triggers an n8n webhook when a post-checkout room shows no motion for 10+ minutes, providing a 'confirmed vacant' signal before dispatching housekeeping.
Tradeoffs
- PROS: Eliminates the common problem of housekeepers arriving at rooms where guests haven't actually left yet (digital checkout ≠ physical departure)
- PROS: Enables 'knock-free' housekeeping deployment
- PROS: Creates additional MSP hardware revenue ($50–$80/sensor at cost, $120–$150 resale = 50–75% margin)
- PROS: Opens door to energy management upsell
- CONS: Additional hardware cost of $5,000–$10,000 for a 50-room property
- CONS: Sensor battery replacement every 3–5 years
- CONS: Requires additional n8n workflow complexity
- CONS: Adds IoT network management overhead
RECOMMEND WHEN: The hotel has demonstrated ROI from Phase 1 automation, reports frequent issues with premature housekeeping arrivals, and is interested in smart-building capabilities. Best deployed 3–6 months after Phase 1 go-live.
Want early access to the full toolkit?