Skip to main content

Booking checklists (run sheets & gates)

A booking checklist is a checklist staff work through across a booking. It can be:

  • Flat โ€” a single list completed at one moment: pre-departure (before a product line is picked up), pre-check-in (before an experience line is checked in), or a contents check at return.
  • Sectioned (run sheet) โ€” items grouped into named sections spanning the whole booking ("Before arrival", "Client welcome", "Briefing", "Return & closure"). Each section carries one gate anchor:
    • handover โ€” its items must be complete before pickup / check-in.
    • return โ€” its items must be complete before return / close-out.
    • null โ€” reminder only; never blocks anything.

Which checklists apply to a product or experience is resolved from the supplier's "Applies to" configuration (all products / all experiences / specific products, experiences, or their categories). A line is gated when one or more booking checklists resolve to it. A flat checklist passes its gate when every item is complete with no unresolved critical-item failures; a sectioned run sheet only requires the items anchored to that gate.

A sectioned template produces one checklist instance per line (context: "booking") shared by pickup and return โ€” progress persists across the whole booking, so staff can start "Before arrival" items days ahead and resume anytime. Flat templates keep separate pickup/return instances as before.

A line can resolve multiple applicable checklists. The booking line therefore returns an array of checks, not a single object.

Booking line pickup_checks / return_checks / checkin_checksโ€‹

Each product line carries pickup_checks and return_checks; each experience line carries checkin_checks. All are arrays of check objects โ€” empty when the line is not gated for that action. For a template with no checklist instance started yet, the entry is a not_started stub (no checklist_id); the instance is created lazily by the start endpoint below.

A rental-item extra also carries pickup_checks and return_checks when its linked rental product has applicable checklists. Each extra has its own results, even when two extras use the same product. An extra attached to an experience must pass its pickup checks before that session's check-in and its return checks before close-out. A partial rental pickup or return checks only extras attached to the selected rental lines.

{
"pickup_checks": [
{
"required": true,
"status": "in_progress",
"status_label": "In progress",
"has_critical_failures": false,
"progress": { "completed": 9, "total": 21 },
"gate_progress": { "completed": 4, "total": 7, "has_critical_failures": false },
"sections": [
{ "name": "Client welcome", "gate": "handover", "completed": 4, "total": 4, "has_critical_failures": false },
{ "name": "Return & closure", "gate": "return", "completed": 0, "total": 8, "has_critical_failures": false }
],
"checklist_id": 845,
"template_id": 12,
"template_name": "Watercraft rental run sheet",
"items": [ /* WorkshopChecklistItem objects */ ]
}
]
}
FieldTypeDescription
requiredbooleanThe line is gated for this action. (A sectioned checklist with nothing anchored to the action is omitted from the array.)
statusstringnot_started (no checklist instance yet), or the checklist status: pending, in_progress, completed, completed_with_failures. Reflects the whole checklist.
status_labelstringHuman label for the status.
has_critical_failuresbooleantrue when a critical item anchored to this action has been marked failed. The line is blocked until resolved.
progressobjectWhole-checklist progress: { "completed": <int>, "total": <int> }.
gate_progressobject|nullThe subset that blocks this array's action (handover for pickup_checks/checkin_checks, return for return_checks): { "completed", "total", "has_critical_failures" }. Equal to progress for flat checklists.
sectionsarrayPer-section progress: { name, gate, completed, total, has_critical_failures }. One null-named entry (or empty) for flat checklists.
checklist_idinteger|nullThe checklist instance id. null until the instance is created.
template_idintegerThe applied checklist template.
template_namestringThe template name.
itemsarrayThe checklist items (only populated once an instance exists). Each item carries its section snapshot: section_name, section_sort, section_gate.

The booking object also carries under_checklist_override (boolean) โ€” true once the booking has been handed over via an authorized override (see below).

Running a checklist (mobile)โ€‹

POST /api/v1/mobile/bookings/{id}/checklists/start

Body: { "line_type": "product" | "experience" | "extra", "line_id": <int>, "context": "pickup" | "return" } (context defaults to pickup). Ensures the line's checklist instances exist (idempotent) and returns them with item ids. For a sectioned run sheet, pickup and return resolve the same lifecycle instance. Then complete each item:

PATCH /api/v1/mobile/bookings/{id}/checklists/{checklistId}/items/{itemId}

Body: value (string, optional), notes (string, optional), photo (image, optional). The checklist must belong to a line on the booking, which must belong to the requesting supplier.

To untick an item (reset it to incomplete):

DELETE /api/v1/mobile/bookings/{id}/checklists/{checklistId}/items/{itemId}

The gatesโ€‹

A blocked action returns 422 with a distinct error code so clients can tell a gate block apart from a generic failure:

  • Pickup (/actions/pickup, /items/pickup) โ†’ code: "pickup_gate_blocked" โ€” blocked by incomplete handover-anchored items (or any item of a flat pre-departure checklist).
  • Check-in (/actions/check-in, /manifests/bookings/{id}/check-in, /tickets/redeem) โ†’ code: "checkin_gate_blocked" โ€” same rule for experience lines.
  • Return (/actions/return, /items/return) โ†’ code: "return_gate_blocked" โ€” blocked by incomplete return-anchored items (or a flat contents check on opted-in products).
  • Return on a booking that was never picked up (/actions/return, or PATCH with status: "returned") runs the pickup gate first, because it hands the gear over and back in one go โ†’ code: "pickup_gate_blocked". An override on that return waives both gates.
  • Complete (/actions/complete) โ†’ code: "return_gate_blocked" โ€” experience close-out: return-anchored sections must be complete before the booking is closed.

Reminder sections (gate: null) never block any action.

error.details carries line_type (product, experience, or extra), line_id, and kind (not_started / in_progress / critical_failure). Product, experience, and extra IDs are independent; use both line_type and line_id to find the blocked line.

Overrideโ€‹

Staff with the bookings.checklist_override permission can proceed through a blocked gate anyway by adding to the action request body:

{ "override": true, "override_reason": "..." }

The override is logged once per booking as a checklist_override booking note and surfaced via under_checklist_override. Requests with override: true from users without the permission return 403.

Status valuesโ€‹

StatusMeaning
not_startedThe line is gated but no checklist instance exists yet.
pendingThe checklist exists but no items are complete.
in_progressSome items are complete; not finished. Sectioned run sheets commonly stay in_progress between pickup and return โ€” use gate_progress to decide whether a specific action would pass.
completedEvery item complete with no critical failures.
completed_with_failuresComplete but a critical item failed (has_critical_failures reflects the relevant gate subset).

Template sectionsโ€‹

Checklist template resources include a sections array ({ id, name, gate, sort_order }, empty for flat templates), and template items carry section_id (null = ungrouped). Checklist instance items carry the snapshot fields section_name, section_sort, section_gate so the run sheet stays renderable and gateable even if the template later changes.