Skip to content
Knowledge ERP Docs

API Reference ↗
Appointments

Appointments & Scheduling

Schedule customer appointments by type, capture pre-appointment questionnaires, and keep an eye on the day from the appointments dashboard.

The Appointments module schedules customer-facing visits and the information you need before they happen.

In this section #

Detailed guides for everything covered here:

  • Appointment Types — The bookable service catalog for your scheduling module — each type defines the duration, concurrent capacity, and equipment-selection behavior for one kind of customer visit.
  • Opening Hours — Per-location opening hours that tell the scheduler which time slots are available — set the regular week on one screen, with date-range overrides for holidays and seasonal closures.
  • Staff Availability — Each person's own working week and their time off, which narrows the location's hours to the times somebody is actually there.

Where the booking settings live #

Everything that governs online booking sits on the location: its public booking link, its opening hours, its appointment types and capacity, and the support and cancellation email addresses.

Open Appointments → Locations to reach them. That list shows the locations you have made bookable, with the count of appointment types and opening-hours rules on each, so you can see at a glance which ones are ready to take bookings. Click a location to open it and find its booking link.

The same locations also appear under Inventory → Locations, which lists every site including the ones that take no bookings. It is one set of records reachable from two menus — not two separate lists to keep in step.

To make a new site bookable, open it and turn on Enable Appointments; it then appears in the Appointments menu too.

Appointment types #

Define appointment types (the kinds of visits you offer) with their own settings, and set opening hours so scheduling respects when each location is open.

Scheduling #

Book appointments against a customer, type, location, and time. An appointment can link to a sales order, tying the visit to the work it's for.

Equipment selection #

When an appointment type allows equipment selection, the public booking page lets the customer pick in-stock units to reserve for their visit. Only units in inventory categories marked Available for Appointment Selection appear, and the list is narrowed to what the type is for — returnable gear for loan/rental types, sale goods for purchase types. Each picked unit is placed on hold for the appointment; the hold is released automatically if the appointment is cancelled or marked a no-show — from the app, the customer portal, or the API.

A hold also expires on its own. A day after the appointment was due to finish, anything it still holds goes back into stock, so gear is not left reserved behind a booking that has been and gone — one nobody turned up for, or one marked completed without being turned into a loan, rental or order. The release is written to the unit's movement history as a Hold Released against that appointment, exactly as a cancellation would be, and it never touches a unit some later booking has since claimed.

A catch-all appointment type never asks for equipment, on the booking page or in the customer portal, even if equipment selection is switched on: a catch-all exists because nobody yet knows what the job needs.

The list is searchable, and the count beside each item reads "n in stock now" — it is stock on hand at that moment, not a promise about the day booked, so it says which. Ticking something and then searching does not lose the tick.

Underneath is "The item I need isn't listed": a free-text box that is stored in the appointment's notes as "Equipment requested but not listed: …", and shown on the review screen before the booking is confirmed. Without it a customer whose item is not on the list has no way through the step at all.

The public booking page #

Each bookable location has a public page at /book/{location} (the Public booking link on the location) where anyone can book without an account. It runs in four numbered steps — choose an appointment, pick a day and time, your details, check and confirm — with the chosen type, day and time kept on screen throughout, and a progress bar so nobody has to guess how much is left.

Nothing is booked until the final Confirm. Step 4 is a review of everything chosen: what, when (and how long is set aside), where, the name and company and contact details given, the answers to the type's own questions, any equipment requested, and what it costs. It used to be possible to create an appointment straight off the equipment list without ever being shown a summary — and, later, to reach a review that quietly left out the company and the one answer the business had made compulsory.

What each type is comes from its description and pricing note — write both, or the page can only show a name and a duration.

The calendar distinguishes the two reasons a date cannot be picked, which used to render identically:

  • Fully booked (amber) — the location is open, but there is no free slot. Try another day.
  • Closed (grey) — the location does not open then. Trying again is pointless.
  • Dates outside the type's lead time or maximum advance are simply not offered yet, and are not labelled as either.

A key underneath explains the marks, and the location's weekly opening hours are printed below the calendar.

