Checkout API
Multi-step checkout flow for booking tour packages. Handles session management, selection updates, payment processing, and booking finalization.
Overview
Section titled “Overview”The checkout API provides a stateful multi-step flow:
- Start session - Initialize checkout with offer data
- Select flights - Choose outbound/inbound flights (economy or business)
- Select hotels - Optional hotel upgrades
- Select activities - Optional activity add-ons
- Select transfers - Optional transfer upgrades
- Enter travelers - Passenger personal data
- Payment - Process deposit via Stripe
- Confirmation - View booking summary
Session storage: Server-side PHP session (checkout key)
Base URL: /api/{market}/{lang}/checkout
Session Flow
Section titled “Session Flow”POST /checkout/{offerId} (start) │ ├─► GET /checkout (view session) │ ├─► PUT /checkout/flights ├─► PUT /checkout/hotels ├─► PUT /checkout/activities ├─► PUT /checkout/transfers ├─► PUT /checkout/travelers │ ├─► POST /checkout/payment/intent ├─► POST /checkout/payment/confirm │ └─► GET /checkout/confirmation/{reference}Endpoints
Section titled “Endpoints”POST /checkout/{offerId}
Section titled “POST /checkout/{offerId}”Start checkout session for an offer. Idempotent - returns existing session if same offer.
Response: 201 Created (new) or 200 OK (existing)
{ "success": true, "data": { "offer_id": 123, "started_at": "2026-02-15T10:30:00Z", "base_price": 2499.00, "extras_price": 0.00, "total_price": 2499.00, "pax_count": 2, "currency": { "code": "EUR", "symbol": "EUR" } }}GET /checkout
Section titled “GET /checkout”Get current session state. Returns 404 if no active session.
PUT /checkout/flights
Section titled “PUT /checkout/flights”Update flight selection.
Request:
{ "cabin_class": "ECONOMY", "outbound": { "departure_date": "2026-02-15", "departure_time": "09:10", "arrival_time": "15:15", "departure_airport": "MAD", "arrival_airport": "NBO", "flight_numbers": ["EK123", "EK456"], "airlines": ["EK"], "stops": 1, "stopover_airports": ["DXB"] }, "inbound": { /* same structure */ }, "business_extra_price_per_person": null}PUT /checkout/hotels
Section titled “PUT /checkout/hotels”Update hotel upsell selections.
Request:
{ "hotel_selections": [ { "upsell_hotel_id": 6, "nights_start": 1, "nights_end": 3, "price_difference": 150.00 } ]}PUT /checkout/activities
Section titled “PUT /checkout/activities”Update activity upsell selections. Prices calculated server-side.
Request:
{ "activity_selections": [ { "activity_id": 5, "day_number": 2 } ]}PUT /checkout/transfers
Section titled “PUT /checkout/transfers”Update transfer selections. Prices calculated server-side.
Request:
{ "transfer_selections": [ { "transfer_id": 1, "day_number": 1 } ]}PUT /checkout/travelers
Section titled “PUT /checkout/travelers”Store traveler personal data. Count must match offer’s pax_count.
Request:
{ "travelers": [ { "first_name": "John", "last_name": "Doe", "nationality": "ES", "birth_date": "1990-05-15", "phone": "+34612345678", "email": "john@example.com", "passport_number": "AB1234567", "passport_expiry": "2030-01-01" } ]}GET /checkout/confirmation/{reference}
Section titled “GET /checkout/confirmation/{reference}”Get booking data for confirmation page after successful payment.
Response:
{ "success": true, "data": { "booking_reference": "VOL-2026-00001", "tour_name": "Aventura en Japon", "duration_days": 10, "duration_nights": 9, "travelers": 2, "hero_image": "https://cdn.example.com/japan.jpg", "trip_url": "https://..." }}Price Calculation
Section titled “Price Calculation”Prices update automatically as selections change:
total_price = base_price + extras_price
extras_price = sum of: + business_extra_price_per_person * pax_count + hotel_price_differences + activity_prices * pax_count + transfer_pricesSecurity: Activity and transfer prices are calculated server-side from database. Client-provided prices are ignored.
Payment Flow
Section titled “Payment Flow”See Payment Gateway System for full payment documentation.
Key points:
createIntentuses session’stotal_price(including extras) for deposit calculationconfirmcallsBookingFinalizationService::finalizeFromCheckoutSession()after successful payment- After payment, redirect to
/confirmation/{reference}
Booking Finalization
Section titled “Booking Finalization”After successful payment, BookingFinalizationService finalizes the booking:
- Creates Passenger records from
traveler_data - Attaches passengers to booking via
booking_passengerpivot (first = lead) - Attaches passengers to client via
client_passengerpivot - Creates BookingUpsell records from session selections (hotels, activities, transfers)
- Updates booking prices with
base_price,extras_price,total_amount
Source: backend/app/Services/Booking/BookingFinalizationService.php
Idempotency: If booking already has passengers attached, finalization is skipped.
Error Responses
Section titled “Error Responses”| Code | Error | Description |
|---|---|---|
| 400 | no_checkout_session | No active session, call start first |
| 400 | traveler_data_required | Travelers must be entered before payment |
| 404 | offer_not_found | Offer not found or not active in market |
| 404 | booking_not_found | Booking reference not found |
Source Files
Section titled “Source Files”| Component | File |
|---|---|
| Controller | backend/app/Http/Controllers/Api/CheckoutController.php |
| Payment Controller | backend/app/Http/Controllers/Api/PaymentController.php |
| Session Service | backend/app/Services/Checkout/CheckoutSessionService.php |
| Finalization Service | backend/app/Services/Booking/BookingFinalizationService.php |
| Form Requests | backend/app/Http/Requests/Api/Checkout/ |
Related
Section titled “Related”- Payment Gateway System - Payment processing
- Bookings - Booking data model
- Swagger: http://localhost/api/documentation