{"swagger":"2.0","info":{"version":"v1","title":"NYC Limousine API","description":"AI-ready booking API for NYC Limousine services. This API uses a two-layer discovery model:\n\n**Layer 1 (Snapshot):** GET /v1/rates/snapshot — Instant, cached pricing for common routes. Use this FIRST for quick price discovery.\n\n**Layer 2 (Deep Dive):** POST /v1/quotes/calculate — Exact, real-time pricing with tolls, taxes, and surcharges. Use this when the customer is ready for an exact quote.\n\n**Booking Flow:**\n1. GET /v1/rates/snapshot → Show ballpark prices\n2. POST /v1/quotes/calculate → Get exact pricing (may return 422 if terminal needed)\n3. POST /v1/bookings → Create booking → Returns payment URL\n4. GET /v1/bookings/{id} → Check status / get confirmation number","termsOfService":"https://nyclimousine.com/terms","contact":{"name":"NYC Limousine","url":"https://nyclimousine.com"}},"host":"nyclimousine.com","basePath":"/api","schemes":["https"],"paths":{"/v1/mgmt/2fa/send":{"post":{"tags":["Admin2FA"],"operationId":"Admin2FA_Send","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/Admin2FAEmailRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/2fa/verify":{"post":{"tags":["Admin2FA"],"operationId":"Admin2FA_Verify","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/Admin2FAVerifyRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/2fa/check":{"post":{"tags":["Admin2FA"],"operationId":"Admin2FA_Check","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/Admin2FACheckRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/bookings":{"post":{"tags":["Bookings"],"summary":"Create a new booking from a previously calculated quote.\r\n            \r\nIMPORTANT: This creates a booking in \"pending_payment\" status.\r\nThe customer MUST complete payment at the returned payment_url.\r\nOnce payment is confirmed, the ride is dispatched and a confirmation_number is assigned.\r\n            \r\nThe quote_id and session_token must match a valid, non-expired quote\r\nfrom POST /v1/quotes/calculate.","operationId":"Bookings_CreateBooking","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","description":"Booking details including quote_id, vehicle_id, passenger info, and optional flight/amenity details.","required":true,"schema":{"$ref":"#/definitions/BookingRequest"}}],"responses":{"201":{"description":"Booking created. Redirect customer to payment_url.","schema":{"$ref":"#/definitions/BookingResponse"}},"400":{"description":"Validation error — missing required fields.","schema":{"$ref":"#/definitions/ErrorResponse"}},"403":{"description":"Session token does not match the quote.","schema":{"$ref":"#/definitions/ErrorResponse"}},"404":{"description":"Quote not found. Create a new quote first.","schema":{"$ref":"#/definitions/ErrorResponse"}},"410":{"description":"Quote expired — recalculate pricing.","schema":{"$ref":"#/definitions/ErrorResponse"}},"500":{"description":"Internal server error during booking creation."}}}},"/v1/bookings/secure":{"post":{"tags":["Bookings"],"operationId":"Bookings_CreateSecureBooking","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/SecureBookingRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}},"201":{"description":"Booking confirmed with real ECL confirmation number.","schema":{"$ref":"#/definitions/BookingResponse"}},"400":{"description":"Missing or invalid fields.","schema":{"$ref":"#/definitions/ErrorResponse"}}}}},"/v1/bookings/{id}":{"get":{"tags":["Bookings"],"summary":"Check the status of a booking by its reservation ID.\r\n            \r\nPossible statuses:\r\n- \"pending_payment\" — waiting for customer to complete payment at payment_url\r\n- \"payment_received\" — payment completed, awaiting dispatch\r\n- \"confirmed\" — dispatched to driver, confirmation_number available\r\n- \"payment_expired\" — payment link expired, booking not completed","operationId":"Bookings_GetBooking","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","description":"Reservation ID from POST /v1/bookings response.","required":true,"type":"string"}],"responses":{"200":{"description":"Booking found. Check the 'status' field for current state.","schema":{"$ref":"#/definitions/BookingResponse"}},"404":{"description":"Booking not found."}}}},"/v1/bookings/{id}/dispatch":{"post":{"tags":["Bookings"],"summary":"Dispatch a paid booking to ECL (East Coast Limousine) for driver assignment.\r\n            \r\nPrerequisites:\r\n- Booking must exist\r\n- Payment must be completed (status = \"payment_received\")\r\n- Booking must not already be dispatched\r\n            \r\nOn success, the booking moves to \"confirmed\" status with a confirmation_number\r\nfrom the dispatch system.","operationId":"Bookings_DispatchBooking","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","description":"Reservation ID from POST /v1/bookings response.","required":true,"type":"string"}],"responses":{"200":{"description":"Booking dispatched. confirmation_number assigned.","schema":{"$ref":"#/definitions/BookingResponse"}},"400":{"description":"Payment not completed or invalid booking ID.","schema":{"$ref":"#/definitions/ErrorResponse"}},"404":{"description":"Booking not found.","schema":{"$ref":"#/definitions/ErrorResponse"}},"409":{"description":"Already dispatched — no action needed.","schema":{"$ref":"#/definitions/ErrorResponse"}},"502":{"description":"ECL dispatch failed. Retry is safe.","schema":{"$ref":"#/definitions/ErrorResponse"}},"500":{"description":"Internal server error during dispatch.","schema":{"$ref":"#/definitions/ErrorResponse"}}}}},"/v1/bookings/{id}/messages":{"post":{"tags":["Bookings"],"operationId":"Bookings_SendMessage","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","required":true,"type":"string"},{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/BookingMessageRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/register":{"post":{"tags":["Customer"],"summary":"Register a new customer account with email and password.","operationId":"Customer_Register","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/CustomerRegisterRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/login":{"post":{"tags":["Customer"],"summary":"Log in with email and password.","operationId":"Customer_Login","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/CustomerLoginRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/google-login":{"post":{"tags":["Customer"],"summary":"Log in or register with a Google OAuth ID token.","operationId":"Customer_GoogleLogin","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/GoogleLoginRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/refresh":{"post":{"tags":["Customer"],"summary":"Exchange a refresh token for a new access token (token rotation).","operationId":"Customer_Refresh","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/RefreshRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/logout":{"post":{"tags":["Customer"],"summary":"Log out and revoke the refresh token.","operationId":"Customer_Logout","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/RefreshRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/forgot-password":{"post":{"tags":["Customer"],"operationId":"Customer_ForgotPassword","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/ForgotPasswordRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/reset-password":{"post":{"tags":["Customer"],"operationId":"Customer_ResetPassword","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/ResetPasswordRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/profile":{"get":{"tags":["Customer"],"summary":"Get the authenticated customer's profile.","operationId":"Customer_GetProfile","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"customerId","in":"query","required":false,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/profile/update":{"post":{"tags":["Customer"],"operationId":"Customer_UpdateProfile","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/UpdateProfileRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/reservations":{"get":{"tags":["Customer"],"summary":"Get paginated reservation history for the authenticated customer.","operationId":"Customer_GetReservations","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"customerEmail","in":"query","required":false,"type":"string"},{"name":"page","in":"query","required":false,"type":"integer","format":"int32"},{"name":"pageSize","in":"query","required":false,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/customer/reservations/{id}":{"get":{"tags":["Customer"],"summary":"Get a single reservation detail by ID (must belong to the authenticated customer).","operationId":"Customer_GetReservation","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"},{"name":"customerEmail","in":"query","required":false,"type":"string"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/flights/lookup":{"get":{"tags":["Flights"],"operationId":"Flights_Lookup","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"flight","in":"query","required":true,"type":"string"},{"name":"date","in":"query","required":false,"type":"string"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/intel/daily":{"get":{"tags":["Intel"],"summary":"Get today's NYC travel intelligence.\r\n            \r\nReturns 3 travel tips (weather, traffic, events) plus a ready-to-use\r\nsocial media post. Data is scraped from 16 NYC sources and summarized\r\nby AI daily at 6 AM ET.\r\n            \r\nAI agents: Use this to provide real-time NYC context to travelers.\r\nExample: \"It's raining in NYC today — consider booking a limo instead of walking.\"","operationId":"Intel_GetDailyIntel","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"responses":{"200":{"description":"Today's NYC travel intel."},"404":{"description":"No intel data available yet."},"500":{"description":"Server error reading intel data."}}}},"/v1/intel":{"get":{"tags":["Intel"],"summary":"Get metadata about the intel service.","operationId":"Intel_GetInfo","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"responses":{"200":{"description":"Intel service metadata."}}}},"/v1/mgmt/jlimo-upload":{"post":{"tags":["JlimoUpload"],"operationId":"JlimoUpload_Upload","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/jlimo-upload/history":{"get":{"tags":["JlimoUpload"],"operationId":"JlimoUpload_History","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/jlimo-upload/detail/{uploadId}":{"get":{"tags":["JlimoUpload"],"operationId":"JlimoUpload_Detail","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"uploadId","in":"path","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/locations/resolve":{"get":{"tags":["Locations"],"operationId":"Locations_Resolve","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"q","in":"query","required":true,"type":"string"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/quotes":{"get":{"tags":["PriceQuote"],"operationId":"PriceQuote_ListQuotes","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}},"post":{"tags":["PriceQuote"],"operationId":"PriceQuote_CreateQuote","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/PriceQuoteRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/pq/{token}":{"get":{"tags":["PriceQuote"],"operationId":"PriceQuote_GetQuoteByLink","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"token","in":"path","required":true,"type":"string"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/pq/{token}/book":{"post":{"tags":["PriceQuote"],"operationId":"PriceQuote_MarkQuoteBooked","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"token","in":"path","required":true,"type":"string"},{"name":"body","in":"body","required":true,"schema":{"$ref":"#/definitions/QuoteBookRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/quotes/{id}/status":{"post":{"tags":["PriceQuote"],"operationId":"PriceQuote_UpdateQuote","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"},{"name":"body","in":"body","required":true,"schema":{"$ref":"#/definitions/QuoteStatusUpdate"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/quotes/{id}/edit":{"post":{"tags":["PriceQuote"],"operationId":"PriceQuote_EditQuote","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"},{"name":"body","in":"body","required":true,"schema":{"$ref":"#/definitions/QuoteEditRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/mgmt/quotes/{id}":{"delete":{"tags":["PriceQuote"],"operationId":"PriceQuote_DeleteQuote","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/quotes/calculate":{"post":{"tags":["Quotes"],"summary":"Calculate exact pricing for a specific trip.\r\n            \r\nThis endpoint validates locations, calculates distances via Google Maps,\r\nand returns per-vehicle pricing using the same rate engine as nyclimousine.com.\r\n            \r\nIMPORTANT: If the pickup or dropoff is an airport, you MUST include the\r\nterminal number (e.g., \"JFK Airport Terminal 4\"). Otherwise you will receive\r\na 422 response with available terminals — resubmit with the terminal included.","operationId":"Quotes_Calculate","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","description":"Trip details including from, to, date, time, and service type.","required":true,"schema":{"$ref":"#/definitions/QuoteRequest"}}],"responses":{"200":{"description":"Quote calculated successfully with per-vehicle pricing.","schema":{"$ref":"#/definitions/QuoteResponse"}},"400":{"description":"Validation error — missing or invalid fields.","schema":{"$ref":"#/definitions/ErrorResponse"}},"422":{"description":"Airport terminal required. Check 'options' for valid terminals and resubmit.","schema":{"$ref":"#/definitions/ErrorResponse"}},"500":{"description":"Internal server error during quote calculation."}}}},"/v1/quotes/{id}":{"get":{"tags":["Quotes"],"summary":"Retrieve a previously calculated quote by its ID.\r\nQuotes expire after 24 hours.","operationId":"Quotes_GetQuote","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"id","in":"path","description":"The quote_id from a previous calculate response.","required":true,"type":"string"}],"responses":{"200":{"description":"Quote found with pricing details.","schema":{"$ref":"#/definitions/QuoteResponse"}},"404":{"description":"Quote not found or has expired."}}}},"/v1/receipts/send":{"post":{"tags":["Receipt"],"operationId":"Receipt_SendReceipt","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/ReceiptRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/routes/estimate":{"post":{"tags":["Routes"],"operationId":"Routes_Estimate","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/RouteEstimateRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/routes/tour-estimate":{"post":{"tags":["Routes"],"operationId":"Routes_TourEstimate","consumes":["application/json","text/json","application/xml","text/xml","application/x-www-form-urlencoded"],"produces":["application/json","text/json","application/xml","text/xml"],"parameters":[{"name":"request","in":"body","required":true,"schema":{"$ref":"#/definitions/TourEstimateRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}}}}},"/v1/rates/snapshot":{"get":{"tags":["Snapshot"],"summary":"Get pre-computed snapshot rates for common NYC limousine routes.\r\n            \r\nThis is the primary discovery endpoint for AI agents (Gemini, ChatGPT, Perplexity).\r\nUse this to instantly show users \"starting at\" prices without any API cost.\r\n            \r\nFor exact all-in pricing with tolls and surcharges, use POST /v1/quotes/calculate.","operationId":"Snapshot_GetSnapshot","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"responses":{"200":{"description":"Cached snapshot rates for common routes. 24-hour cache.","schema":{"$ref":"#/definitions/SnapshotResponse"}},"500":{"description":"Server error retrieving snapshot rates."}}}},"/v1/vehicles":{"get":{"tags":["Vehicles"],"summary":"List all available vehicle types for NYC Limousine service.\r\nThis is a public endpoint — no authentication required.\r\nReturns vehicles with capacity, descriptions, and images,\r\nplus a global list of available amenity add-ons.\r\nUse the vehicle_id from this response when creating a booking.","operationId":"Vehicles_GetVehicles","consumes":[],"produces":["application/json","text/json","application/xml","text/xml"],"responses":{"200":{"description":"List of available vehicles and amenities.","schema":{"$ref":"#/definitions/VehicleListResponse"}},"500":{"description":"Server error retrieving vehicles."}}}}},"definitions":{"Admin2FAEmailRequest":{"type":"object","properties":{"email":{"type":"string"}}},"Admin2FAVerifyRequest":{"type":"object","properties":{"email":{"type":"string"},"code":{"type":"string"}}},"Admin2FACheckRequest":{"type":"object","properties":{"trustToken":{"type":"string"}}},"BookingRequest":{"description":"Request body for POST /v1/bookings — create a booking from a quote.\r\nRequires API key authentication and a valid quote_id from POST /v1/quotes/calculate.","required":["quoteId","sessionToken","vehicleId","passenger"],"type":"object","properties":{"quoteId":{"description":"Quote ID from a previous /v1/quotes/calculate response.","type":"string"},"sessionToken":{"description":"Session token from the quote response.","type":"string"},"vehicleId":{"format":"int32","description":"Selected vehicle ID from the quote's vehicles array.","type":"integer"},"vehicleColor":{"description":"Preferred vehicle color (from vehicle's colors array). Optional.","type":"string"},"passenger":{"$ref":"#/definitions/PassengerInfo","description":"Passenger details."},"passengersCount":{"format":"int32","description":"Number of passengers riding.","type":"integer"},"luggageCount":{"format":"int32","description":"Number of luggage pieces.","type":"integer"},"specialInstructions":{"description":"Special instructions for the driver.","type":"string"},"flight":{"$ref":"#/definitions/FlightInfo","description":"Flight information (required if pickup/dropoff is at an airport)."},"amenities":{"description":"Selected amenities (WiFi, water bottles, etc.).","type":"array","items":{"$ref":"#/definitions/AmenitySelection"}}}},"PassengerInfo":{"description":"Passenger contact information.","required":["firstName","lastName","email","phone"],"type":"object","properties":{"prefix":{"description":"Title prefix (Mr, Mrs, Ms, Dr).","type":"string"},"firstName":{"description":"First name.","type":"string"},"lastName":{"description":"Last name.","type":"string"},"email":{"description":"Email address.","type":"string"},"phone":{"description":"Phone number (e.g., \"+12125551234\").","type":"string"},"mobile":{"description":"Mobile/cell number.","type":"string"}}},"FlightInfo":{"description":"Flight details for airport pickups/dropoffs.","type":"object","properties":{"airline":{"description":"Airline name (e.g., \"Delta\").","type":"string"},"flightNumber":{"description":"Flight number (e.g., \"DL123\").","type":"string"},"departureCity":{"description":"Departure city code (e.g., \"LAX\").","type":"string"},"scheduledTime":{"description":"Scheduled arrival/departure time (HH:MM).","type":"string"},"type":{"description":"Flight type: \"domestic\" (default) or \"international\".","type":"string"}}},"AmenitySelection":{"description":"An amenity/add-on selection.","type":"object","properties":{"name":{"description":"Amenity name (must match available amenity from vehicle details).","type":"string"},"quantity":{"format":"int32","description":"Quantity requested.","type":"integer"}}},"BookingResponse":{"description":"Response from POST /v1/bookings — booking created, pending payment.\r\nThe customer must complete payment at the payment_url to confirm the booking.","type":"object","properties":{"bookingId":{"description":"Unique booking identifier (same as reservation_id).","type":"string"},"reservationId":{"format":"int32","description":"Database reservation ID. Use this to check status via GET /v1/bookings/{reservation_id}.","type":"integer"},"status":{"description":"Booking status:\r\n- \"pending_payment\" — waiting for customer to pay via payment_url\r\n- \"confirmed\" — payment received, ride dispatched, confirmation_number available\r\n- \"cancelled\" — booking was cancelled","type":"string"},"paymentUrl":{"description":"Stripe checkout URL. Direct the customer here to complete payment.\r\nThe booking is NOT confirmed until payment is completed.","type":"string"},"paymentExpiresAt":{"format":"date-time","description":"When the payment link expires.","type":"string"},"quoteSummary":{"$ref":"#/definitions/BookingQuoteSummary","description":"Summary of the quoted vehicle and total price."},"confirmationNumber":{"description":"Dispatch confirmation number from the ride provider.\r\nOnly available after payment is completed (status = \"confirmed\").","type":"string"},"passengerName":{"description":"Passenger name for the booking.","type":"string"},"pickup":{"format":"date-time","description":"Pickup date and time.","type":"string"},"fromLocation":{"description":"Pickup location.","type":"string"},"toLocation":{"description":"Dropoff location.","type":"string"},"flightVerified":{"type":"boolean"},"flightDetails":{"$ref":"#/definitions/BookingFlightDetails"}}},"BookingQuoteSummary":{"description":"Summary of the quote associated with a booking.","type":"object","properties":{"vehicle":{"description":"Vehicle name.","type":"string"},"total":{"format":"double","description":"Total price to be charged.","type":"number"},"currency":{"description":"Currency (always \"USD\").","type":"string"}}},"BookingFlightDetails":{"type":"object","properties":{"flight":{"type":"string"},"airline":{"type":"string"},"originCode":{"type":"string"},"originCity":{"type":"string"},"destinationCode":{"type":"string"},"destinationCity":{"type":"string"},"scheduledDeparture":{"type":"string"},"scheduledArrival":{"type":"string"},"status":{"type":"string"},"isDomestic":{"type":"boolean"},"isDelayed":{"type":"boolean"},"delayMinutes":{"format":"int32","type":"integer"}}},"ErrorResponse":{"description":"Standard error response. For 422 errors, includes a recovery_prompt\r\nthat AI agents can use to fix the request and retry.","type":"object","properties":{"error":{"description":"Error code (e.g., \"terminal_required\", \"invalid_location\", \"validation_error\").","type":"string"},"message":{"description":"Human-readable error message.","type":"string"},"recoveryPrompt":{"description":"AI-friendly recovery prompt. When present, the AI should present this\r\nto the user and resubmit with the corrected information.","type":"string"},"field":{"description":"Which field caused the error (\"from\", \"to\", etc.).","type":"string"},"options":{"description":"Available options to fix the error (e.g., terminal numbers).","type":"array","items":{"type":"string"}},"suggestion":{"description":"Suggested corrected input.","type":"string"}}},"SecureBookingRequest":{"required":["payment","quoteId","sessionToken","vehicleId","passenger"],"type":"object","properties":{"payment":{"$ref":"#/definitions/PaymentCard"},"quoteId":{"description":"Quote ID from a previous /v1/quotes/calculate response.","type":"string"},"sessionToken":{"description":"Session token from the quote response.","type":"string"},"vehicleId":{"format":"int32","description":"Selected vehicle ID from the quote's vehicles array.","type":"integer"},"vehicleColor":{"description":"Preferred vehicle color (from vehicle's colors array). Optional.","type":"string"},"passenger":{"$ref":"#/definitions/PassengerInfo","description":"Passenger details."},"passengersCount":{"format":"int32","description":"Number of passengers riding.","type":"integer"},"luggageCount":{"format":"int32","description":"Number of luggage pieces.","type":"integer"},"specialInstructions":{"description":"Special instructions for the driver.","type":"string"},"flight":{"$ref":"#/definitions/FlightInfo","description":"Flight information (required if pickup/dropoff is at an airport)."},"amenities":{"description":"Selected amenities (WiFi, water bottles, etc.).","type":"array","items":{"$ref":"#/definitions/AmenitySelection"}}}},"PaymentCard":{"required":["cardNumber","expiryMonth","expiryYear","cvv","cardholderName","billingZip"],"type":"object","properties":{"cardNumber":{"type":"string"},"expiryMonth":{"type":"string"},"expiryYear":{"type":"string"},"cvv":{"type":"string"},"cardholderName":{"type":"string"},"billingAddress":{"type":"string"},"billingCity":{"type":"string"},"billingState":{"type":"string"},"billingZip":{"type":"string"},"billingCountry":{"type":"string"}}},"BookingMessageRequest":{"required":["message"],"type":"object","properties":{"message":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"}}},"CustomerRegisterRequest":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"}}},"CustomerLoginRequest":{"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"}}},"GoogleLoginRequest":{"type":"object","properties":{"idToken":{"type":"string"}}},"RefreshRequest":{"type":"object","properties":{"refreshToken":{"type":"string"}}},"ForgotPasswordRequest":{"type":"object","properties":{"email":{"type":"string"}}},"ResetPasswordRequest":{"type":"object","properties":{"token":{"type":"string"},"newPassword":{"type":"string"}}},"UpdateProfileRequest":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"}}},"PriceQuoteRequest":{"type":"object","properties":{"fromAddress":{"type":"string"},"toAddress":{"type":"string"},"fromName":{"type":"string"},"toName":{"type":"string"},"fromZip":{"type":"string"},"toZip":{"type":"string"},"pickupDate":{"type":"string"},"pickupTime":{"type":"string"},"serviceType":{"type":"string"},"passengers":{"format":"int32","type":"integer"},"luggage":{"format":"int32","type":"integer"},"distanceMiles":{"format":"double","type":"number"},"durationMinutes":{"format":"int32","type":"integer"},"vehicleId":{"format":"int32","type":"integer"},"vehicleName":{"type":"string"},"vehicleCode":{"type":"string"},"originalBaseFare":{"format":"double","type":"number"},"originalTotal":{"format":"double","type":"number"},"tolls":{"format":"double","type":"number"},"airportParking":{"format":"double","type":"number"},"salesTax":{"format":"double","type":"number"},"extraChargesJson":{"type":"string"},"overrideBaseFare":{"format":"double","type":"number"},"discountType":{"type":"string"},"discountValue":{"format":"double","type":"number"},"discountAmount":{"format":"double","type":"number"},"finalTotal":{"format":"double","type":"number"},"apiQuoteId":{"type":"string"},"fullApiResponseJson":{"type":"string"},"customerName":{"type":"string"},"customerEmail":{"type":"string"},"customerPhone":{"type":"string"},"expiryDays":{"format":"int32","type":"integer"},"maxUses":{"format":"int32","type":"integer"},"requireLogin":{"type":"boolean"},"adminNotes":{"type":"string"}}},"QuoteBookRequest":{"type":"object","properties":{"reservationId":{"format":"int32","type":"integer"}}},"QuoteStatusUpdate":{"type":"object","properties":{"status":{"type":"string"}}},"QuoteEditRequest":{"type":"object","properties":{"customerName":{"type":"string"},"customerEmail":{"type":"string"},"customerPhone":{"type":"string"},"adminNotes":{"type":"string"},"expiresAt":{"format":"date-time","type":"string"},"discountType":{"type":"string"},"discountValue":{"format":"double","type":"number"},"discountAmount":{"format":"double","type":"number"},"finalTotal":{"format":"double","type":"number"}}},"QuoteRequest":{"description":"Request body for POST /v1/quotes/calculate — get exact pricing for a specific trip.\r\n            \r\nAI agents: If picking up at an airport, you MUST include the terminal number\r\nin the \"from\" field (e.g., \"JFK Airport Terminal 4\"). If omitted, you will\r\nreceive a 422 response with a list of valid terminals.","required":["pickupDate","pickupTime"],"type":"object","properties":{"from":{"description":"Pickup location. For airports, include the terminal (e.g., \"JFK Airport Terminal 4\").\r\nFor addresses, use a full address (e.g., \"350 5th Ave, New York, NY 10118\").","type":"string"},"to":{"description":"Dropoff location. Same format as \"from\".","type":"string"},"fromLocation":{"$ref":"#/definitions/LocationInput"},"toLocation":{"$ref":"#/definitions/LocationInput"},"pickupDate":{"description":"Pickup date in YYYY-MM-DD format. Must be today or later.","type":"string"},"pickupTime":{"description":"Pickup time in HH:MM (24-hour) format.","type":"string"},"serviceType":{"description":"Service type: \"one_way\", \"hourly\", \"roundtrip\", or \"wait_and_return\".\r\nDefault: \"one_way\".","type":"string"},"passengers":{"format":"int32","description":"Number of passengers (used for vehicle capacity filtering).","type":"integer"},"luggage":{"format":"int32","description":"Number of luggage pieces.","type":"integer"},"returnDate":{"description":"Return date in YYYY-MM-DD format (required for \"roundtrip\" service type).","type":"string"},"returnTime":{"description":"Return time in HH:MM (24-hour) format (required for \"roundtrip\" service type).","type":"string"},"hourlyHours":{"format":"int32","description":"Number of hours for hourly service (required when service_type is \"hourly\").\r\nMinimum: 2 hours.","type":"integer"},"hourlyEvent":{"format":"int32","description":"Event type ID for hourly service. Get available events from the quote response.","type":"integer"},"stops":{"type":"array","items":{"$ref":"#/definitions/QuoteStop"}}}},"LocationInput":{"type":"object","properties":{"displayValue":{"type":"string"},"name":{"type":"string"},"dbLocationId":{"format":"int32","type":"integer"},"dbLocationName":{"type":"string"},"dbLocationCode":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zipcode":{"type":"string"},"lat":{"format":"double","type":"number"},"lng":{"format":"double","type":"number"},"placeId":{"type":"string"},"locationType":{"type":"string"},"isAirport":{"type":"boolean"},"terminal":{"type":"string"}}},"QuoteStop":{"type":"object","properties":{"location":{"type":"string"},"waitingMinutes":{"format":"int32","type":"integer"}}},"QuoteResponse":{"description":"Response from POST /v1/quotes/calculate — exact pricing for all available vehicles.\r\nUse the quote_id and session_token when creating a booking via POST /v1/bookings.","type":"object","properties":{"quoteId":{"description":"Unique quote identifier. Pass this to POST /v1/bookings.","type":"string"},"sessionToken":{"description":"Session token linking this quote to a booking. Required for POST /v1/bookings.","type":"string"},"expiresAt":{"format":"date-time","description":"When this quote expires (typically 24 hours). Prices may change after expiry.","type":"string"},"from":{"$ref":"#/definitions/LocationDetail","description":"Validated pickup location details."},"to":{"$ref":"#/definitions/LocationDetail","description":"Validated dropoff location details."},"pickup":{"format":"date-time","description":"Pickup date and time.","type":"string"},"serviceType":{"description":"Service type requested.","type":"string"},"distanceMiles":{"format":"double","description":"Calculated trip distance in miles.","type":"number"},"durationMinutes":{"format":"int32","description":"Estimated trip duration in minutes.","type":"integer"},"vehicles":{"description":"Array of available vehicles with exact pricing.","type":"array","items":{"$ref":"#/definitions/QuoteVehicle"}}}},"LocationDetail":{"description":"Validated location details.","type":"object","properties":{"name":{"description":"Location name.","type":"string"},"address":{"description":"Full address.","type":"string"},"city":{"description":"City.","type":"string"},"state":{"description":"State abbreviation.","type":"string"},"zip":{"description":"ZIP code.","type":"string"},"type":{"description":"Location type: \"airport\", \"transit\", \"address\", or \"venue\".","type":"string"},"code":{"description":"Airport/venue code if applicable.","type":"string"},"terminal":{"description":"Terminal number if airport.","type":"string"}}},"QuoteVehicle":{"description":"A single vehicle option with exact pricing.","type":"object","properties":{"vehicleId":{"format":"int32","description":"Vehicle ID to use when booking.","type":"integer"},"name":{"description":"Display name (e.g., \"Luxury Sedan\").","type":"string"},"code":{"description":"Vehicle code (e.g., \"SEDN\").","type":"string"},"description":{"description":"Vehicle description.","type":"string"},"imageUrl":{"description":"URL to vehicle exterior image.","type":"string"},"interiorImageUrl":{"description":"URL to vehicle interior image.","type":"string"},"maxPassengers":{"format":"int32","description":"Maximum passenger capacity.","type":"integer"},"maxLuggage":{"format":"int32","description":"Maximum luggage capacity.","type":"integer"},"colors":{"description":"Available vehicle colors.","type":"array","items":{"type":"string"}},"pricing":{"$ref":"#/definitions/PricingDetail","description":"Exact pricing breakdown for this vehicle on this route."},"amenities":{"description":"Available amenities/add-ons for this vehicle on this route. Null if none available.","type":"array","items":{"$ref":"#/definitions/AmenityDetail"}}}},"PricingDetail":{"description":"Detailed price breakdown. The \"total\" field is the all-in price the customer will pay.","type":"object","properties":{"baseFare":{"format":"double","description":"Base fare before tolls and taxes.","type":"number"},"tolls":{"format":"double","description":"Toll charges for this route.","type":"number"},"airportParking":{"format":"double","description":"Airport parking fee if applicable.","type":"number"},"subtotal":{"format":"double","description":"Subtotal before tax.","type":"number"},"salesTax":{"format":"double","description":"Sales tax amount.","type":"number"},"total":{"format":"double","description":"TOTAL all-in price including all taxes and fees. This is what the customer pays.","type":"number"},"stopCharges":{"type":"array","items":{"$ref":"#/definitions/StopChargeDetail"}},"totalStopCost":{"format":"double","type":"number"},"totalStopWaitingCost":{"format":"double","type":"number"},"extraCharges":{"description":"Extra charges breakdown (Fuel, STC, Service, etc.).","type":"array","items":{"$ref":"#/definitions/ExtraChargeDetail"}},"discount":{"$ref":"#/definitions/DiscountDetail","description":"Discount applied, if any."},"fareType":{"description":"Fare calculation method (PTP, HDF, LDF, Hourly, etc.).","type":"string"},"rateSource":{"description":"Rate source (Zone Rate, Flat Rate, etc.).","type":"string"},"hourlyRate":{"format":"double","description":"Hourly rate (only for hourly service type).","type":"number"},"minHours":{"format":"int32","description":"Minimum hours required (only for hourly service type).","type":"integer"}}},"AmenityDetail":{"description":"Amenity/add-on detail for a vehicle (e.g., baby seat, meet and greet, VIP greeting).","type":"object","properties":{"amenityId":{"format":"int32","description":"Amenity ID for booking.","type":"integer"},"name":{"description":"Display name (e.g., \"Forward Facing Baby Seat\").","type":"string"},"detail":{"description":"Description/detail for tooltip.","type":"string"},"imageUrl":{"description":"URL to amenity image.","type":"string"},"pricePerUnit":{"format":"double","description":"Price per unit in dollars.","type":"number"},"maxQuantity":{"format":"int32","description":"Maximum quantity selectable.","type":"integer"},"isVipGreet":{"description":"Whether this is a VIP greeting service.","type":"boolean"}}},"StopChargeDetail":{"type":"object","properties":{"name":{"type":"string"},"amount":{"format":"double","type":"number"},"included":{"type":"boolean"},"isWaiting":{"type":"boolean"}}},"ExtraChargeDetail":{"description":"Extra charge detail (e.g., Fuel surcharge, STC, Service/Gratuity).","type":"object","properties":{"name":{"description":"Charge display name (e.g., \"Fuel (2%)\", \"Service (20%)\").","type":"string"},"amount":{"format":"double","description":"Charge amount in dollars.","type":"number"},"type":{"description":"Charge type: \"%\" for percentage, \"$\" for flat, \"Optional\" for optional.","type":"string"},"value":{"format":"double","description":"Charge percentage or flat value.","type":"number"}}},"DiscountDetail":{"description":"Discount details if a discount was applied to the fare.","type":"object","properties":{"name":{"description":"Discount name (e.g., \"10% off all day\").","type":"string"},"originalFare":{"format":"double","description":"Original fare before discount.","type":"number"},"amount":{"format":"double","description":"Discount savings in dollars.","type":"number"},"type":{"description":"Discount type (PER = percentage, AMT = flat amount).","type":"string"}}},"ReceiptRequest":{"type":"object","properties":{"confirmationNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"lastFourCC":{"type":"string"},"reservationDate":{"type":"string"}}},"RouteEstimateRequest":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"departureTime":{"type":"string"}}},"TourEstimateRequest":{"type":"object","properties":{"pickup":{"type":"string"},"dropoff":{"type":"string"},"stops":{"type":"array","items":{"$ref":"#/definitions/TourStop"}},"departureTime":{"type":"string"}}},"TourStop":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"duration":{"format":"int32","type":"integer"}}},"SnapshotResponse":{"description":"Layer 1 \"Snapshot\" response — pre-computed rates for common routes.\r\nAI agents should check this endpoint FIRST for instant price discovery\r\nbefore using the dynamic /v1/quotes/calculate endpoint.","type":"object","properties":{"lastUpdated":{"format":"date-time","description":"When the snapshot data was last refreshed from the database.","type":"string"},"currency":{"description":"Currency code (always USD).","type":"string"},"locationContext":{"description":"Geographic coverage area.","type":"string"},"snapshotRates":{"description":"Array of pre-computed route rates.","type":"array","items":{"$ref":"#/definitions/SnapshotRoute"}},"deepQuoteEndpoint":{"description":"URL to the dynamic quote endpoint for exact pricing.","type":"string"}}},"SnapshotRoute":{"description":"A single route with pre-computed vehicle rates.\r\nThese are \"starting at\" prices — use /v1/quotes/calculate for exact all-in pricing.","type":"object","properties":{"routeId":{"description":"Unique route identifier (e.g., \"JFK_MANHATTAN\").","type":"string"},"displayName":{"description":"Human-readable route name (e.g., \"JFK Airport to Manhattan\").","type":"string"},"vehicleOptions":{"description":"Available vehicle options with base rates.","type":"array","items":{"$ref":"#/definitions/SnapshotVehicle"}},"inclusions":{"description":"What's included in the base rate.","type":"array","items":{"type":"string"}},"exclusions":{"description":"What's NOT included (varies by exact route).","type":"array","items":{"type":"string"}},"bookingNote":{"description":"Note about getting exact pricing.","type":"string"},"promotionNote":{"description":"Promotional message about available discounts (e.g., \"Book online and get 10% discount!\").","type":"string"}}},"SnapshotVehicle":{"description":"A vehicle option within a snapshot route.","type":"object","properties":{"class":{"description":"Vehicle class name (e.g., \"Luxury Sedan\").","type":"string"},"capacity":{"description":"Passenger capacity (e.g., \"3 Passengers\").","type":"string"},"baseRate":{"format":"double","description":"Base rate before tolls and surcharges.","type":"number"},"allInEstimate":{"format":"double","description":"Estimated all-in price including average tolls, taxes, and fees.","type":"number"},"hourlyRate":{"format":"double","description":"Hourly rate (for hourly service only).","type":"number"},"minHours":{"format":"int32","description":"Minimum hours required (for hourly service only).","type":"integer"},"features":{"description":"Key selling features of this vehicle.","type":"array","items":{"type":"string"}},"discount":{"$ref":"#/definitions/SnapshotDiscount","description":"Discount details if an online booking discount is available for this vehicle."}}},"SnapshotDiscount":{"description":"Discount information for a snapshot vehicle.","type":"object","properties":{"name":{"description":"Discount name (e.g., \"10% off all day\").","type":"string"},"description":{"description":"Discount description (e.g., \"Book your reservation online today and get 10% discount!\").","type":"string"},"originalRate":{"format":"double","description":"Original rate before discount.","type":"number"},"savings":{"format":"double","description":"Amount saved.","type":"number"}}},"VehicleListResponse":{"description":"Response model for GET /v1/vehicles — lists all available vehicle types.","type":"object","properties":{"count":{"format":"int32","description":"Number of vehicles returned.","type":"integer"},"vehicles":{"description":"List of available vehicle types.","type":"array","items":{"$ref":"#/definitions/VehicleItem"}},"amenities":{"description":"Available amenity add-ons (applies to all vehicles).","type":"array","items":{"$ref":"#/definitions/AmenityItem"}}}},"VehicleItem":{"description":"A single vehicle type available for booking.","type":"object","properties":{"vehicleId":{"format":"int32","description":"Internal vehicle ID used when booking.","type":"integer"},"code":{"description":"Short vehicle code (e.g., \"LX\", \"SUV\").","type":"string"},"name":{"description":"Display name (e.g., \"Luxury Sedan\", \"6 Passenger Luxury SUV\").","type":"string"},"description":{"description":"Full description of the vehicle.","type":"string"},"maxPassengers":{"format":"int32","description":"Maximum number of passengers.","type":"integer"},"maxLuggage":{"format":"int32","description":"Maximum number of luggage pieces.","type":"integer"},"imageUrl":{"description":"URL to the vehicle exterior image.","type":"string"},"interiorImageUrl":{"description":"URL to the vehicle interior image.","type":"string"},"hasColorSelection":{"description":"True if color selection is available for this vehicle (actual colors provided in quote response).","type":"boolean"},"hasMeetAndGreet":{"description":"True if this vehicle includes meet-and-greet service at airport terminals.","type":"boolean"}}},"AmenityItem":{"description":"An amenity add-on available for booking (e.g., baby seat, champagne).","type":"object","properties":{"amenityId":{"format":"int32","description":"Amenity ID for booking reference.","type":"integer"},"name":{"description":"Amenity name.","type":"string"},"price":{"format":"double","description":"Price per unit in USD (0 = complimentary).","type":"number"},"maxQuantity":{"format":"int32","description":"Maximum quantity that can be ordered (0 = not orderable, display only).","type":"integer"}}}}}