Because a booking page is often the first thing a stranger sees:

  • It is branded with your business. The heading and the browser tab carry the account name; the branch is named underneath, so a customer of a two-site business still knows which one they are booking. Location names are internal records — a page headed "Downtown Studio (Online Booking)" reads to a first-time visitor as the wrong website.
  • Where and how to reach you are shown throughout. The location's address and support phone appear in the page header, on the confirmation, and in the confirmation email. If the location has no address, the page says so plainly rather than presenting the location's name as a destination. Turning Enable Appointments on therefore makes the location's address and support phone required — see Locations. Where you have published no phone number, nothing on the page invites the customer to ring: it names the email address instead, rather than telling somebody to call a number that isn't there.
  • When you travel to the customer, the page asks where. An appointment type marked We travel to the customer collects a street address, town and postal code on the details step, and the "Where" on every screen afterwards becomes We are coming to you plus that address — rather than your branch, and never "check with us before you set off", which is advice for a journey the customer is not making. Types the customer comes to you for are unchanged and ask for no address.
  • The same person cannot book the same slot twice. If the email on the form already has a live booking overlapping the chosen time at that location, the page says so instead of creating a second one, and offers to pick a different time or to email the details to that address. It does not display the booking: anyone can type anyone's address into a public form, so the details go to the mailbox rather than to the screen (throttled to three sends an hour per address). Capacity is unaffected — a different customer can still take the same slot for as long as staff are free.
  • The email address is checked properly. name@example is refused as well as name@, and the message appears on the page rather than in a browser tooltip.

Keeping the booking page private #

The public booking page is open to anyone with the link, so it is careful about what it will confirm.

Duplicate bookings. If the address entered already holds a booking for the same service at the same time, the page says so rather than taking a second one. That check is deliberately narrow: it matches the address actually typed on the booking, for the same appointment type. A booking for a different service, or one made under a different address, is neither mentioned nor blocked.

Rate limiting. Checks are limited per address and per network. Somebody working through a list of addresses is stopped within a few attempts and shown a "try again shortly" page that says nothing about any address. Attempts are recorded — hashed, never the address itself — so a sweep can be spotted after the fact.

Email verification. Where the fact of having an appointment is itself private — a clinic, a therapist, anything health-related — turn on Require email verification before booking on the location. The customer is emailed a six-digit code and the booking is taken only once they enter it. Nothing about any address is looked up or said until that code is entered, so the page cannot be asked about anybody. It also stops someone booking in a stranger's name and having your confirmation land in their inbox.

It adds one step to every booking, so it is off unless you turn it on.

Timezones #

Each bookable location has a timezone — the clock its opening hours and appointment times are read off. Set it under Location → Appointments. Leave it blank and the location uses your account's timezone, and failing that the system default, so a single-site business never has to think about it.

It matters as soon as anybody is not standing in the same place as you:

  • The booking page names the clock. Times are always the branch's, and the page says so — "10:00" with nothing after it is the most expensive ambiguity a booking page can have.
  • A visitor elsewhere sees their own time too. The page reads the timezone from their browser and prints their local time under each slot, and there is a picker to change it. Nothing is guessed from an IP address, which a VPN gets wrong.
  • Confirmation emails and reminders name the timezone next to the time.
  • Calendar invitations carry the real instant, so the entry lands at the right moment in the customer's diary wherever they are.
  • Lead times and booking windows are measured on the branch's clock. A site several hours from the server used to have its "today" decided by the server for part of every day, which moved both the earliest and the latest bookable date.

Putting it in the customer's calendar #

Every booking is offered as a calendar entry, three ways, because customers do not all keep their diary in the same place: Google and Outlook open straight into that calendar with the event filled in, and Apple / other downloads an .ics file that every other calendar understands. The same three appear on the confirmation screen the moment a booking is taken, on the "Your booking" page, and in the confirmation email — which also carries the .ics as an attachment.

The entry holds the appointment type, the business name, the address, the phone number to call, the reference, and the link back to the booking, so it is still useful months later when the email has been buried.

Changes follow the customer's calendar. A rescheduled appointment is sent as a revision of the entry the customer already has — their calendar moves it rather than drawing a second block at the old time — and a cancellation removes it. That only works because the invitation keeps one identity for the life of the booking; it is not a fresh event each time.

The appointment is offered for filing as soon as it is booked, before it has been confirmed. A slot a customer chose but could not write down is a slot they forget. Cancelled and no-show appointments are not offered at all.

Managing a booking without an account #

The confirmation screen and the confirmation email both carry a View or cancel this booking link to a "Your booking" page, showing what was booked, where, when, its status, and its reference. From there the customer can cancel — which releases any held equipment and notifies the location's cancellation-notice email, exactly as a portal cancellation does. Cancelling is not offered once the appointment is completed or its time has passed.

They can also move the booking to a different time, without cancelling it first. The page offers the next three weeks; picking a day shows what is free, and picking a time moves the booking there. The old time is held throughout, so a customer who looks and finds nothing better simply keeps what they had — which is what cancelling-and-rebooking could not promise.

