Send Check-in
The Send Check-in workflow is the single most important guest-facing flow in the platform: it's the moment we deliver the door PIN and arrival instructions to the guest, ~24h before they arrive. If it fails silently, the guest arrives without a PIN and the operator has to scramble.
The happy path
- A reservation is created.
- The Generate access code task fires (cron-scheduled, typically ~24h before check-in).
- The Nuki API issues a PIN; the platform writes it to the canonical guest row (
guests.nukiAccessCode). - The Send Check-in task fires (cron-scheduled, typically a few minutes after step 3 completes — configurable in the task template).
- The task's action sends a WhatsApp message to the guest containing:
- The full address
- Arrival window (e.g. "After 15:00, before midnight")
- The PIN code (
{{guest.nukiAccessCode}}) - Late-night arrival instructions if applicable - Parking and WiFi info if part of the template - The task auto-resolves when the message send succeeds.
Operators don't normally see any UI for this — it just happens. They see the task in Pulse if they want to verify it's queued.
When something goes wrong
Symptom: "Auto-resolve was BLOCKED because the condition is not met: reservation.nukiAccessCode is_not_null"
You'll see this on the Pulse dashboard or as a WhatsApp notification to you.
What it means: the Send Check-in task tried to fire, but its precondition ("the reservation must have a Nuki PIN") evaluated to false.
Why this can happen even though the PIN exists:
Behind the scenes the condition checker reads from guests.nukiAccessCode. For one reservation there can be multiple guest rows (Hospitable webhook may re-sync the booking and create duplicates). Only the latest row typically has the PIN. The checker's JOIN to guests is now disambiguated to prefer rows with non-empty access codes — fixed in #260 commit baa96065. Before that fix, the JOIN could pick a row without the PIN, blocking the task.
What to do today:
- Open the property's Smart Lock page. Look at Active codes for this reservation.
- If a PIN exists — the data is fine; the task evaluation just used the wrong row. Manually trigger Send Check-in from the reservation detail page (see Manual trigger below).
- If no PIN exists — the Generate access code task didn't run or failed. Trigger it manually first, then Send Check-in.
Symptom: PIN is generated but the message didn't send
Open the reservation detail page and look at the task list:
- Generate access code → status
done✓ - Send Check-in → status
not_done✗
Common causes:
- The 24h WhatsApp window is closed — Meta only allows free-text outbound to numbers that messaged us in the last 24h. Outside that window we have to use an approved template. If the guest hasn't yet messaged, we fall back to the
task_resolvedtemplate. See Communications → WhatsApp Bot. - The guest's phone number is invalid — check the reservation detail page. Phone numbers from Booking.com sometimes arrive without the country prefix.
- An auto-resolve condition unrelated to PIN blocked the task — e.g. "guest must have acknowledged previous message first". Check the task's checklist items.
Symptom: silent skip — the task is marked done but no message was sent
This was a bug class fixed in #180. The auto-resolve flow used to mark the task done even when sendReply was internally skipped. After #180, a skipped send marks the task failed with a reason — surfaced in the Pulse Activity Log.
If you still suspect a silent skip, check Admin → Activity Log for the task ID — it should now log the skip reason.
Manual Send Check-in
To override the cron-fired version (e.g. because the auto-fire was blocked or you want to send earlier):
- Open the reservation detail page.
- Find the Send Check-in task in the task list.
- Click the task to open it.
- Click Send now (or, on the Pulse card, the Send Check-in primary action button).
The task fires immediately. If the WhatsApp window is closed it falls back to the template path.
When the operator gets pinged about a blocked Send Check-in
The platform's auto-resolve evaluator, when it can't fire a task, sends a WhatsApp notification to the operator at ~08:00 local time (when the morning cron runs). The message names the task, the property, the guest, and the failing condition.
Example operator-facing message:
Task 216874 (Castle&River Luxe-Vydrica) Auto-resolve was BLOCKED because the condition is not met: reservation.nukiAccessCode is_not_null. Please resolve this task manually.
When you get one:
- Open the named task — note the reservation and property.
- Verify the PIN exists on the Smart Lock page.
- If it does → manually trigger Send Check-in.
- If it doesn't → manually trigger Generate access code first, then Send Check-in.
Related issues
- #260 — canonical guest-row selection (May 2026 fix).
- #231 — silent-success in actionExecutor (May 2026 predecessor).
- #237 — UI dedup for duplicate guest rows in 2N QR codes panel.
- #180 — silent-skip semantics for auto-resolve.