Fit ticket
Endpoints for the ski / snowboard / boot fit ticket attached to a booking. Available when at least one product or experience on the booking has the fit_ticket_capture capability enabled.
Endpoints
GET /api/v1/bookings/{booking_id}/fit-ticket
Returns the resolved fit ticket: pack items (with supplier overrides applied), latest confirmation per participant, customer fit history, and the suggested DIN value.
Scope: bookings:read
Path params:
booking_id(int) — the booking id
Response (200):
{
"data": {
"booking_id": 1234,
"fit_capabilities": {
"fit_ticket_capture": true,
"din_calculator": true
},
"fields": [
{
"id": 7,
"key": "din_setting",
"label": "DIN setting",
"field_type": "number",
"options": null,
"is_required": false,
"help_text": "Calculator suggests; tech must confirm against the binding chart.",
"sort_order": 70
}
],
"tickets": [
{
"participant_id": 99,
"name": "Aanya Patel",
"values": {
"height_cm": "140",
"weight_kg": "35",
"din_setting": "4.5"
},
"history": {
"values": {"height_cm": "138", "weight_kg": "33"},
"last_updated_at": "2026-01-03T14:12:00Z",
"last_booking_id": 999
},
"latest_confirmation": {
"id": 4567,
"confirmed_at": "2026-05-27T09:14:00Z",
"confirmed_by_user_id": 12,
"din_suggested": 4.5,
"din_confirmed": 4.5,
"din_source": "calculator",
"din_age_bracket": "junior"
},
"suggested_din": 4.5
}
],
"pickup_allowed": true
},
"meta": { "request_id": "...", "timestamp": "..." }
}
Errors:
404— booking not found or belongs to a different supplier422 fit_ticket_disabled— no product / experience on the booking has the capability on
POST /api/v1/bookings/{booking_id}/fit-ticket/confirm
Append a fit-confirmation audit row. Same path the supplier portal Livewire UI uses — writes a BookingFitConfirmation row, computes the DIN suggestion server-side for the audit trail, and triggers the customer-profile sync.
Scope: bookings:write
Request body:
{
"participant_id": 99,
"din_age_bracket": "junior",
"values": {
"height_cm": 140,
"weight_kg": 35,
"age": 8,
"ability_level": "beginner",
"foot_size_mondopoint": "23.0",
"boot_sole_length_mm": 250,
"din_setting": 4.5
}
}
participant_id— optional. Omit for a single-fit booking with no participants.confirmed_by_user_id— ignored / derived. The confirming tech / staff member is always taken from your authenticated credentials and written to the append-only audit row server-side — never trusted from the request body. If you do send it, it must equal the authenticated user id; a mismatch is rejected with403. The mobile app already sends its own logged-in user id, so this is backward compatible.din_age_bracket— optional.junior|adult|senior. Defaults toadult.values.din_setting— required ifdin_calculatorcapability is on; pickup is blocked until set.
Authentication: because the confirming staff member is derived from the request principal, this write must be made with a mobile staff token (/api/v1/mobile/bookings/{booking_id}/fit-ticket/confirm). A bare supplier API key has no associated staff user and receives 403 — use API keys for the read-only GET only.
Errors:
403— no authenticated staff user (e.g. a bare API key), or aconfirmed_by_user_idwas supplied that does not match the authenticated user404— booking not found or belongs to a different supplier422 fit_ticket_disabled— no product / experience on the booking has the capability on
Response (201):
{
"data": {
"confirmation_id": 4567,
"confirmed_at": "2026-05-27T09:14:00Z",
"din_suggested": 4.5,
"din_confirmed": 4.5,
"pickup_allowed": true
}
}
Notes
- Append-only. Re-confirming creates a new row. The latest row per participant is the "current" fit.
- DIN safety. The suggestion is from the ISO 11088 / Salomon chart — a tech must verify against the binding manufacturer's chart before rental.
din_confirmedis the value of record. - Customer profile sync. Values whose pack item has
sync_to_profile = trueare upserted into the customer's profile on confirmation, so the next booking's fit ticket can pre-fill from history. Sync fires on confirmation, not onBooking::completed— data persists even if the rental gets cancelled mid-flight. - Cross-supplier isolation. Customer profile fields are scoped per (customer, supplier, key). Cross-supplier data is never shared.
AI Assistant tools
The same endpoints are exposed as Dash AI tools:
get_fit_ticket(read-only) —bookings:readconfirm_fit—bookings:write