Beds24 thread reconciliation
runBeds24MessageReconciliation in src/lib/beds24-reconciliation.ts.
Runs every 15 min, before the watchdog, to keep
beds24_messages.verified_in_thread_at + outbound_log.delivered_at
up to date.
Why this exists
Mailgun and Twilio both have webhooks that fire when delivery completes. Beds24 doesn’t. The closest signal is “is the message in the thread when you GET it later?”
Without reconciliation, every Beds24 thread message would stay in the watchdog’s “stale, no delivery confirmation” pile forever.
What it does
- Find unverified
beds24_messagesrows from the last 24h:SELECT id, booking_id, beds24_message_idFROM beds24_messagesWHERE verified_in_thread_at IS NULLAND sent_at >= ? - Group by
booking_id— one API call per booking covers all that booking’s pending verifications - For each booking, fetch
/bookings/messages?bookingId=Xvia Beds24 v2 API - For each unverified row, check if the message-id is in the returned thread
- On match:
- Set
verified_in_thread_aton thebeds24_messagesrow - Call
markOutboundDelivered(env, "beds24_message", id, now)to update theoutbound_logrow
- Set
Bounds + failure handling
- Only checks rows <24h old (older = no point re-fetching)
- One booking’s API failure doesn’t block others (try/catch per booking)
- If access token fetch fails, the whole sweep skips — try again next 15 min
Source
src/lib/beds24-reconciliation.tssrc/beds24/client.ts—getBookingMessagesGET helpermigrations/0024_delivery_observability.sql(createsbeds24_messages)- Tests:
test/lib/beds24-reconciliation.test.ts(7 cases)