Take appointments and standing bookings
For appointments, lessons and rentals, customers pick an open time from your staff’s hours, your rooms and your calendar. A standing booking keeps the same time every week, and you can book for a customer and send them a pay link.
Turn on “customers pick a time” for an offering and set the grid start times fall on (every 15 minutes, say), how much notice you need and how far ahead people can book. Each price you sell has its own length, like 60 minutes for $90 and 90 minutes for $130. Change a length and new bookings use it; times already booked keep theirs. The staff you list are who customers can book. Who takes it doesn’t change how long it runs, so if someone needs longer, add an option for it, like a 75-minute cut. With more than one option, customers pick one, like “90 min · $130”, before they see times.
An option can have its own staff and rooms. Say only Sam grooms large dogs and they need the big tub: large-dog times then come from Sam’s hours and the tub’s, and two large dogs can’t overlap with one tub. An option with no staff or rooms of its own uses the offering’s. To set them, open the offering, find the option under What people buy and open Who does it and where.
Add-ons let customers add extras when they book, like hot stones for 15 minutes or a bottle of massage oil. Pick them from your products: a service with a length adds its minutes, so the booking blocks the whole time (90 minutes plus 15 needs a 105-minute gap). An item is handed over at the visit and sells only while it’s in stock. Each add-on is charged as its own line, even when a pack or membership pays for the booking, and a minutes pack takes only the option’s minutes. Cancelling ends the add-ons with the booking under the same policy, and moving it keeps them.
To offer add-ons, open the offering and use Add-ons: pick a service or item from your products, or Add a new one to make it there. Or ask the assistant, like “Add hot stones for $20 and 15 minutes to my deep tissue”: it sets up the add-on with the offering as one change for you to approve. Move them up or down to set the order customers see. When customers book, they pick the option, then tick any add-ons, and see the total length and price, like “105 min · $150”, before they see times. A sold-out item shows as Sold out. If no time fits, they’re offered a shorter option or the same one without the add-ons. When a pack pays for the visit, checkout says “Paid with your pack” and charges the add-ons. The booking on your schedule shows the option and add-ons.
Customers can book several services in one visit, like a manicure and then a pedicure. After picking the first, they tap Add another service and pick the next, with its own option and add-ons. Each part starts when the one before ends, and they see only times where every part has someone free. One checkout charges the whole visit, with each service its own line, and a pack pays any part it covers. If someone takes part of the time while they pay, nothing is booked and they’re offered the next time the whole visit fits.
A visit moves and cancels as a whole. When a customer moves it, every part moves together and keeps its length. When they cancel, every part is cancelled under your policy. You can cancel just one part from the session’s Who’s coming: it’s refunded under the booking’s policy, and the other parts stay booked. On the schedule, each part of a visit is marked with its place in the visit, like 1/2, and opening it shows every part, who takes it and the visit’s total. Messages go once for the whole visit: the customer’s confirmation, reminder and request, and your new-booking alert or request to accept, each list every part with its time and who takes it. A part you cancel on its own gets its own message.
Set each person’s own hours and days off, and whether customers can book them online, on Schedule, Team. Team members can set their own there too.
Open times are worked out from each person’s hours (their own, else the offering’s, else your business hours), minus everything they already have: other bookings, the classes they teach, time you’ve blocked, and your Google Calendar’s busy times when it’s you. Rooms and equipment the offering needs have to be free too, including setup and cleanup. A 60-minute massage with 15 minutes of cleanup holds its room for 75.
If two people try to book the last room at the same moment, one gets it and the other is told it was just booked and offered the next open time. Nothing is ever booked twice.
Want to OK each booking yourself? Turn on approval. Customers’ bookings then wait for you, with the time kept for them, and they’re told it’s requested. Accept it to confirm, or decline it and anything they paid goes back in full. Bookings you make yourself don’t wait.
You can book for a customer: send a pay link that holds the time for 48 hours, or mark it paid in person. Unpaid by then, the time opens again and nothing is charged.
A standing booking keeps a customer’s time every week, like a Thursday lesson or Monday, Wednesday and Friday daycare. It’s paid by one sale, usually billed monthly, and books their dates about four months ahead, topped up every day. If a date is taken (a recital, a full day), it isn’t skipped quietly: you hear about it and it’s booked once it’s free. They can skip a week by cancelling that date. A standing booking billed monthly ends when its billing is cancelled.
Connect Google Calendar on Schedule, Team. Every session you lead goes on your calendar right away and moves when it moves. Without it, customers get an Add to calendar link in their confirmation and on their booking’s page.
Customers can move a booked time from their booking’s page: they pick another open time long enough for what they booked, with the same person when they’re free, and what they paid moves with them. A move keeps the length it was booked with, even if you’ve changed the option since. If they email asking for an open time, it waits for your OK, ready to approve.
With a deposit policy (Settings, Policies), a time paid online takes the deposit when it’s booked and the rest at the visit.
For agents
Turn it on with onDemand on the offering (stepMinutes, noticeMinutes, horizonDays, bufferMinutes, approval, optional hours), staff on the offering in the order to try them, and one or more one admissions, each an option with its own durationMinutes (5 to 720, in 5-minute steps), name and price. An option can name its own staff (who takes it, in order) and resources (rooms it holds, by resourceId, groupId or name), each replacing its list when given and kept when left out: its own staff replace the offering’s for its bookings, and its own rooms replace the offering’s. offerings.get lists them with their admissionId; offering-wide lists leave them out. Staff or rooms on any other admission are refused. With no staff or rooms of its own, an offering takes the owner’s time, unless every option names its own. offerings.save writes each option’s length to its product on every save; a new option needs one, and one left out keeps its length. A durationMinutes on any other admission, or on a class or event, is refused. A booking runs its option’s length; who takes it never changes that, and staff take no durationMinutes. A booking keeps its option’s length as it was when booked, and a minutes pack draws that, never the session’s span. offerings.bookable lists each option as an admission with its own name, price, durationMinutes and staff (its own people, else the offering’s); the offering’s minutes is its shortest option’s length. offerings.times takes offeringId, date and admissionId (the option; only times long enough for its length are open; it can be left out only when the offering has one option, and is refused otherwise), with seek: true for the first date from there with times, resourceId for one person, or minutes to fit a fixed length instead (a booking being moved keeps the length it was booked with). It answers times with start, label and who is free. offerings.days takes offeringId, from, to and the same admissionId (the same rule), resourceId and minutes, and answers the dates with open times. A visit books several services back to back: offerings.times and offerings.days take parts, the services after the first in order (up to 4), each with its offeringId, admissionId (the same rule), addOns and optional resourceId. Each part starts when the one before it ends, with no gap and no buffer between them; only starts where every part has someone free and its rooms are open, and each time answers visit, every part with its start and who takes it. The same person is tried first for the next part. Setup and cleanup are skipped between two parts that share a person or room. A part at another location is refused. To book a visit, pass the same start to offerings.book with more: the parts after the first, each with its admissionId, addOns and optional resourceId. Every part books or none does, in one sale with each part its own line and its add-ons, and a pack or membership pays any part it covers (one you name with grantId for the first). A time taken meanwhile answers taken with the next start where the whole visit fits, and nothing is booked. It answers visit, each part’s enrollmentId, sessionId, start and staff. A visit waits for your OK as a whole when any part’s service asks for it, and offerings.accept or offerings.decline on any part acts on them all. offerings.transfer with toStart on any part moves the whole visit, toStart being the first part’s new start; each part keeps its length (ask offerings.times with each part’s minutes). offerings.cancelEnrollment cancels every part of a visit; the business can pass part: true to cancel just that one, which refunds its line and add-ons under the booking’s policy and keeps the rest booked. Messages about a visit go once for it and name every part. offering.enrolled, offering.cancelled and offering.transferred come for each part with visitId (the first part’s enrollmentId), and automations run once per visit; a part cancelled with part: true has a null visitId. offerings.roster, offerings.enrollment and offerings.booking answer visit for a booking that’s part of one: every part with its time, person and status, the visit’s minutes and total. offerings.book takes admissionId, start from offerings.times, optional resourceId, the buyer, attendees, seats, pay (card or door), codes and an optional requestId to retry safely; it answers status (confirmed, held with payment or payAt/holdUntil, pending_approval, or taken with message and next) with sessionId and staff. Add-ons: offerings.save takes addOns, the whole list in order, on an offering customers pick a time for: products by name or id, or a new one as { name, priceMinor, durationMinutes }, made through commerce.createProduct in the same save (a product with the same name is reused, its price and minutes changed to these when they differ); each is a service with durationMinutes or a physical product, and packs, memberships, bundles, gift cards and downloads are refused. offerings.get answers them as addOns, and offerings.bookable lists them on each such offering as addOns, in order, each with productId, name, kind (service or item), minutes (what a service adds; null for an item), price, priceMinor and soldOut (an item with no stock left can’t be picked). offerings.review with start checks a pack or membership against the time and option picked before a session exists; its cover names the grant’s kind (pack, membership), and each sale line says whether it’s an addOn. offerings.roster lists each booked time’s option (name and booked minutes) and addOns (name and minutes). offerings.times, offerings.days, offerings.review and offerings.book take the picked addOns, each once; one not on the offering, off sale or sold out is refused before a time is held. Service add-ons add their minutes to the option’s length. offerings.book sells each add-on as its own line in the booking’s sale, opened even when a pack or membership pays for the option; a minutes pack draws the option’s minutes only. Cancelling ends the add-on lines with the booking under its policy; moving keeps them and moves their cancellation window. offerings.accept and offerings.decline take enrollmentId of a pending_approval booking. Accepting one that held nothing yet has the pack or membership the customer picked when they booked pay (grantId; with none picked, the one that costs least; none sells it instead), and its add-ons still sell as their own sale. If its seat was taken meanwhile, it waits in line with that pick and pays the same way when a seat frees; under a waitlist policy that charges automatically, the add-ons go on the saved card with the option. offerings.bookStanding takes admissionId, days (0 is Sunday), startMinute, every (weeks), from, optional until and resourceId, the buyer, attendee, seats, pay, and agreeToRenewal with termsVersion from commerce.previewSale for one billed again and again; it answers standingId, booked and any clashes. Cancel one date with offerings.cancelEnrollment. offerings.endStanding takes standingId for one paid up front; one billed again and again ends through commerce.cancelAgreement. offerings.transfer with enrollmentId and toStart (from offerings.times) moves a booked time to another open time that fits the length it was booked with; it answers sessionId and start, or is refused with the next open time. resources.savePerson sets a person’s bookable and own hours (weekly, daysOff; null for the business’s). Repeating offerings.book or offerings.enroll with the same requestId answers the same booking, with payAt again while it’s held for its pay link.