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.
Opening Hours define when each of your inventory locations is open for appointments. The scheduler uses these rules to generate bookable time slots — so if a location has no hours configured for a given day, no appointments can be booked there. Rules come in two flavors: a recurring day-of-week rule (e.g. every Wednesday, 09:00–17:00) or a date-range override (e.g. December 24–26 closed for the holiday). When both types match a given date, the date-range rule wins.
Opening hours only apply to locations that have Appointments enabled. If a location doesn't appear in the Opening Hours form, go to Locations and turn on the Enable Appointments flag before adding hours.
A day can have more than one window. Add two rows for the same weekday — 09:00–12:00 and 13:00–17:00 — and the scheduler treats the gap as closed, so a business that shuts for lunch can say so. Both are used; a second row is no longer ignored.
Day-of-week rules #
A day-of-week rule fires every week on the chosen day. This is how you configure your normal operating schedule:
- Location — which appointment-enabled location this rule applies to. Required.
- Label — an optional human-readable note (e.g.
Regular Hours). Leaving it blank is fine for standard weekly hours. - Day of Week — Sunday through Saturday (0–6). Set this for a repeating weekly rule; leave it blank when using a date range instead.
- Open Time and Close Time — the window during which slots are generated.
Type them however you write times:
9:00 AM,9am,9and09:00all mean nine o'clock. Anything unreadable is refused on the page rather than saved as a blank. Both are disabled when Closed is toggled on. - Closed — turn this on to mark the entire day as unavailable without specifying times (useful for a location that's always closed on Sundays, for example).
A complete weekly schedule is simply seven day-of-week rules — one per day. Days with no rule and no matching date-range override are treated as closed by the scheduler.
A booking on a day the location is shut is flagged. Save one anyway — from the booking form, with Book anyway ticked — and it carries an Outside opening hours mark in the Clash column, on the dashboard and on its own page, naming the hours the site keeps that day.
That only applies once a location has hours recorded. A location with no opening-hours rules at all is never flagged: nothing has been said about when it opens, so nothing is claimed about when it is shut, and the booking form does not refuse times there either. Record the week and both start working.
Date-range overrides (holidays and seasonal hours) #
A date-range rule applies only between Date From and Date To (inclusive) and takes priority over whatever day-of-week rule would otherwise apply. Use these for:
- Closures — toggle Closed on and set a date range for public holidays or planned shutdowns.
- Extended or reduced hours — set different open/close times for a seasonal period without touching the weekly schedule.
- One-day exceptions — set Date From and Date To to the same date for a single-day override.
Leave Day of Week blank on a date-range rule; the two fields are mutually exclusive — day-of-week is for repeating weekly rules, date range is for bounded overrides.
Setting the regular week #
Appointments → Opening Hours → Edit weekly hours shows all seven days of one location on a single screen. Pick the location, set each day, and save once.
Each day is one of three things, and the difference between the last two matters:
| Status | What it means | Bookable? |
|---|---|---|
| Open | You trade that day, between the times you give. | Yes, within the window |
| Closed | You have decided the location does not open that day. | No |
| Not configured | Nobody has said yet. | No |
Closed and Not configured both refuse bookings, so a half-finished week behaves exactly like a deliberately short one. That is why they are shown apart: a weekend left as Not configured is a gap someone still has to make a decision about, and the weekly screen labels it so you can see which days those are. Set a day back to Not configured to remove its rule entirely.
The weekly editor only ever touches regular day-of-week rules. Holiday and seasonal date-range overrides are left alone by it — see below.
Whose week you may set. These rules are what the public booking page offers, so adding a day to a location's week, or taking one away, is checked at that location — on this screen and everywhere else. Adding needs the Opening Hours create permission there. Removing needs create or edit there, on top of the delete permission: whoever may add days to a site's week may clear them again, but the delete permission on its own is not enough. If your role is scoped to particular sites, picking another one and saving is refused, naming the site and who can give you a role there, and nothing on that site's week is touched.
That covers every route to the same outcome, not just this screen: the per-rule Delete on a location's own page, the bulk delete and restore on the Opening Hours list, and
DELETE /api/v1/location-hours/{id}. So a delete permission held account-wide does not on its own let somebody close another branch's trading week — one rule at a time or all at once.Changing the times on a day that already exists is a different question and is not narrowed this way: an account-wide Opening Hours edit permission edits any site's rules, as it always has.
Managing individual rules #
From Appointments → Opening Hours — the standalone list shows every rule across all locations, including date-range overrides. Use Add a date-range rule for a holiday or seasonal window. The table shows the location name, day, date range, open/close times, and whether the rule marks the location as closed.
From the Location record itself — open any appointment-enabled location (Inventory → Locations → [location]) and find the Opening Hours tab. The inline relation manager lets you create, edit, and delete rules directly on the location's page without navigating away — open the location for editing to use it, since the read-only view page shows the hours without the buttons, for everybody, whatever their role carries. Add there is checked against the location whose page you are on, so a site-scoped role sees it padlocked on somebody else's location rather than adding hours to their booking page.
All three paths manage the same underlying records; use whichever is convenient.
In the REST API these records are still called location hours and are served from
/api/v1/location-hours. The name in the app changed; the API noun did not, so existing scripts keep working.
How the scheduler uses these rules #
When generating available time slots for an appointment type, the system:
- Looks up the date being checked against the location's date-range overrides
(most recent
date_fromwins if multiple ranges overlap). - Falls back to the day-of-week rule for that date's weekday if no date-range rule matches.
- Returns
null(closed / no slots) if the matching rule hasis_closed = trueor if no rule exists at all. - Generates time slots by stepping through the open–close window in increments of the appointment type's duration.
This means you can precisely control availability without touching appointment type configuration — simply adjust the location's hours.
Relationship to other modules #
Opening hours belong to an Inventory Location and gate availability for Appointment Types that are tied to that location. Customers booking through the customer portal only see slots that fall within open hours; slots outside the window are never offered. Loan agreements can also link to appointments, so keeping opening hours accurate ensures that reserved-equipment appointments land on days the location is actually open.
Doing it from the API #
# List all hours rules for a specific location
curl "https://your-domain.com/api/v1/location-hours?location_id=<location-id>" \
-H "Authorization: Bearer $TOKEN"
# Create a recurring day-of-week rule (Monday 08:00–17:00)
curl -X POST "https://your-domain.com/api/v1/location-hours" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"location_id": "<location-id>",
"day_of_week": 1,
"open_time": "08:00",
"close_time": "17:00",
"is_closed": false
}'
# Create a holiday closure (date-range override)
curl -X POST "https://your-domain.com/api/v1/location-hours" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"location_id": "<location-id>",
"label": "Christmas Closure",
"date_from": "2026-12-24",
"date_to": "2026-12-26",
"is_closed": true
}'
Times are sent and returned as
HH:MMstrings (24-hour format). Thelocation_idfilter on the list endpoint accepts the location'sidand is the most efficient way to pull hours for a single location.