Availability comes from the same source the booking calendar uses, asked to ignore this appointment's own hold so the time it already occupies is not reported as taken by itself. The slot is checked again at the moment of the move, so a page left open overnight cannot take a time somebody else has since booked.

Where the location requires staff approval for changes to a confirmed appointment, the move is lodged as a request instead and the customer is told so — the same rule the portal follows. A pending booking moves immediately.

That link is signed and expires a month after the appointment. The signature is what grants access, not the appointment reference printed on the confirmation: the reference identifies a booking, it does not open one, and an appointment id on its own opens nothing. This is what stops the page from being usable to look up other people's bookings.

The reference #

Every booking carries an eight-character referenceE2C4FE13 — shown on the confirmation screen, in the confirmation email and on the customer's "Your booking" page. It is what they quote when they get in touch.

On your side it appears on the appointment page and as a column on the Appointments list, and the list's search box finds it: paste or type the reference a customer quotes and their booking comes back. Case and spacing do not matter. The reference is derived from the appointment's id, so every booking ever taken has one and it can never drift from the record it names.

Confirmation & next steps #

New bookings start as Pending. The customer receives an email with a signed Confirm Appointment link; following it confirms the booking (proving they own that email) and, when the email uniquely matches one existing customer, attaches that customer automatically. Staff can also confirm from the appointment page.

The public pages say so plainly, because "Pending" on its own reads as something having gone wrong: the confirmation screen tells the customer to check their email and click the link, and the "Your booking" page repeats it next to the status, naming the address it was sent to. The slot is held either way — the confirmation step is about proving the address, not about whether the time is theirs.

Once confirmed, the appointment page shows a Next Steps panel. Based on the type's next-step flags, one-click actions create a loan agreement, rental agreement, sales order, or customer return — pre-filled with the customer and carrying the requested equipment across as lines.

A booking from a first-time customer has no customer record attached, so converting it creates one from the name, company, email and phone on the booking and links it to the appointment.

The booking form asks for a Company, which is optional and only for someone booking on behalf of a business. Give one and the customer is filed under the business — the company becomes the customer's name, the way an accounting system files a trade account — while the person stays on the record as the contact. Leave it blank and the booking is filed as a person. Without that field a business had to type its company into the name box, and the customer came out split down the first space: "Acme Plant Hire" filed as a person with the surname "Plant Hire". If the booking details already match a single existing customer, that customer is used instead of a duplicate being created. Two cases are left to you rather than guessed at: when the details match more than one customer, and when the booking has no name or no email or phone at all. Use Attach Customer to settle those — it lists records matching the booking email or phone, and can create a new one pre-filled from the booking.

Changing an appointment, and telling the customer #

Every state change that a customer would care about offers to email them, and records what was sent on the appointment's Customer Emails list — the type of email, the address it went to, when it was sent, and who sent it. A row appears whether or not the send succeeded: Sent At is filled in only once the mail server has accepted the message, so a failed send shows the reason instead of quietly reading as sent. Any row can be resent, and an appointment nobody has written to yet can be emailed from the same list.

The state changes live on the appointment page rather than the edit form:

  • Confirm marks a pending appointment as confirmed, and emails the customer to say so.
  • Reschedule takes the new date and time. It refuses a slot outside the location's opening hours or one the assigned employee is already booked for, unless you tick Move it anyway. A confirmed appointment goes back to Pending when it moves, because the customer has not agreed to the new time — the email asks them to confirm it. Tick The customer has agreed to this time (you moved it with them on the phone) to keep it confirmed.
  • Cancel releases any equipment held for the appointment and emails the customer. It can be undone: a cancelled appointment can be Reinstated, which brings it back as Pending — not Confirmed — so the customer is asked again. Equipment released by the cancellation is not re-held.

Cancelling and un-cancelling are not available from the status dropdown on the edit form, because that route skips the equipment release and the email. Moving the date or time of a confirmed appointment from the edit form still sets it back to Pending, and says so, so the record never claims an agreement that has not happened.

Who is available, and when #

Availability is worked out from four things, and a slot has to survive all of them: the type's lead time and booking window, the location's opening hours, the assigned person's own schedule, and their existing bookings — with the type's buffers counted as busy time either side of each one.

Staff Availability (under Appointments) is where a person's own working week lives. It works exactly like opening hours: a day-of-week row is the regular pattern, and a date-range row with Not working is time off.

  • Somebody with no rules here cannot be booked at any time. Everybody who takes appointments needs a working week set, or the types they are on offer no slots. Existing staff were given their location's working week when this changed, so nothing had to be set up by hand and availability carried on as it was.
  • Personal hours narrow the branch's, they do not extend them. A person marked available 08:00–20:00 at a site that closes at 17:00 is still done at five.
  • The whole appointment has to fit inside the shift. A technician who finishes at 17:00 is not offered a two-hour job at 16:00.
  • Time off takes them out of the diary entirely for those dates, and the public page stops offering them.

