| Field | Type | Description |
|---|---|---|
| Name | Text | Shown on the public booking page |
| Description | Textarea | Short blurb โ displayed on the service card |
| Duration | Minutes | Used to calculate available time slots |
| Price | Decimal | Display price. Set to 0 for a free service |
| Requires Payment | Toggle | When on, triggers Stripe Checkout before confirming |
| Image | Upload | Cover image shown on the booking page service card |
| Is Active | Toggle | Only active services appear for booking |
| Sort Order | Drag handle | Controls order on the public booking page |
| Is Virtual | Toggle | Marks the service as an online/video appointment |
| Auto-generate Google Meet link | Toggle | Visible when virtual โ auto-creates a Meet link per booking |
| Custom Video Call URL | URL | Static Zoom, Teams, or any https:// link to use instead of (or as a fallback for) Meet |
{primary.fa-lightbulb-o} Set Duration accurately โ it determines how many bookings fit in a day. A 60-minute service with a provider working 9amโ5pm generates 8 available slots.
Any service can be marked as virtual to support online/video appointments. The Virtual Session section appears at the bottom of the service edit form.
Best for providers who use Google Calendar sync.
When a client books this service, a unique Google Meet link is automatically created via the Calendar API and:
.ics iCal file as X-GOOGLE-CONFERENCE (shows natively in Google Calendar and Apple Calendar){primary.fa-info-circle} Google Meet generation requires the provider to have Google Calendar sync connected (Manage โ Integrations โ Calendar Sync). If the provider is not connected, no Meet link is generated โ the custom URL fallback is used instead.
{warning.fa-lock} Meet links are immutable โ once generated for a booking, rescheduling or updating the booking never overwrites the link. This ensures clients always have a working URL.
Best when you have a static room URL or prefer not to use Google Meet.
https:// URL in Custom Video Call URLThe custom URL is sent to all clients booking this service. Every booking for this service uses the same room link.
The email system resolves the video call link in this order:
booking.meet_link (auto-generated Google Meet, if available)
โ service.video_link (your custom Zoom / Teams URL)
โ (no button shown)
If Google Meet generation is disabled and no custom URL is set, the "Join Video Call" button is simply omitted from the email.
Each service can be delivered by one or more providers. Clients choose a provider when booking.
To assign providers:
{warning.fa-exclamation-triangle} A service with no providers assigned will not appear on the booking page โ even if the service itself is active. Always assign at least one active provider.
Available time slots are calculated dynamically at booking time. The slot engine respects:
| Factor | Effect |
|---|---|
| Provider working hours | Slots only generated within the provider's enabled hours for that day |
| Service duration | Slots are spaced by the service duration (e.g. 60min service โ 9:00, 10:00, 11:00โฆ) |
| Existing confirmed bookings | Already-booked slots are blocked and not shown |
| Provider active status | Inactive providers are excluded |
Provider works: 9:00 โ 17:00
Service duration: 90 minutes
Generated slots:
09:00 โ 10:30
10:30 โ 12:00
12:00 โ 13:30
13:30 โ 15:00
15:00 โ 16:30
Total: 5 slots per day
{success.fa-check-circle} Slots are generated in real time โ no pre-population or caching. A slot only appears if it is genuinely available the moment the customer views the page.
| Service Type | Booking Flow |
|---|---|
Free (Price = 0, Requires Payment = off) |
Booking confirmed immediately โ no payment step |
Displayed price, no payment (Price > 0, Requires Payment = off) |
Price shown for reference only โ booking confirmed immediately |
Paid (Price > 0, Requires Payment = on) |
Client redirected to Stripe Checkout โ booking confirmed only after payment succeeds |
See Stripe Payments for full setup instructions including webhook configuration.