Skip to main content

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 supplier
  • 422 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 with 403. The mobile app already sends its own logged-in user id, so this is backward compatible.
  • din_age_bracket — optional. junior | adult | senior. Defaults to adult.
  • values.din_setting — required if din_calculator capability 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 a confirmed_by_user_id was supplied that does not match the authenticated user
  • 404 — booking not found or belongs to a different supplier
  • 422 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_confirmed is the value of record.
  • Customer profile sync. Values whose pack item has sync_to_profile = true are 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 on Booking::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:read
  • confirm_fit — bookings:write