All work
Built
WhatsApp APIFastAPISheetsWebhooks

Books appointments over WhatsApp, keeps the schedule in Google Sheets the owner already uses, and can't double-book — even when two customers ask for the same slot at the same moment.

Built and verified · recorded run, offline test suite, and full source below.

The problem

Small businesses lose bookings in the gap between a customer's message and the owner's reply, and the calendar is often a paper notebook. The staff already know WhatsApp and they already know Google Sheets; the bot has to live inside those two things rather than replace them.

Pipeline architecture

A FastAPI service receives WhatsApp webhook events, runs the conversation logic (FAQ answers, slot offers, confirmation), and writes confirmed appointments straight to a Google Sheet the owner already uses. A reminder job reads the same Sheet the day before each appointment. The Telegram version runs on the identical backend with a different transport adapter.

Recorded run

Recorded live in a real terminal: the offline test suite, then ./scripts/demo.sh — a scripted booking conversation against the offline sheet backend, ending with the written rows.

pytest — 46 passed, including the 20-racer double-booking test
pytest — 46 passed, including the 20-racer double-booking test
Scripted conversation: slots offered, choice confirmed, booking reference issued
Scripted conversation: slots offered, choice confirmed, booking reference issued
The sheet after the run: one BOOKED row (BK-BEDA), everything else free
The sheet after the run: one BOOKED row (BK-BEDA), everything else free

Key decisions

One backend, two transports

Telegram and WhatsApp differ only in the adapter layer, so the demo runs on Telegram while the WhatsApp side goes through Meta's sandbox approval. The booking logic is written once.

The Sheet is the source of truth

Owners already live in Google Sheets. The bot writes rows they can read and edit, and picks its slots up from the same Sheet, so there is no second system to learn or keep in sync.

Sandbox-first proof

A real-phone recording through a temporary tunnel plus message logs is the proof, not a public business number. Nobody should hand out a live WhatsApp number to demonstrate a bot.

Guardrails

  • An atomic slot check prevents double-bookings.
  • The owner confirms the reminder message before it goes out.
  • Customer details stay in the owner's own Sheet and nowhere else.

Verification

Targets a booking captured in under a minute of conversation. Verified in the recorded run and the tests: a scripted booking completes in a few turns, exactly one of 20 concurrent bookings wins a contested slot, and reminders draft before sending by default.