How a stay runs itself
A booking arrives as a Smoobu (channel manager) webhook and upserts reservation state into DynamoDB. From
there everything is autonomous: two days before arrival the stack creates and fiscalises the invoice
(Cebelca), creates a time-bound Nuki smart-lock PIN and publishes it into the guest's welcome message; on
arrival day it arms the building intercom and polls for the guest's first keypad entry; guest ID scans are
filed to the Slovenian eTurizem registry over mTLS SOAP, and the monthly statutory return files itself.
Every schedule runs in a real timezone (Europe/Berlin), so DST is AWS's problem.
Reservations & smart lock
- Webhooks upsert reservation state; an hourly sync reconciles drift and cancellations.
- 6-digit Nuki PINs created for the arrival window, deleted after departure, and written into Smoobu placeholders so guests see them in confirmations.
- Nuki lock logs detect the first keypad entry and trigger check-in and cleaning flows — including a WhatsApp/email alert to the cleaning boss if no cleaner has entered by a set time before check-in.
Identity, billing & compliance
- Identity-scan polling with guest de-duplication in DynamoDB and Smoobu sync.
- Statutory reporting: check-in data is built into the required
knjigaGostovXML and submitted to eTurizem via the official client-cert SOAP API. - Invoicing via the Cebelca API; PDFs archived to S3; all tokens and the mTLS certificate live in Secrets Manager; structured logging in CloudWatch.
Engineering highlights
The interesting parts came from real incidents — each fix is now a permanent property of the system.
Trust-nothing device control
Nuki's API returns "accepted", not "applied" — and one dropped command locked a guest out for hours. The check-in monitor now reads state back from the device and re-asserts it every 5 minutes until the guest is detected. A second, independent check-in signal (the keypad code's usage counter) covers the cloud log silently dropping entries the lock itself recorded.
Atomic claims, not read-then-write
Every "send this once" decision — reminders, forecasts, the monthly statutory report, guest de-dup — is a DynamoDB conditional write, so a concurrent webhook and a scheduled run can never double-send or double-file. The statutory sequence number is an atomic counter.
Alert latches & reconciliation
Alerts are one-shot latches re-armed on recovery, with an all-clear sent on self-heal — a flapping device can't email every 5 minutes. And after a cancellation webhook silently stopped matching for weeks, the hourly sync now reconciles cancellations too — hardened so a failed fetch can never masquerade as "everything was cancelled".
Structural secret containment
The repo's early history contains an mTLS private key, so publication is guarded twice: a pre-push hook rejects any ref whose history ever touched key files, and a mirror-publisher script credential-sweeps the tree and pushes a single parentless squashed commit. The leak is impossible, not remembered.
Source code
The whole stack is public: one SAM template, eight Lambda handlers and one module per vendor integration. GitHub shows a single squashed snapshot rather than the commit history, because the early history carried an mTLS key. That is the publication guard described above doing its job.
Fougl/apartment
Serverless short-term rental automation on AWS SAM: Lambda, DynamoDB, S3, EventBridge and Secrets Manager. A booking webhook drives invoicing, smart-lock PINs, guest registration, cleaning checks, laundry forecasts and the monthly statutory report.
Start with aws-serverless/template.yaml (the whole infrastructure), src/handlers/checkin_monitor.py (arrival detection and lock control) and src/common/store.py (the DynamoDB state layer).
How to read it
Handlers stay about the workflow; each vendor’s API quirks live in one module under src/common/
(Smoobu, Nuki, Cebelca, eTurizem, CheckinScan). Every schedule is declared in a real timezone in the template,
and every “send this once” decision is a conditional write, so the code reads the way the incidents above are described.