How I automate a booking business end to end

I automate booking businesses end to end: normalised intake, radius matching, WhatsApp broadcasts, payment and consent gates. Here is the whole method.

8 min read

I am about to give away the full method I used to automate a booking business end to end, the same pattern that runs the Vets at Home platform. Every step, in order, nothing held back.

Why would I do that? Because the steps are not the moat. The moat is doing the work. You can hand someone the complete recipe for a booking platform and the gap between reading it and running it is hundreds of decisions, a few thousand lines of code, and the stamina to keep going when the third edge case of the day turns out to contradict the first two. People ask me why I publish this stuff. Simple: people won't do it. The ones who would are exactly the ones I want to talk to anyway.

A booking business, for the purpose of this guide, is any business where a customer requests a visit or an appointment, someone from a pool of providers has to accept it, money and paperwork have to clear before the work happens, and there is follow-up afterwards. Home-visit vets, obviously. Also surveyors, engineers, physios, photographers, mobile mechanics, anyone who dispatches skilled people to postcodes.

Here is the whole machine.

Step 1: Normalise intake from every source

Bookings arrive from everywhere: the website form, paid ads landing pages, the phone, sometimes a partner referral. The first automation is boring and it is the most important one: every single booking, whatever the source, lands in one place in one shape.

That means a single jobs table with a machine-readable source field on every row. Not "Website" typed by a human, but website_form, paid_ads_form, values that code can branch on without anyone remembering the spelling. Everything downstream keys off this record: attribution, routing, follow-up tone, reporting. If you skip this step, every later automation needs a special case per source, and special cases breed until the system is unmaintainable.

While you are at it, model the business as it actually is. A generic CRM gives you one flat "contacts" list and asks you to bend vets, pet owners, crematoria and practices into it. Refuse. On the Vets at Home build the schema has vets, pet owners, crematoria, practices, jobs and referrals as first-class entities, each with their own fields and relationships. The flat-contacts compromise is where most booking automations go to die, because every workflow ends up parsing tags to work out what kind of thing it is talking to.

Step 2: Geocode once, match by radius

Each provider gets a home postcode, stored coordinates and a travel radius. Geocode each postcode exactly once, when it is first stored, and keep the coordinates. In the UK, postcodes.io does this for free.

When a booking arrives, geocode the customer's postcode the same way, then run a haversine distance query in the database against every provider's stored coordinates and radius. That one query returns the providers genuinely in range. No mapping API in the matching path, no per-job cost, answers in milliseconds.

Straight-line distance is fine for matching. You only need real driving distance later, when a job is actually allocated and you are working out mileage. For that I use Google's Distance Matrix exactly once per postcode pair, then cache the result forever. The system I inherited recalculated driving distance every single time a job was viewed, which was quietly costing about £40 a month for the same answers over and over. Postcodes do not move. Cache them.

Now tell the in-range providers about the job. WhatsApp, because field providers live on their phones and email gets read tomorrow.

The detail that makes this work: each message carries a durable personal login link, a token tied to that provider, not a password and not a one-time code. The vet taps the link on their phone and lands directly in their portal, on that job, already authenticated. No login screen has ever survived contact with someone standing in a car park between visits. Remove it.

Two rules for the broadcast itself. First, show limited details only: the area, the timing, the nature of the job. Full customer details unlock only after allocation, which protects the customer's privacy and stops anyone going around the system. Second, the provider records availability with one tap, and the office allocates with one click. Broadcast wide, allocate deliberately.

Keep the radius, the escalation rules and the tiers as data in the database, not as logic buried in code. When the business wants to widen a radius or add a tier, that should be an edit, not a release.

This is the step that makes the automation safe rather than just fast. Nothing progresses until the gates clear.

The moment a booking is allocated, the system issues a payment link and a consent form. Confirmations, scheduling messages and provider notifications all key off both gates: paid AND consented. Not one. Both. For an end-of-life vet visit the consent is a legal and ethical requirement; for your business it might be a signed quote, a deposit, terms acceptance. Same gate, different paperwork.

Why be strict about it? Because the failure mode of a fast system is confidently doing the wrong thing at scale. A human coordinator instinctively pauses when payment has not landed. Your automation must encode that pause explicitly or it will cheerfully dispatch a provider to a job that nobody has paid for, and it will do it at three in the morning at no marginal cost.

Cancellation is part of the same gate logic. When a booking cancels, every downstream field, notification flag and scheduled message must reset, and refresh again if payment and consent arrive on a rebook. I have fixed this bug in a live system. Build the reset in from day one.

