Services and availability
Services, multi-resource requirements, schedules and how slots are computed.
Services
A service is what the customer books.
| Field | Meaning |
|---|---|
duration_min | Length of the service |
step_min | Grid for start times (every 15, 30 minutes…) |
buffer_before_min / buffer_after_min | Cleanup or preparation time blocked around the booking |
price_cents, currency | Price shown by the bot (always from the database) |
deposit_cents | Pix deposit required to confirm |
lead_time_min | Minimum notice (for example 60 minutes) |
max_advance_days | How far ahead customers can book |
window_mode | The slot is a fixed window (deliveries: 14:00–16:00) |
fulfillment_mode | scheduled (default, with a time slot) or queue (dispatch by queue, no fixed time) |
intake_form | JSON Schema of extra data to collect (insurance, address…) |
requirements | Which resources the service needs at the same time |
Window or dispatch: two fulfillment modes
Every service defines how the booking is fulfilled (fulfillment_mode):
scheduled(the default): the booking occupies a known time range — a fixed slot or, withwindow_mode, a window (deliveries from 14:00 to 16:00, with capacity per zone).queue(dispatch, for water, gas or on-demand delivery): the booking has no fixed time — it joins a courier's backlog queue. The engine assigns it to the courier with the fewest active tasks, and each courier has a cap on active tasks at a time, enforced in the database. The queue uses the same states as a booking: pending → accepted → started → completed (or failed).
So the same delivery business can offer scheduled windows, immediate dispatch, or both.
Requirements
A requirement says: from this group, I need this many units. A service can have several; a slot exists only if all of them are free.
{
"name": "Laser hair removal",
"duration_min": 45,
"buffer_after_min": 10,
"requirements": [
{ "resource_group_id": "grp_professionals", "units": 1 },
{ "resource_group_id": "grp_lasers", "units": 1 },
{ "resource_group_id": "grp_rooms", "units": 1 }
]
}
With two professionals but only one laser, Wagend will never offer two overlapping laser sessions.
Advanced options:
units: "party_size"— consume as many units as people (restaurants, classes).offset_min/duration_minon a requirement — use a resource for part of the service only (for example the wash basin during the last 15 minutes of a hair color).
Schedules
Each resource has a schedule: weekly rules in the resource's time zone plus overrides for specific dates (closed, or special hours).
{
"tz": "America/Sao_Paulo",
"weekly": { "tue": [["09:00", "19:00"]], "sat": [["08:00", "12:00"], ["13:00", "16:00"]] },
"overrides": [{ "date": "2026-12-24", "ranges": [["09:00", "13:00"]] }, { "date": "2026-12-25", "closed": true }]
}
How slots are computed
- Expand the schedules for the requested range, in each resource's time zone.
- Remove active bookings and holds (plus buffers) and manual blocks.
- Cut into candidate slots using the service duration and step.
- Apply lead time, max advance, cutoff rules and party size.
- Cross all requirements, trying group members according to the assignment strategy.
- Return a short, ordered list.
When nothing is available, the response includes unavailable_reason (closed, no_staff, no_equipment, no_space, lead_time, max_advance, cutoff, full) so the bot can explain why.