Bookings
Book a Boat
Reserve a boat and create a booking with payment
Booking is a two-step process:
- Reserve -- check availability and get confirmed pricing
- Create and Pay -- create the booking record and Stripe PaymentIntent
Both steps require session authentication.
Step 1: Reserve
POST
/bookings/reserveValidates the boat, checks availability (including live checks against external booking systems), resolves pricing from seasonal rates, and returns the confirmed price. Does not create a booking or hold dates.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
boat_id | string | Yes | ID of the boat to book |
start_date | string | Yes | Start date (YYYY-MM-DD) |
end_date | string | Yes | End date (YYYY-MM-DD) |
guest_count | integer | No | Number of guests (validated against boat capacity) |
Request
Response
Response Fields
| Field | Type | Description |
|---|---|---|
available | boolean | Always true (errors thrown if unavailable) |
confirmedPrice | number | Final charter price for the date range |
nights | integer | Number of nights |
priceUpdated | boolean | true if the live price differs from stored seasonal pricing |
Errors
| Status | Message |
|---|---|
400 | Missing required fields: boat_id, start_date, end_date |
400 | This boat is not available for booking |
400 | Maximum capacity is N guests |
400 | Check-in is only available on Saturday |
400 | Minimum charter duration is N days |
400 | You cannot book your own company's boat |
401 | Authentication required |
404 | Boat not found |
409 | These dates are no longer available |
502 | Could not verify availability. Please try again. |
Step 2: Create and Pay
POST
/bookings/create-and-payCreates the booking record, holds dates on external booking systems, resolves fees, and creates a Stripe PaymentIntent. The client uses the returned clientSecret to complete payment via Stripe Elements.
After payment succeeds on the client, call POST /bookings/{id}/confirm to finalize.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
boat_id | string | Yes | ID of the boat to book |
start_date | string | Yes | Start date (YYYY-MM-DD) |
end_date | string | Yes | End date (YYYY-MM-DD) |
guest_count | integer | No | Number of guests |
guest_first_name | string | No | Guest first name (defaults to auth user's name) |
guest_last_name | string | No | Guest last name (defaults to auth user's name) |
guest_email | string | No | Guest email (defaults to auth user's email) |
guest_phone | string | No | Guest phone number |
selected_optional_fee_ids | string[] | No | IDs of optional fees the guest selected |
coupon_code | string | No | Coupon code to apply |
Request
Response
Response Fields
| Field | Type | Description |
|---|---|---|
bookingId | string | Created booking ID (UUID) |
clientSecret | string | Stripe PaymentIntent client secret for completing payment |
paymentIntentId | string | Stripe PaymentIntent ID |
confirmedPrice | number | Charter base price |
confirmedCurrency | string | Currency code (EUR or USD) |
totalPrice | number | Total amount charged (charter + required fees + optional fees + service fee - coupon) |
holdExpiresAt | string | When the date hold expires (15 minutes for direct/Nausys boats) |
priceChanged | boolean | true if the live price differs from the earlier reserve check |
previousPrice | number | Previous charter price (only present when priceChanged is true) |
previousTotal | number | Previous total (only present when priceChanged is true) |
fees | object | Detailed fee breakdown |
fees.charter | number | Base charter price |
fees.requiredFees | array | Mandatory fees (cleaning, transit, etc.) |
fees.optionalFees | array | Guest-selected optional fees |
fees.serviceFee | number | Flat platform service fee ($45) |
fees.couponDiscount | number | Discount amount from coupon |
fees.couponCode | string | Applied coupon code, or null |
Booking Status After Creation
| Boat Type | Initial Status | Reason |
|---|---|---|
| External (Nausys/MMK) | accepted | Dates are held as an option on the external system |
| Direct (instant book) | accepted | Moves to confirmed after payment |
| Direct (standard) | pending | Requires owner approval |
Errors
| Status | Message |
|---|---|
400 | Missing required fields: boat_id, start_date, end_date |
400 | This boat is not available for booking |
400 | Maximum capacity is N guests |
400 | Check-in is only available on Saturday |
400 | Minimum charter duration is N days |
400 | You cannot book your own company's boat |
400 | These dates are no longer available |
401 | Authentication required |
404 | Boat not found |
500 | Failed to create booking |
502 | Could not reserve dates. Please try again. |
502 | Payment setup failed. Please try again. |