Online Booking Portal
The public, customer-facing "book online" side of Appointments. A member of the public — someone who is not logged into ERPat — finds your business, picks a service, chooses a provider and a free time, and confirms an appointment from any phone or browser. When no times are open, the same page lets them join the waitlist; after a completed visit, a separate link lets them leave a review.
What the public portal is
The portal is a set of login-free web pages served under /appointments/book. It only appears and works when two conditions are met: the Appointments module is enabled for the business, and the business has ticked "Enable public booking page" in Settings. Miss either and every public page returns a 404 — a deliberate way to hide a portal that isn't turned on.
The public pages at a glance
/appointments/book — a multi-tenant landing page that lists every business accepting online bookings as clickable cards ("Book now"). Only populated when multi-tenancy is enabled; in a single-tenant install it looks empty, but the direct company URL still works.
/appointments/book/{company-slug} — the main flow for one business: three stacked steps that reveal progressively (pick service → provider + date + time → your details → confirm), plus the waitlist call-to-action.
/appointments/book/success/{uuid} — a standalone confirmation page (also the target of the confirmation email's "Manage" link). No login and no tenant lookup needed.
/appointments/review/{company-slug}/{uuid} — linked from the review-request email. Shows the star form only when the visit is Completed and not yet reviewed.
How the right business is resolved
Every public request carries the company slug in the URL. Behind the scenes the portal performs tenant resolution: it looks up the slug in the main directory, verifies the business is active, and switches to that business's data so the services, availability, and booking all operate within the correct company. A slug that is unknown, inactive, or points to a business with public booking switched off simply 404s.
The customer booking journey (SOP)
The company booking page reveals three steps one at a time — each step only appears once the previous choice is made. Here is the happy path exactly as a customer experiences it.
SOP · Book an appointment online (happy path)
Actor: Customer (public, not logged in)
-
Open the business's booking link
Go to /appointments/book/{company-slug}, or click the business card on the directory. A teal hero banner shows the company logo (if set), the company name, and a "Book an Appointment" subtitle.
-
Step 1 — Select a service
Under "Select a service", click the desired service card. Services are grouped by category; anything uncategorized falls under "Other Services". Each card shows the service name, its duration in minutes, and its price. Only Active and Public services appear. Selecting a card reveals Step 2 and loads the providers who can perform it.
-
Step 2 — Choose a provider and date
The Provider dropdown defaults to "Any available provider". Leave it there to maximise the times shown (the system pools every capable staff member), or pick a specific person. Then choose a Date in the native date picker.
-
Pick a time slot
Available times load as clickable buttons. While they load you may see "Loading available times…"; before choosing a date the hint reads "Select a date to see available times." Each button shows a friendly 12-hour label (e.g. 2:30 PM). Clicking one selects it (it turns solid teal) and reveals Step 3. Changing the provider or date re-queries the times.
-
Step 3 — Enter your details
Fill Customer Name, Phone, and Email (all required); Notes is optional. The email must be valid — it is where the confirmation goes and how your account is found or created.
-
Click "Confirm Booking"
The teal Confirm Booking button re-checks that the slot is still free, then creates the appointment. On success an inline panel shows a large green check with "Appointment Confirmed" and "A confirmation has been sent to your email.", and the customer is sent to the success page.
-
Keep the confirmation email & reference
A Confirmed booking triggers a confirmation email to the customer (and a "new appointment" notice to staff). The success page shows a Reference code (the appointment UUID) in monospace — worth keeping; it is also embedded in the email links.
What happens the moment a customer confirms
When Confirm Booking succeeds, the portal:
- Re-resolves the business, re-verifies the service is active and public, and confirms the chosen staff really is assigned to that service.
- Re-checks the exact slot is still free inside a locked transaction (see the race check) so two customers can't grab the same time.
- Finds or creates the customer by email, then writes the appointment (status Confirmed, source online) and its service line.
- Emails a confirmation to the customer and a "new appointment" notice to the assigned staff (falling back to the company email if the staff member has no email).
Booking form fields
| Field | Required | Meaning & notes |
|---|---|---|
| Service (Step 1 card) | Yes | The treatment wanted. Only Active + Public services appear; cards show duration & price. Grouped by category; uncategorized under "Other Services". Selecting one loads capable providers. |
| Provider | No | Defaults to "Any available provider". Options are loaded for the chosen service and list only staff assigned to it. If a slot is picked, the actual staff for that slot is captured from the slot button, not the dropdown. |
| Date | Yes | Native date input. Only today through the Maximum advance booking window is bookable; past or too-far dates return no slots. Changing it re-queries slots. |
| Time slot | Yes | Chosen by clicking a slot button. Labels are 12-hour (e.g. "2:30 PM"); the stored value is 24-hour. Picking one reveals Step 3 and captures the slot's actual provider. |
| Customer Name | Yes | Full name. Split on the first space into first/last when a new customer is created. |
| Phone | Yes | Required on the main booking form. (Optional on the waitlist mini-form.) |
| Yes | Must be a valid email. The confirmation goes here and it is the key used to find/create the customer. | |
| Notes | No | Free-text message to the business (preferences, requests). Saved on the appointment; defaults to empty. |
The success / thank-you page
After confirming, the customer lands on /appointments/book/success/{uuid}. It shows a large green check, an "Appointment Confirmed" heading, the reassurance line about the email, the Reference code in monospace (when present), and a "Back to home" button linking to the site root. This page needs no login and no tenant lookup, so the link in the confirmation email works from anywhere.
What customers see when things are empty
How available time slots are calculated
The Time buttons are not free-typed — every one is computed by the availability engine. Customers only ever see start times the engine returns. Understanding the six inputs below is the fastest way to answer "why aren't there more times?" without touching any code.
The six inputs to a slot
| Input | What it does to the slots | Set where |
|---|---|---|
| Slot interval | The spacing between offered start times (e.g. every 15 min). Smaller interval = more start times. Minimum 5, in steps of 5. | Settings |
| Minimum lead time | Hides (and rejects) any slot starting sooner than this many minutes from now — blocks last-minute bookings. | Settings |
| Maximum advance days | The booking horizon. Dates beyond this window return no slots at all. | Settings |
| Provider working availability | Each capable provider's start/end working times for that weekday, read from the HR weekly Schedule. No schedule = no slots for that person. | HR Schedule |
| Existing bookings | Times a provider is already busy are removed. Cancelled and No Show appointments are excluded (they don't block time). | Calendar / bookings |
| Service duration + buffers | A start time only survives if the service (plus its before/after buffer) fits without overlapping the provider's other bookings or their prep/cleanup. | Services |
Working hours come from the HR schedule
The engine reads each provider's working window — start and end times for the relevant weekday — from the HR weekly Schedule, not from the Appointments module. This is the single most common reason a provider shows no times.
Buffers & duration shrink availability
Buffers are turnaround padding attached to a service (setup before, cleanup after). When checking whether a new booking fits, the engine pads the busy intervals of both the existing appointment and the new one, so services never overlap into each other's prep or cleanup time. A service with large buffers legitimately shows fewer slots than the raw working hours suggest. The duration itself must also fit end-to-end within a free gap.
Lead time and the horizon can look like "fully booked"
Two settings quietly trim the ends of the day and the calendar:
- Minimum lead time removes slots that are too soon. With a 60-minute lead, nothing starting within the next hour is offered.
- Maximum advance days removes dates that are too far. Pick a date past the horizon (seeded default 60 days) and you get "No available times" — even though nothing is booked.
"Any available provider" pools everyone
Leaving the provider on Any available provider pools every staff member assigned to the service and returns their combined open times (the earliest option at each time). Picking a specific slot then assigns whichever provider that slot belongs to. This is the setting that shows customers the most options.
The race check on submit
Two customers can see the same slot at once. To keep only one from winning, Confirm Booking re-checks availability inside a locked transaction with a per-provider, per-day lock. The second submitter gets the inline error "That time slot is no longer available. Please choose another." and the button re-enables so they can pick a different time.
Joining the waitlist online
When a chosen date returns "No available times for this date.", a waitlist call-to-action appears right below the slots. It lets the customer ask to be emailed if a spot opens, without booking anything now.
SOP · Join the waitlist from the public page
Actor: Customer (public, not logged in)
-
Reach a "no slots" result
Follow Steps 1–2 of the booking journey and pick a date that shows "No available times for this date." The waitlist prompt appears.
-
Click "Join the waitlist"
This reveals a mini-form. The service and the preferred date you had selected are carried over automatically.
-
Fill Name and Email (Phone optional)
On this mini-form only Name and a valid Email are required; Phone is optional. The email is where the "a spot opened" notice is sent.
-
Submit
The form is replaced in place with the success line: "You're on the waitlist — we'll email you if a spot opens." A waitlist entry is created with status Waiting and source = online.
Waitlist statuses a customer's entry moves through
Leaving a review (public flow)
After a visit, a customer can leave a 1–5 star review with an optional comment. The link arrives by email and points at /appointments/review/{company-slug}/{uuid}. The page is state-driven — it only shows the star form when the visit is genuinely reviewable.
Where the review link comes from
Reviews are invited by the automated review-request email, sent by an hourly job a configured number of hours after the appointment is marked Completed — once per appointment. That email carries the {REVIEW_URL} link to this page. The whole flow depends on staff marking the visit Completed and on "Enable review requests" being on in Settings.
What the review page shows (three states)
| State | What the customer sees |
|---|---|
| Reviewable (Completed, not yet reviewed) | A teal hero with logo + name, a "Leave a Review" heading, a row of 5 clickable stars (hover highlights amber), an optional comment box ("Tell us about your experience (optional)"), and a full-width teal "Submit Review" button. |
| Already reviewed | A green check with "You've already reviewed this visit. Thank you!" — one review per appointment is allowed. |
| Not yet Completed | A muted message that the review isn't available yet. Customers who follow the link too early see this. |
SOP · Leave a review after a completed visit
Actor: Customer (public, not logged in)
-
Open the review link from the email
/appointments/review/{company-slug}/{uuid}. If the visit is Completed and not yet reviewed, the star form shows.
-
Click the stars
Choose 1–5 stars — filled stars light amber (
#f0ad4e); hovering previews the level. A rating is required; submitting without one shows "Please select a star rating." -
Add a comment (optional)
Type any feedback in the comment box, or leave it blank.
-
Submit the review
Click Submit Review. The card is replaced in place with a green check and "Thanks for your feedback!" The review is saved tied to the appointment, customer, staff, and service, and is published immediately.
Settings that shape the portal
Everything about the portal is controlled from the admin side. These are the per-tenant settings that most directly change what customers see and can do — all on the Appointment Settings page, which requires the Manage Appointment Settings permission.
| Setting | Effect on the portal | Seeded default |
|---|---|---|
| Enable public booking page | The master on/off. Off ⇒ the whole portal 404s; customers can't book or join the waitlist. | Off |
| Slot interval (minutes) | Spacing between offered start times. Smaller = more slots. Min 5, step 5. | 15 |
| Minimum lead time (minutes) | Hides slots starting too soon; blocks last-minute online bookings. | 60 |
| Maximum advance booking (days) | How far ahead customers may book. Dates beyond return no slots. | 60 |
| Cancellation window (hours) | How many hours before start a customer may still cancel/change. | 24 |
| Public booking URL | Read-only, clickable — derived from the company slug. Opens the live portal in a new tab so you can preview/share it. | from slug |
| Enable review requests | Master switch for the automated post-visit review email that links to the public review page. | Off |
| Review request delay (hours) | How long after completion the review email is sent. | 24 |
SOP · Turn on public booking & prepare the portal
Actor: Manager / Front desk (admin side)
-
Enable the Appointments module
In Settings → Manage Modules, make sure the Appointments module is enabled for the business. Without it, the portal 404s and the settings page won't appear.
-
Tick "Enable public booking page"
On Appointment Settings, turn on the master switch. Note the read-only Public booking URL shown just beneath it (built from your company slug).
-
Build the public catalog
In Services, create your categories and services and mark the ones you want online as Active and Public. Private or inactive services never reach the portal.
-
Assign staff to each service
Only staff explicitly assigned to a service are offered for it. A service with no assigned staff has no providers and therefore no slots.
-
Give each provider an HR schedule
Make sure every provider has an HR weekly Schedule with working in/out times — otherwise no slots will generate for them, no matter what else is set.
-
Tune the booking window
Set slot interval, minimum lead time, and maximum advance days so the engine offers the right times, then Save.
-
Preview and share the URL
Click the Public booking URL link (opens in a new tab) to see exactly what customers see, then share /appointments/book/{company-slug} in your SMS, social bio, and Google profile.
Permissions & access model
The public pages themselves are fully public — no permission gates apply to booking, slots, providers, submit, success, the waitlist, or reviews. Access is instead controlled by the two conditions above (module enabled and public booking on), plus a business rule for reviews (status must be Completed and no existing review). The admin-side permissions that configure the portal are:
| Permission | Governs |
|---|---|
| Manage Appointment Settings | Turning public booking on and setting slot / lead / advance / review windows. |
| Services (+ Create/Update/Delete) | Building the public catalog that customers browse and the staff assignments that produce slots. |
| Appointments (+ Create/Update/Delete) | The resulting bookings once they land in the calendar. |
| Waitlist (+ Create/Update/Delete) | Managing the waitlist entries customers create from the portal. |
Troubleshooting & edge cases
The most common "why doesn't the portal work?" questions, with the fix.
The portal silently 404s unless both the Appointments module is enabled and "Enable public booking page" is turned on in Settings. A slug that is unknown, inactive, or belongs to a business with booking off also 404s. Check both switches and the slug.
No time slots appear for a provider.The engine reads working hours from the HR weekly Schedule (not the Appointments module). A provider with no schedule with in/out times for that weekday gets no slots. Off-days and overnight shifts (out time at or before in time) also yield nothing. Confirm the provider actually works that day.
A service I created isn't on the booking page.Only services that are both Active and Public show online, and each needs at least one assigned provider to produce slots. A private or inactive service is invisible to customers even if staff are assigned. Fix it in Services.
The date says "No available times" but we're not fully booked.Slots respect the minimum lead time and maximum advance days. A too-soon or too-far date legitimately returns "No available times" — easy to mistake for "fully booked". Check the date is inside the window and the provider is working that day.
A customer got "That time slot is no longer available."Two customers raced for the same slot. The submit re-checks availability inside a locked transaction with a per-provider/day lock, so the second submitter is rejected even though they saw the slot moments earlier. They just pick another time — the button re-enables automatically.
Fewer slots appear than the working hours suggest.Buffers count against availability: a service with large before/after buffers reserves prep/cleanup time around each booking, so the raw working hours produce fewer offer-able starts. Reduce the buffer, shorten the slot interval, or widen schedules to open up more.
A returning customer booked but their profile didn't update.Booking finds the customer by email. If that email already exists, the existing account is reused — the name/phone typed on the form still save on the appointment, but the existing user record is what gets linked. This is expected behavior, not a bug.
The customer says they never got a confirmation email.Emails are best-effort after the booking commits — a booking still succeeds even if the email fails (the failure is logged, not shown to the customer). Emails also require the matching email templates to exist and be non-empty. The customer can still use the success page and its Reference.
The confirmation/review links point at the wrong place.Public confirmation and review links are built from the company slug — the only slug the portal resolves the business by. A custom booking slug that differs from the company slug can break these links. Keep them aligned.
The review page says the review isn't available.The review page only works once staff mark the appointment Completed. Before completion, customers who follow the link see a "not available" message. Each appointment can be reviewed only once; a duplicate quietly becomes "You've already reviewed this visit."
The directory at /appointments/book looks empty.The directory landing page is only populated when multi-tenancy is enabled. In single-tenant installs it looks empty, but the direct company URL /appointments/book/{company-slug} still works. Share the direct link.
Why is Phone required to book but optional for the waitlist?The main booking form requires Name, Phone, and a valid Email. The waitlist mini-form only needs Name and a valid Email — Phone there is optional. If a customer can't submit a booking, the missing Phone or an invalid Email is the usual cause.
Appointment status legend
Statuses a portal booking can reach (set by staff after the online booking is created). Only Confirmed is produced by the portal itself; the rest are staff-driven and shown here for context.
#f0ad4e.
#1d97a6.
#5bc0de.
#5bc0de.
#5cb85c.
#d9534f.
#777777.
Related pages
Make services Public + Active and assign providers — the catalog behind the portal.
Turn public booking on and tune slot interval, lead time, advance window, and review requests.
Where online bookings land, and the full appointment lifecycle.
Matching rules, the bell/notify action, and how a freed slot emails Waiting customers.
How published reviews and ratings roll up per staff and service.
Definitions for slot, company slug, lead time, buffer, review and more.