Step 5: Escalate when nobody accepts

Sometimes the broadcast goes out and nothing comes back. The system has to notice silence, because silence is exactly what a busy office misses.

Set a timer on every broadcast. When it expires with no acceptance, escalate through tiers: widen the radius, then ring the next circle of providers, then surface it to a human with the full history attached. Each escalation is recorded on the job, which tier fired and why, so you can see afterwards which postcodes are chronically underserved. That record is not bureaucracy, it is your recruitment map: it tells you where to find your next provider before customers start telling you with one-star reviews.

The principle: the system handles the happy path end to end and hands humans the exceptions with full context. Automation that hides its failures is worse than no automation.

Step 6: Aftercare and reviews on a schedule

The job is done. Most businesses stop automating here, which is backwards, because this is the cheapest part to automate and the part humans most reliably forget.

Aftercare messages, follow-up paperwork, and the review or feedback request all go out on a schedule triggered by job completion, with timing and tone matched to the context. For a bereavement business that means restrained, carefully spaced messages and a feedback request that arrives when it is decent for it to arrive, not forty minutes after the visit. Whatever your business, the sequencing logic is identical even though the words and the gaps are completely different.

Where this goes wrong

I have watched versions of this fail, including bits of my own early attempts. The repeat offenders:

Improving while migrating. If you are replacing an existing process, replicate the live behaviour exactly first, then improve. On the Vets at Home build we ported 25 automation workflows from a no-code tool into typed code with 248 automated tests, like-for-like against live behaviour, before changing anything. Twice I was tempted to "fix" something mid-port. Both times the old behaviour turned out to exist for a reason that was not written down anywhere.

Cutting over all at once. Build the new system in parallel, touch nothing live, and flip one workflow at a time, verifying each before the next. Big-bang cutovers fail at 11pm on a Friday. Always.

Trusting tests over reality. Tests prove your code does what you think. Only running against real data proves what you think is right. Verify each workflow against live behaviour before you trust it.

Forgetting the unhappy paths. Cancellations, amendments, the customer who pays but never consents, the provider who accepts then withdraws. The happy path is a third of the build. Budget accordingly.

Letting per-use costs hide. Anything that calls a paid API per view or per message will quietly compound. Cache aggressively and put a cost line against every external call before launch.

What it actually takes

Honest accounting: this is weeks of focused work, not a weekend. You need working knowledge of a web framework, a relational database, a workflow engine that can run scheduled and event-driven jobs, the WhatsApp Business API, and a payment provider. More than any of that, you need the stamina to chase down the dozens of edge cases that only surface when real bookings hit the system, and the discipline to keep replicating boring old behaviour when every instinct says improve it. None of it is beyond a competent developer who will actually sit down and grind through it. That is the whole point of giving it away: the recipe is free, the cooking is the work.

If you would rather I just did it, book a consultation and bring me your booking process.

Frequently asked questions

What does it mean to automate a booking business end to end?
It means every stage runs as one connected system: bookings from every source land in one normalised record, providers are matched by travel radius, jobs are broadcast over WhatsApp with personal login links, payment and consent gate progression, unanswered broadcasts escalate through tiers, and aftercare and review requests fire on a schedule after completion. Humans handle exceptions and allocation decisions; the system handles everything repetitive.
How does radius matching work for a home-visit booking system?
Each provider stores a home postcode, coordinates and a travel radius, geocoded once using a free service such as postcodes.io. When a booking arrives, its postcode is geocoded the same way and a haversine distance query in the database returns every provider in range. Straight-line distance is enough for matching; real driving distance is only fetched at allocation, once per postcode pair, then cached permanently.
Why should payment and consent gate a booking before the visit happens?
Because the failure mode of a fast automated system is confidently doing the wrong thing at scale. A human coordinator pauses instinctively when payment has not landed; automation must encode that pause explicitly. Issuing a payment link and consent form at allocation, and keying all confirmations and provider notifications off both clearing, stops the system dispatching providers to jobs nobody has paid for or agreed to.
Should I rebuild my booking automations or replicate them first?
Replicate first, improve second. When the Vets at Home platform was rebuilt, 25 live workflows were ported from a no-code tool into typed code with 248 automated tests, matched like-for-like against live behaviour before anything changed. Old behaviour often exists for reasons nobody wrote down, and a parallel build with one-workflow-at-a-time cutover means nothing breaks mid-migration.

One useful AI idea a week

Proper Productivity: each issue covers one thing we have tested on a real business. No hype, no filler.

One email a week. Unsubscribe whenever.