Why We Let Customers Book Meeting Rooms in Plain WhatsApp
I built a complete room booking platform for Innovation Cafe: web portal, admin dashboard, payments, calendar sync. But 30-50% of repeat customers still preferred WhatsApp. So I added a bot that lets them book in plain language.
Stack
Why not just use the portal
Innovation Cafe is a sister company under the same ownership as Be Creative, where I work. We had four meeting and training rooms, a full web portal for booking, online payments through SkipCash, the whole setup. But 30-50% of our repeat customers still booked over WhatsApp. Not because they didn't know about the portal. Because WhatsApp was more convenient.
Qatar does business on WhatsApp. Telling those customers to use the portal instead would have meant losing bookings. But handling them manually wasn't scaling either.
The obvious answer is a WhatsApp bot. But most booking bots work like forms: one question, one answer, next question. Type something unexpected and they break. That's basically a worse version of the portal. If convenience was the reason people preferred WhatsApp, a rigid bot would defeat the point.
The parser: three layers
I built a parser that runs in three stages. Each stage exists because the others have gaps.
First, regex pre-processing. Before the AI sees anything, a rule-based parser scans for structured data: emails, times (12h and 24h), durations ("2 hours", "half day"), dates ("tomorrow", "next Monday"), and room names. This layer is fast, free, and can't hallucinate.
Second, GPT-4o-mini. The pre-processed context goes to the AI with a tight system prompt. The model extracts whatever the regex missed: names, company, intent. Temperature is 0.1 to keep output deterministic. The prompt includes rules to prevent the AI from guessing values that weren't stated or copying someone's name into the company field.
Third, post-processing validation. Whatever comes back from the AI gets checked against business rules. Past dates are rejected. Times outside 7:30 AM to 11:30 PM are dropped. Durations that would push past closing time are flagged. The user gets told what's wrong specifically, not a generic error.
Merge priority: regex results override AI output, which overrides previously collected session state. The most reliable source wins.
What this means in practice
A customer can open with "I'm Mohammed from Be Creative, ramees@bce.qa, training room tomorrow at 2pm for 3 hours" and the bot extracts all seven fields in one pass, confirms the details, and sends a payment link. No back-and-forth.
More often someone sends something partial: "I want to book the marina view room". The bot picks up the room, asks only for what's missing, and accepts answers in any format, including just replying "1" to pick from a list. Sessions persist in Supabase for 24 hours, so someone who goes quiet mid-booking picks up where they left off.
The bot recognizes room names, dates in natural phrasing, and names — all through the same parser pipeline.
The full platform
The WhatsApp bot is one channel into a larger system. There's a web booking portal where customers can pick a room, check availability, choose add-ons (parking, catering), and pay online. Both channels create bookings in the same Supabase backend with the same availability checks and the same payment flow through SkipCash.
Web booking flow: room selection, date and time, customer details, and payment
The admin dashboard is where the team manages everything: a bookings list with status management, room CRUD (capacity, pricing, active/popular flags), voucher codes with usage limits, add-on services, an analytics page with revenue charts and peak-time breakdowns, a Google Calendar view, and a full activity log of every action taken.
Reminders go out via both WhatsApp and email at 24 hours, 2 hours, and 15 minutes before the booking. Confirmed bookings sync to Google Calendar automatically. Customers can look up their own bookings via OTP verification without needing an account.
The bot also recognizes returning customers by phone number and pre-fills their name, email, and company from previous bookings.
Handling the edges
The AI would sometimes copy a person's name into the company field, especially for names that sound like a business. The post-processor catches this: if the company field matches the name, it gets nulled out.
When the AI is unavailable, the bot doesn't break. The regex output is used as a fallback, and the conversation continues with whatever was extracted.
Room slugs are hardcoded as a fallback alongside the live database list. If the DB call fails, the parser still has valid room data to match against.
Stack
Next.js 16 serverless on Vercel. WhatsApp Cloud API (Meta Direct) for messaging. Supabase for bookings, availability, and session state. Upstash Redis for OTP codes and rate limiting (5 attempts per 15 minutes, 3 sends per hour). SkipCash for payments. Google Calendar API for event sync. Resend for email confirmations.
The takeaway
The three-layer approach (regex first, AI second, validation third) works for any domain where you need to extract structured data from conversational input. Regex handles the predictable parts cheaply. AI handles the rest. Validation enforces business rules that neither should be trusted to know on their own.
The AI's job is extraction, not decision-making. It returns a JSON object with null for anything it doesn't see. Everything downstream works from that.