Reminders #

An appointment type can carry a list of reminder lead times in hours. 24 emails the customer the day before; add 2 as well and they also hear from you two hours out. Leave the list empty — the default — and the type sends no reminders at all.

  • Each lead time is sent once per appointment, and appears on the appointment's Customer Emails list like every other message, with the address it went to and whether the mail server accepted it. A reminder the server refused shows there as a failure to resend by hand rather than being retried every quarter of an hour.
  • The reminder offers a way out. It repeats what, when and where, and carries the View or cancel this booking link — a customer who cannot make it and has no way to say so becomes a no-show instead of a cancellation somebody else could have taken.
  • An unconfirmed booking is asked to confirm. If the appointment is still Pending when its reminder goes, the email says so and includes the confirm button.
  • Cancelled, no-show, completed and past appointments are never reminded, and nor is anything outside its lead time yet.

Text as well as email. Turn on Also send reminders by text on the type and the same reminder is sent by SMS to the number on the booking. It needs a Twilio connection under Integrations and a phone number on the booking; without either, the email still goes and nothing fails.

Reminders are checked every fifteen minutes, so one is sent within a quarter of an hour of its lead time rather than exactly on it.

Reacting to appointments yourself #

Appointments are available to the workflow builder as four triggers, so a business can build its own follow-up rather than waiting for a setting:

Trigger Fires when
Appointment booked A booking is created — the public page, the portal, the staff form or the API
Appointment cancelled Its status becomes Cancelled, however that happened
Customer does not show up Its status becomes No Show
Appointment is coming up At each of the type's reminder lead times, alongside the reminder itself

Each one carries the appointment, its type, the customer, the contact details, the location, and the scheduled date and time; coming up also carries how many hours ahead it is, so one rule can behave differently for the day-before and the two-hours-out pass.

Asking your own questions when somebody books #

An appointment type can carry its own booking form questions — which machine, which site, is there a lift — asked on the booking form itself, while the customer is choosing a slot. Add them under the type's Booking Form Questions tab. Five kinds:

Answer type The customer gets Required means
Short answer One line They must type something
Long answer A box for a few sentences They must type something
Choose one Your own list of options They must pick one
Yes or no A yes and a no to pick between They must pick one — answering "No" still books
Tick box A single tick box They must tick it — leave Required off and they can book without ticking, and the appointment records "No"

"Yes or no" and a required "Tick box" are not the same question. Use Yes or no when either answer is fine and you just need to know — "Do you need a loan unit while yours is in?". Use a Tick box with Must be answered switched on only for something they have to accept before you will take the booking — "I accept the cancellation policy." An unticked box cannot be told apart from one nobody touched, so a required tick box can only mean "must tick"; ask a real question that way and you have built a form nobody can say no to.

A tick box only blocks the booking when Must be answered is on. Left off — the default — the customer can book without ticking it and the appointment records "No", which is the right shape for a fact you want but will not refuse work over. So if you are adding a waiver or a cancellation policy, switch it on; the type alone does not do it.

  • The answers land on the appointment, in a Booking Form Answers panel, so whoever prepares for the visit reads them without opening anything else. A yes or no reads as "Yes" or "No" there, the same as a ticked or unticked agreement.
  • A required question blocks the booking until it is answered, and the message names the question rather than saying "this field". Only require what you genuinely cannot start the job without: every field between a customer and a confirmed slot costs bookings.
  • An unanswered optional question stores nothing — except an agreement, which always has a state and so records the "No".
  • Each answer keeps a copy of the question as it was asked. Rewording a question later does not rewrite what a customer was answering, and deleting one does not erase their answer.

This is not the pre-visit questionnaire. A questionnaire is emailed after the booking and writes into the customer's own custom fields; these are asked during it and describe the job. Use questions for the few things that decide what you send, and the questionnaire for everything else.

Questionnaires #

A pre-visit questionnaire collects what you need before a customer arrives. It is not a survey: a survey asks how something went and is sent afterwards, and is normally sent automatically. The two are separate buttons that say which end of the visit they are for — Send Pre-Visit Questionnaire and Send Feedback Survey — and the survey button only appears once the appointment is completed or marked no-show.

