AutomationFlowsEmail & Gmail › Send Smart Lock Pins for Apaleo Reservations with Seam, Gmail, and Twilio

Send Smart Lock Pins for Apaleo Reservations with Seam, Gmail, and Twilio

Byiamvaar @iamvaar on n8n.io

This workflow reacts to Apaleo reservation unit assignments, generates a time-bound smart lock access code via Seam, saves it back to the Apaleo reservation comment, and notifies the guest using Gmail and Twilio, while also rotating an Apaleo bearer token on a 58‑minute…

Cron / scheduled trigger★★★★☆ complexity17 nodesHTTP Request@Apaleo/N8N Nodes Apaleo OfficialGmailTwilio
Email & Gmail Trigger: Cron / scheduled Nodes: 17 Complexity: ★★★★☆ Added:

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

This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "axsgV44TTWkeJWh9",
  "name": "smart lock pin gen",
  "tags": [],
  "nodes": [
    {
      "id": "1f499e33-d10c-45f8-b47d-9972e711cb0d",
      "name": "Create Access Code on Seam",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4352,
        2384
      ],
      "parameters": {
        "url": "https://connect.getseam.com/access_codes/create",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"device_id\": \"{{ $json.device_id }}\",\n  \"name\": \"Reservation: {{ $json.reservation_id }}\",\n  \"starts_at\": \"{{ $json.starts_at }}\",\n  \"ends_at\": \"{{ $json.ends_at }}\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.4
    },
    {
      "id": "12e8a9a8-4ad9-4caa-b957-db64642eafe3",
      "name": "Retrieve Reservation Details",
      "type": "@apaleo/n8n-nodes-apaleo-official.apaleo",
      "position": [
        3888,
        2384
      ],
      "parameters": {
        "group": "booking-v1",
        "resource": "Reservation",
        "operation": "BookingReservationsByIdGet",
        "requestOptions": {},
        "additionalFields": {
          "expand": []
        },
        "BookingReservationsByIdGet_id": "={{ $json.data.entityId }}"
      },
      "credentials": {
        "apaleoOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6bbe5676-cdac-404a-8e7b-7fd56b0f8e59",
      "name": "Link Room to Lock Code",
      "type": "n8n-nodes-base.code",
      "position": [
        4128,
        2384
      ],
      "parameters": {
        "jsCode": "// 1. Fetch the booking data from your Apaleo node\nconst apaleo = $('Retrieve Reservation Details').item.json;\n\n// 2. Construct the matching string (e.g., \"BER-VWD 1.001\")\nconst targetUnitId = `${apaleo.unit.id} ${apaleo.unit.name}`;\n\n// 3. Your master list of database/mock mappings\nconst rooms = [\n  { \"unit_id\": \"BER-VWD 1.001\", \"locker_id\": \"782885f3-fe44-4147-88b0-765da2df3d5c\" }, // these are sample unit id's and lockerid's replace these with actual unit id & name and seam.co device id\n  { \"unit_id\": \"BER-VWD 1.002\", \"locker_id\": \"d9d4b4c3-bc3d-4f86-a371-339a2dc545fd\" }// these are sample unit id's and lockerid's replace these with actual unit id & name and seam.co device id\n];\n\n// 4. Find the matching room\nconst match = rooms.find(room => room.unit_id === targetUnitId);\n\n// 5. Output a single clean object containing everything Seam needs\nreturn [{\n  json: {\n    device_id: match ? match.locker_id : \"NOT_FOUND\",\n    reservation_id: apaleo.id,\n    starts_at: apaleo.arrival,\n    ends_at: apaleo.departure\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "474cc176-9d0e-494c-8707-e7f5fa7da48a",
      "name": "Add PIN to Reservation Note",
      "type": "@apaleo/n8n-nodes-apaleo-official.apaleo",
      "position": [
        4592,
        2384
      ],
      "parameters": {
        "group": "booking-v1",
        "resource": "Reservation",
        "operation": "BookingReservationsByIdPatch",
        "requestOptions": {},
        "BookingReservationsByIdPatch_id": "={{ $('Link Room to Lock Code').item.json.reservation_id }}",
        "BookingReservationsByIdPatch_body": "=[\n  {\n    \"op\": \"replace\",\n    \"path\": \"/comment\",\n    \"value\": \"\ud83d\udd11 Smart Lock PIN: {{ $json.access_code.code }} (Generated Automatically)\"\n  }\n]"
      },
      "credentials": {
        "apaleoOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a5a96e04-8620-4d0a-9c30-16f3feee557e",
      "name": "Retrieve Customer Contact Info",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4832,
        2384
      ],
      "parameters": {
        "url": "=https://api.apaleo.com/booking/v1/reservations/{{ $('On Reservation Unit Assignment').item.json.data.entityId }}?expand=primaryGuest,booker,assignedUnits",
        "options": {
          "redirect": {
            "redirect": {}
          },
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        },
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "headerParameters": {
          "parameters": []
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "3fe362b5-ddbd-4285-a5d9-4d00b365f310",
      "name": "Deliver PIN via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        5200,
        2240
      ],
      "parameters": {
        "sendTo": "={{ $json.body.primaryGuest.email }}",
        "message": "=<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n</head>\n<body style=\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; color: #334155; margin: 0; padding: 40px 20px; background-color: #F8FAFC;\">\n    \n    <!-- Main Card -->\n    <div style=\"max-width: 480px; margin: 0 auto; background: #FFFFFF; padding: 40px; border-radius: 16px; box-shadow: 0 4px 24px rgba(15, 23, 42, 0.06);\">\n        \n        <!-- Header -->\n        <div style=\"text-align: center; margin-bottom: 35px;\">\n            <h2 style=\"color: #0F172A; margin: 0; font-size: 20px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;\">Blankarray Hotels</h2>\n        </div>\n\n        <p style=\"margin-top: 0; font-weight: 600; color: #0F172A;\">Dear {{ $json.body.booker.firstName }} {{ $json.body.booker.lastName }},</p>\n        <p style=\"color: #64748B;\">Your room is ready. For a seamless, contactless check-in, please use your secure smart lock PIN below.</p>\n        \n        <!-- High-Contrast PIN Box (The Two-Color Pop) -->\n        <div style=\"background-color: #0F172A; border-radius: 12px; padding: 35px 20px; text-align: center; margin: 40px 0;\">\n            <p style=\"margin: 0; color: #94A3B8; font-size: 12px; text-transform: uppercase; letter-spacing: 1.5px; font-weight: 600;\">Secure Access PIN</p>\n            \n            <!-- Dynamic Placeholder -->\n            <h1 style=\"margin: 15px 0 0 0; color: #FFFFFF; letter-spacing: 10px; font-size: 46px; font-weight: 700; line-height: 1;\">{{ $json.body.comment.match(/\\d{6}/)?.[0] }}</h1>\n        </div>\n\n        <p style=\"color: #64748B; font-size: 14px; text-align: center;\">This PIN is active for the exact duration of your reservation.</p>\n        \n        <!-- Footer -->\n        <div style=\"margin-top: 45px; border-top: 1px solid #E2E8F0; padding-top: 25px; text-align: center;\">\n            <p style=\"margin: 0; color: #0F172A; font-weight: 600; font-size: 14px;\">The Blankarray Team</p>\n        </div>\n\n    </div>\n</body>\n</html>",
        "options": {
          "appendAttribution": false
        },
        "subject": "Here is your Smart Lock Pin for your reserved room"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "185a9d2f-a08c-4316-aba8-7c0cc5e19829",
      "name": "Send PIN using Twilio",
      "type": "n8n-nodes-base.twilio",
      "position": [
        5200,
        2496
      ],
      "parameters": {
        "to": "={{ $json.body.booker.phone }}",
        "from": "+1234567890",
        "message": "=Hi {{ $json.body.booker.firstName }} {{ $json.body.booker.lastName }},\nThanks for your recent reservation. And here is the pin for accesing the Unit.\n{{ $json.body.comment }}\n\nThanks,\nBlankarray",
        "options": {}
      },
      "credentials": {
        "twilioApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2eb62f2a-0331-4a83-960d-07f3089972cb",
      "name": "When Triggered Every 58 Minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        3664,
        3040
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 58
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "8e3be041-f2c4-4d00-9531-6cf79a2d50f5",
      "name": "Obtain Apaleo Access Token",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3888,
        3040
      ],
      "parameters": {
        "url": "https://identity.apaleo.com/connect/token",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "grant_type",
              "value": "client_credentials"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Basic enter-your-dev-app-basic-api-here"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "ef98925c-8df9-4a50-b8ef-2622d90c7a53",
      "name": "Update API Credential Information",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4128,
        3040
      ],
      "parameters": {
        "url": "https://enter-your-n8n-instance-url-here/api/v1/credentials/enter-your-credential-id-here",
        "method": "PATCH",
        "options": {},
        "jsonBody": "={\n  \"data\": {\n    \"token\": \"{{ $json.access_token }}\",\n    \"allowedHttpRequestDomains\": \"all\"\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "n8nApi"
      },
      "credentials": {
        "n8nApi": {
          "name": "<your credential>"
        },
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "994a01de-2d91-41ed-a263-62d3563e363d",
      "name": "On Reservation Unit Assignment",
      "type": "@apaleo/n8n-nodes-apaleo-official.apaleoTrigger",
      "position": [
        3648,
        2384
      ],
      "parameters": {
        "events": "reservation/unit-assigned",
        "options": {
          "ignoreAccountLevelFilter": true
        }
      },
      "credentials": {
        "apaleoOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "typeVersion": 1
    },
    {
      "id": "ede08129-a1b1-4f8a-8924-2d2cf0e765f3",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3040,
        2032
      ],
      "parameters": {
        "width": 480,
        "height": 896,
        "content": "## smart lock pin gen\n\n### How it works\n\nThis workflow generates and distributes smart lock PINs when a reservation unit is assigned in Apaleo. It fetches reservation details, maps the assigned room to a Seam lock, creates an access code, stores the PIN back on the reservation, and sends it to the guest by email and SMS. A separate scheduled branch refreshes the Apaleo API token used by the workflow.\n\n### Setup steps\n\n- Configure the Apaleo trigger and Apaleo nodes with the correct property/account access and event subscription for reservation unit assignment.\n- Set up the Seam HTTP request with a valid Seam API key and confirm the access-code endpoint, device IDs, and payload fields are correct.\n- Update the room-to-lock mapping in the code node so every Apaleo room or unit ID maps to the correct Seam lock ID.\n- Configure Gmail credentials for sending guest emails and Twilio credentials for sending SMS messages.\n- Configure the customer contact-data request with the correct Apaleo API authorization and reservation/contact endpoint fields.\n- For the scheduled credential refresh branch, set the Apaleo OAuth client credentials, replace the placeholder n8n instance URL, and ensure the n8n API credential patch request targets the correct credential.\n\n### Customization\n\nAdjust the PIN validity window, naming convention, and access-code payload sent to Seam. Customize the reservation note format plus the Gmail and Twilio message templates to match guest-facing wording and check-in instructions."
      },
      "typeVersion": 1
    },
    {
      "id": "e52ce377-f51c-414e-9942-2b1fe32c6d3e",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3600,
        2224
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 320,
        "content": "## Reservation event lookup\n\nStarts when Apaleo reports that a unit has been assigned, then retrieves the reservation details needed for downstream PIN creation."
      },
      "typeVersion": 1
    },
    {
      "id": "178bb93e-f25d-40ed-991b-7c59b10c3cbf",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4080,
        2208
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 336,
        "content": "## Map and create PIN\n\nMaps the assigned room or unit from the reservation to the corresponding smart lock ID, then calls Seam to create an access code for that lock."
      },
      "typeVersion": 1
    },
    {
      "id": "a0f0e546-33c5-47a9-bbae-7da2cd99a43c",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4544,
        2224
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 320,
        "content": "## Save PIN and contact\n\nAppends the generated PIN to the reservation note in Apaleo, then fetches the guest contact data required for notifications."
      },
      "typeVersion": 1
    },
    {
      "id": "718d4355-acb7-420b-b415-2e587c21cefb",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5152,
        2032
      ],
      "parameters": {
        "color": 7,
        "height": 624,
        "content": "## Notify guest with PIN\n\nSends the smart lock PIN to the guest through two parallel communication channels: email via Gmail and SMS via Twilio."
      },
      "typeVersion": 1
    },
    {
      "id": "449f1ba9-d29b-44b3-845d-3b587ac790cf",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3616,
        2912
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 304,
        "content": "## Refresh Apaleo credentials\n\nRuns separately on a 58-minute schedule to fetch a fresh Apaleo access token and patch the configured n8n API credential with the updated token."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "97a183a8-ebb0-47fc-9274-7429b25d61d1",
  "connections": {
    "Link Room to Lock Code": {
      "main": [
        [
          {
            "node": "Create Access Code on Seam",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Access Code on Seam": {
      "main": [
        [
          {
            "node": "Add PIN to Reservation Note",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Obtain Apaleo Access Token": {
      "main": [
        [
          {
            "node": "Update API Credential Information",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add PIN to Reservation Note": {
      "main": [
        [
          {
            "node": "Retrieve Customer Contact Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Reservation Details": {
      "main": [
        [
          {
            "node": "Link Room to Lock Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On Reservation Unit Assignment": {
      "main": [
        [
          {
            "node": "Retrieve Reservation Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Customer Contact Info": {
      "main": [
        [
          {
            "node": "Deliver PIN via Gmail",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send PIN using Twilio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Triggered Every 58 Minutes": {
      "main": [
        [
          {
            "node": "Obtain Apaleo Access Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

This workflow reacts to Apaleo reservation unit assignments, generates a time-bound smart lock access code via Seam, saves it back to the Apaleo reservation comment, and notifies the guest using Gmail and Twilio, while also rotating an Apaleo bearer token on a 58‑minute…

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

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

This workflow monitors Bitcoin (BTC) and Ethereum (ETH) prices in real-time using CoinGecko’s public API. It sends you an instant alert when a price crosses a custom threshold or when the 24-hour chan

HTTP Request, Gmail, Twilio
Email & Gmail

YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.

Gmail, Google Drive, Google Sheets +1
Email & Gmail

14310 Send Overdue Invoice Payment Reminders With Ifirma Gmail Postgrid And Slack. Uses httpRequest, stopAndError, slack, gmail. Scheduled trigger; 53 nodes.

HTTP Request, Stop And Error, Slack +1
Email & Gmail

Addendo — Blog Automatico Don Jacinto Nahual. Uses httpRequest, redis, github, gmail. Scheduled trigger; 51 nodes.

HTTP Request, Redis, GitHub +1
Email & Gmail

Addendo — Blog Automatico Don Jacinto Nahual. Uses httpRequest, redis, github, gmail. Scheduled trigger; 51 nodes.

HTTP Request, Redis, GitHub +1