Bookable
A bookable is the thing you reserve. Meeting rooms, desks, vehicles, parking spaces, charging stations, market stalls. If it sits in the real world and can be claimed for a window of time, it is a bookable. Everything else in the platform either configures bookables, decorates them, or records what happened to them.
A bookable optionally carries a Bookable Type for grouping, any number of capabilities for room features and executable behaviors, and any number of timeslots that constrain when it can be booked. Bookings live in their own table and reference the bookable through bookable_id.
Timeslots
A timeslot attached directly to the bookable is what defines its open hours. See Schedule for the rule shape and the meaning of available.
INFO
A bookable with no directly attached timeslot is open at all times. Only timeslots bound straight to the bookable are read for availability; timeslots on the bookable type, location or organization don't propagate. For office hours, attach the timeslot to the bookable itself.
Reading time on a bookable
There are three ways to read time on a bookable, and they answer different questions.
GET /bookable/{id}/booking returns the booking rows as they sit in the database. A recurring booking is one row with a recurrence pattern in its schedule; expand the pattern on the client if you need per occurrence data. Use this when you want the records.
GET /bookable/{id}/calendar walks a queried window and returns one entry per occurrence, so a single recurring row can produce many entries. Use this to render a timetable.
GET /bookable/{id}/available returns the free surface inside a queried window: the bookable's timeslots minus what is already booked. Use this to show open slots or to sanity check a candidate booking before posting.
See Calendar and Availability for how the calendar and available views are computed.
API
The Bookable tag covers CRUD on the bookable, the three time views above, attached capabilities and timeslots, and actions bound at this level.