The questions are your custom fields. Anything flagged Show on questionnaire under Settings → Custom Fields is asked; nothing else is, and a customer cannot write to a field that is not flagged. User-picker fields are never asked publicly. Answers are validated and stored exactly as a staff member's would be, land on the record's own custom field values, and appear in the change history attributed to the customer — so if an answer replaces something staff entered, you can see it and undo it.

Sending it. Use Send Pre-Visit Questionnaire on the appointment (or on a sales order) to create and email the link in one step. The record then shows whether it was sent and whether it has been answered, so you never have to go looking. Sending again re-sends the same link rather than issuing a second one.

Sending it automatically. Set Send Questionnaire (hours before) on an appointment type and every appointment of that type is emailed its questionnaire that many hours ahead. Leave it blank — the default — and the questionnaire stays manual. Each appointment gets at most one, and cancelled and past appointments are never sent one.

The link is personal, single use, and stops working once answered. It is not displayed on screen; use Show Questionnaire Link on the invitation if you need to copy it.

Customer self-service (portal) #

Customers manage their own appointments from the customer portal. Each appointment opens to a detail page showing the location's address and support phone, the requested equipment, and status-aware actions:

  • Pending appointments can be cancelled, edited (contact details, notes, and — when the type allows equipment selection — the requested equipment, re-held against on-hand stock), or rescheduled to any open slot, validated against the same availability rules as booking.
  • Confirmed appointments can be cancelled, and a reschedule becomes a request that staff approve or decline in the Customer Reschedule Requests inbox (with a pending badge) — or it applies immediately when the location enables Auto-approve confirmed reschedules. Cancelling can notify the location's cancellation-notice email.
  • Completed appointments show the records they produced (the related sales order, rental, loan, or return).

Configure the support phone, cancellation-notice email, and auto-approve toggle under Location → Appointments. Every portal change is attributed to the customer in the change history.

Booking from the staff side #

Appointments → New appointment, or New appointment on the dashboard.

  • Time is a list of the slots that are genuinely available — the times the location is open, long enough for the type's duration to fit before closing, and with an assigned employee free. It is the same availability the public booking page offers, so a phone booking and a web booking cannot disagree.
  • Switch on Enter a time manually to type a time instead. The guards still apply: a time outside opening hours or one that double-books the assigned employee is refused, and Book anyway is what releases it. A date in the past is refused either way.
  • Choosing a Customer fills the contact name, email and phone from their record, so the confirmation goes to the address you hold rather than one typed from memory. Clearing the customer leaves the contact details in place.

An appointment type with no staff assigned cannot be booked online at all — the public calendar has nobody to offer. Neither can one whose assigned staff have no working hours set, for the same reason: a person with no hours is bookable at no time. The Bookable column on the appointment types list says which of the two it is. Staff can still book either one here and assign somebody later.

Cancelling #

Cancel on the appointment row or its page sets the status to Cancelled and releases any equipment being held. The booking stays on the record, so the history and the customer link survive — this is the action you want in almost every case. Deleting an appointment removes the record and is tucked behind the row's More menu.

A cancelled or no-show appointment will not accept a Send Survey: it never happened, so there is nothing to ask about. The refusal says so rather than quietly doing nothing, and it holds for the scheduled survey triggers too.

Dashboard #

The appointments dashboard is the front desk's day sheet. Pick Today, Tomorrow, This Week or Next Week and it lists every booking in that window, grouped under a dated day heading and ordered by start time.

Each row shows the start and end time and the appointment's length, the customer's name, a click-to-call phone number, the type, the location, the assigned employee and the status — and the whole row links through to the appointment.

Clashes are flagged. When the same employee is booked for two appointments that overlap, both rows are marked Double-booked and a banner counts them for the period. Cancelled appointments release their slot and unassigned appointments never clash, so the count reflects real conflicts. Back-to-back bookings — one ending exactly as the next begins — are not clashes.

The same clash flag appears as a Clash column on the Appointments list and on each appointment's own page, naming who the conflict is with.

The dashboard is an agenda, not a drag-and-drop calendar grid: rows under day headings rather than blocks on an hour axis. It answers what is happening and in what order, which is what running the day needs.

Doing it from the API #

# List appointments
curl "https://your-domain.com/api/v1/appointments" \
  -H "Authorization: Bearer $TOKEN"

status accepts pending, confirmed, completed, cancelled or no_show; anything else is rejected with a 422. Setting it to cancelled or no_show releases any equipment the booking was holding, the same as the Cancel and Mark No Show actions in the app.

# Cancel an appointment (releases its held equipment)
curl -X PATCH "https://your-domain.com/api/v1/appointments/$APPOINTMENT_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "cancelled"}'