Your ticket lands on WhatsApp with a one-line ask. Attendees reply YES, CANCEL, or RESCHEDULE — no app, no login, no form. The bot updates their registration, replies with a warm confirmation, and frees the seat for the waitlist. The keyword bot that clears your no-show list in the channel Indian attendees actually read.
rsvp_status = confirmed, timestamps it, sends a warm confirmation reply.rsvp_status = cancelled. Waitlist auto-promote picks it up on the next tick.GET /webhooks/whatsapp?hub.verify_token=…. We only echo the challenge back if the token matches a tenant's whatsapp_verify_token.X-Hub-Signature-256. We HMAC the raw body with the tenant's whatsapp_app_secret and compare with hash_equals. Mismatched messages get logged and dropped.phone_number_id in the payload — one unique index on the tenants table means we can't accidentally route to two.Every event organiser in India has this problem. Registrations open, 400 people sign up in a week, everyone gets an email confirmation. Comes event day, 260 show up. That's a 35% no-show rate on a "confirmed" list — and the wait list attendees who would have shown up got nothing because the seat was technically taken.
The gap is that email confirmation is not the same thing as an RSVP. Nobody scrolls a mailbox at 9pm the night before an event. What they DO read is WhatsApp. So we made the ticket ask the question there. One line. YES or CANCEL. If they cancel, the waitlist tick picks it up within minutes and someone else gets the seat and the same nudge.
We built it around the two things Indian attendees actually do: reply in Hinglish and skip filling forms. Keyword match handles the first. Zero forms handles the second.
X-Hub-Signature-256 HMAC of the raw body computed with your app secret — we verify it server-side before touching the payload./webhooks/whatsapp routes to the right tenant by phone-number-id from the inbound payload. Each tenant stores its own credentials.