{"openapi":"3.1.0","info":{"title":"ATV in Bali public API for AI agents & developers","version":"1.0.0","summary":"Read-only JSON: ATV rides in Bali, prices, availability and quotes with a checkout hand-off link.","description":"Compare and book the best ATV quad bike rides across Bali: Ubud jungle trails, river crossings, caves and waterfalls. Instant confirmation, hotel pick-up, no agency markup.\n\nThis API is read-only. An agent can list rides and prices, check availability for a date and get an exact quote. Bookings are completed by the guest on the website: hand them the `checkoutUrl` from the quote (or availability) response — it opens the checkout with the selection prefilled, the guest enters their details, picks a payment plan and pays; the e-voucher is issued automatically.\n\nPrices are set in Indonesian rupiah (IDR). The `usd` figures are approximate display conversions; never promise a USD amount. Never invent a price, a time or an age rule that is not in a response.\nRate limit: 60 requests per minute per IP (headers X-RateLimit-Limit / X-RateLimit-Remaining; 429 with Retry-After). Catalogue responses are CDN-cached for 5 minutes, availability for 60 seconds, quotes never. CORS is open (GET, OPTIONS).\nHuman documentation: https://www.atvinbali.com/developers","termsOfService":"https://www.atvinbali.com/terms","contact":{"name":"ATV in Bali","url":"https://www.atvinbali.com","email":"familytripsbali@gmail.com"}},"servers":[{"url":"https://www.atvinbali.com","description":"Production"}],"tags":[{"name":"Catalogue","description":"Rides, packages and prices"},{"name":"Booking","description":"Availability and quotes — the guest books on the checkout link"}],"paths":{"/api/public/rides":{"get":{"operationId":"listRides","tags":["Catalogue"],"summary":"List ATV rides with packages and prices","description":"Every published ride with its active packages, list prices (IDR + approximate USD), departure times, policies, payment options and suitability. Cached for 5 minutes on the CDN.","x-openai-isConsequential":false,"parameters":[{"name":"destination","in":"query","required":false,"description":"Filter by riding area slug (see rides[].destination.slug).","schema":{"type":"string"},"example":"ubud"},{"name":"ride","in":"query","required":false,"description":"Only rides with SINGLE or TANDEM quads.","schema":{"type":"string","enum":["SINGLE","TANDEM"]}},{"name":"transfer","in":"query","required":false,"description":"1/true = only rides that offer hotel transfer; 0/false = meet-at-venue only.","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"cc","in":"query","required":false,"description":"Engine size in cc (250, 350, 450).","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Free-text search in title, area and summary.","schema":{"type":"string"},"example":"jungle"}],"responses":{"200":{"description":"The rides.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RidesResponse"}}}},"400":{"description":"Invalid parameters — the `hint` says what to fix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; wait `retryAfterSeconds` (also sent as Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The site owner has switched the API off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/rides/{slug}":{"get":{"operationId":"getRide","tags":["Catalogue"],"summary":"One ride in full","description":"Long description, highlights, what to expect, FAQs, recent reviews and every package with itinerary and checkout link template.","x-openai-isConsequential":false,"parameters":[{"name":"slug","in":"path","required":true,"description":"Ride slug from listRides.","schema":{"type":"string"}}],"responses":{"200":{"description":"The ride.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RideResponse"}}}},"400":{"description":"Invalid parameters — the `hint` says what to fix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; wait `retryAfterSeconds` (also sent as Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The site owner has switched the API off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/availability":{"get":{"operationId":"checkAvailability","tags":["Booking"],"summary":"Check departure times for a date, or a calendar of days","description":"Day mode (pass `date`): every departure time of the package with available / reason and a prefilled checkoutUrl, applying the cut-off, closed days and remaining capacity exactly like the booking widget. Calendar mode (no `date`): one row per day from `from` for `days` days. `guests` are people; tandem quads seat two. Cached for 60 seconds on the CDN.","x-openai-isConsequential":false,"parameters":[{"name":"package","in":"query","required":true,"description":"Package id (rides[].packages[].id).","schema":{"type":"string"}},{"name":"date","in":"query","required":false,"description":"YYYY-MM-DD (Bali) — day mode.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"guests","in":"query","required":false,"description":"Number of people riding (default 1).","schema":{"type":"integer"}},{"name":"slot","in":"query","required":false,"description":"HH:mm — check only this departure time (day mode).","schema":{"type":"string"}},{"name":"from","in":"query","required":false,"description":"YYYY-MM-DD — first day of the calendar (default today in Bali).","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"Calendar length, 1–62 (default 14).","schema":{"type":"integer"}}],"responses":{"200":{"description":"Day mode or calendar mode.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/AvailabilityDayMode"},{"$ref":"#/components/schemas/AvailabilityCalendar"}]}}}},"400":{"description":"Invalid parameters — the `hint` says what to fix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or inactive package.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; wait `retryAfterSeconds` (also sent as Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The site owner has switched the API off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/public/quote":{"get":{"operationId":"getQuote","tags":["Booking"],"summary":"Exact price for a selection + checkout link","description":"The same calculation as the website's checkout: per-day price overrides, package discount, add-ons, deposit amount and the payment plans (pay in full online, deposit, or pay in full on the day in cash where offered). Also tells whether that departure is bookable right now and returns the checkoutUrl to hand to the guest. Never cached.","x-openai-isConsequential":false,"parameters":[{"name":"package","in":"query","required":true,"description":"Package id.","schema":{"type":"string"}},{"name":"date","in":"query","required":true,"description":"YYYY-MM-DD (Bali).","schema":{"type":"string"}},{"name":"slot","in":"query","required":true,"description":"Departure time HH:mm from the package's timeSlots.","schema":{"type":"string"}},{"name":"u","in":"query","required":false,"description":"Unit selection `unitId:qty`; repeat for several units (unit ids under packages[].prices[].unitId).","schema":{"type":"string"},"example":"ckx…:2"},{"name":"a","in":"query","required":false,"description":"Add-on selection `addonId:qty`; repeatable.","schema":{"type":"string"}},{"name":"guests","in":"query","required":false,"description":"Instead of `u`: number of people → default adult unit × quads needed.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Quote, payment options and checkout link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"400":{"description":"Invalid parameters — the `hint` says what to fix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown or inactive package.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded; wait `retryAfterSeconds` (also sent as Retry-After).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The site owner has switched the API off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Money":{"type":"object","properties":{"idr":{"type":"integer","description":"Amount in Indonesian rupiah — the amount actually charged."},"usd":{"type":"number","description":"Approximate US dollar value at the site's display rate. Never promise this figure."}},"required":["idr","usd"],"description":"An amount in IDR with its approximate USD value."},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable message, English."},"hint":{"type":"string","description":"What to do about it."},"retryAfterSeconds":{"type":"integer"},"docs":{"type":"string","description":"Documentation URL."}},"required":["error","docs"]},"Site":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"bookingHelpWhatsapp":{"type":"string","description":"E.164 number a guest can message for help."},"contactEmail":{"type":"string"},"timezone":{"type":"string","const":"Asia/Makassar"}},"required":["name","url","timezone"]},"Currency":{"type":"object","properties":{"base":{"type":"string","const":"IDR"},"usdRate":{"type":"number","description":"IDR per 1 USD used for the approximate usd figures."},"usdNote":{"type":"string","const":"approximate"}},"required":["base","usdRate"]},"Destination":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"}},"required":["slug","name","url"]},"MeetingPoint":{"type":"object","properties":{"name":{"type":"string"},"mapsUrl":{"oneOf":[{"type":"string"},{"type":"null"}]},"latitude":{"oneOf":[{"type":"number"},{"type":"null"}]},"longitude":{"oneOf":[{"type":"number"},{"type":"null"}]}},"required":["name"]},"Pickup":{"type":"object","properties":{"freeArea":{"oneOf":[{"type":"string","description":"Area where hotel pick-up is free on packages with transfer."},{"type":"null"}]},"onTransferPackagesOnly":{"type":"boolean"}},"required":["onTransferPackagesOnly"]},"Cancellation":{"type":"object","properties":{"refundPct":{"type":"integer","description":"Refund percentage when cancelled before the deadline (0 = non-refundable)."},"refundDeadlineHours":{"type":"integer","description":"Hours before the start."},"text":{"type":"string","description":"One-line summary."},"lines":{"type":"array","items":{"type":"string"},"description":"The operator's own policy lines."}},"required":["refundPct","refundDeadlineHours","text","lines"]},"Policies":{"type":"object","properties":{"cutoffHours":{"type":"integer","description":"Bookings close this many hours before the departure time."},"holdMinutes":{"type":"integer","description":"Minutes the quads are held while the guest pays online."},"cancellation":{"$ref":"#/components/schemas/Cancellation"},"weather":{"type":"string","description":"Rain / track-closure policy."},"termsUrl":{"type":"string"},"cancellationPolicyUrl":{"type":"string"}},"required":["cutoffHours","holdMinutes","cancellation","weather","termsUrl","cancellationPolicyUrl"]},"PaymentPlan":{"type":"object","properties":{"plan":{"type":"string","description":"FULL = pay everything online; DEPOSIT = part online, balance in cash at the venue; PAY_LATER = pay in full on the day in cash at the venue (nothing online, quads reserved at once).","enum":["FULL","DEPOSIT","PAY_LATER"]},"label":{"type":"string"},"payNowPct":{"type":"integer"},"payAtVenuePct":{"type":"integer"},"description":{"type":"string"}},"required":["plan","label","payNowPct","payAtVenuePct","description"]},"PaymentMethod":{"type":"object","properties":{"id":{"type":"string","enum":["midtrans","paypal","bank_transfer"]},"label":{"type":"string"},"currency":{"type":"string","enum":["IDR","USD"]}},"required":["id","label","currency"]},"Payment":{"type":"object","properties":{"currency":{"type":"string","const":"IDR"},"plans":{"type":"array","items":{"$ref":"#/components/schemas/PaymentPlan"},"description":"Payment plans the guest can pick at checkout, in the order offered."},"allowDeposit":{"type":"boolean","description":"A deposit option is offered."},"depositPct":{"type":"integer","description":"Deposit percentage (100 when deposits are off)."},"allowPayLater":{"type":"boolean","description":"'Pay in full on the day — cash' is offered: the guest reserves without paying online."},"onlineMethods":{"type":"array","items":{"$ref":"#/components/schemas/PaymentMethod"},"description":"Online payment methods currently switched on."},"holdMinutes":{"type":"integer"},"note":{"type":"string"}},"required":["currency","plans","allowDeposit","depositPct","allowPayLater","onlineMethods","holdMinutes","note"],"description":"How a guest can pay. The guest chooses the plan on the checkout page."},"Suitability":{"type":"object","properties":{"minimumAgeToDrive":{"oneOf":[{"type":"integer"},{"type":"null"}]},"minimumAgeAsPassenger":{"oneOf":[{"type":"integer","description":"Youngest tandem passenger."},{"type":"null"}]},"maxWeightKg":{"oneOf":[{"type":"integer"},{"type":"null"}]},"pregnancyAllowed":{"oneOf":[{"type":"boolean"},{"type":"null"}]},"excludedConditions":{"type":"array","items":{"type":"string"},"description":"Health conditions the operator excludes."},"licenceRequired":{"type":"boolean","description":"Always false: the tracks are on private land."},"notes":{"type":"array","items":{"type":"string"},"description":"The operator's own wording on ages, health and waivers."}},"required":["minimumAgeToDrive","minimumAgeAsPassenger","licenceRequired","notes"]},"Price":{"type":"object","properties":{"unitId":{"type":"string","description":"Pass as u=<unitId>:<qty> to the quote endpoint and the checkout link."},"label":{"type":"string","description":"e.g. 'Per person' or '1 ATV for 2 persons'."},"ageGroup":{"type":"string","enum":["ADULT","CHILD","INFANT"]},"ageHint":{"oneOf":[{"type":"string"},{"type":"null"}]},"minQty":{"type":"integer"},"maxQty":{"type":"integer"},"countsTowardCapacity":{"type":"boolean","description":"False for spectators / non-riders."},"price":{"$ref":"#/components/schemas/Money"},"wasPrice":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]}},"required":["unitId","label","ageGroup","minQty","maxQty","countsTowardCapacity","price"],"description":"List price per unit before any package discount (discountPct)."},"Addon":{"type":"object","properties":{"id":{"type":"string","description":"Pass as a=<id>:<qty>."},"title":{"type":"string"},"description":{"oneOf":[{"type":"string"},{"type":"null"}]},"perPerson":{"type":"boolean"},"price":{"$ref":"#/components/schemas/Money"}},"required":["id","title","perPerson","price"]},"ItineraryItem":{"type":"object","properties":{"time":{"oneOf":[{"type":"string"},{"type":"null"}]},"title":{"type":"string"},"description":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["title"]},"Package":{"type":"object","properties":{"id":{"type":"string","description":"Package id — the `package` parameter of availability and quote."},"title":{"type":"string"},"description":{"oneOf":[{"type":"string"},{"type":"null"}]},"rideType":{"type":"string","description":"SINGLE = one rider per quad; TANDEM = two people per quad.","enum":["SINGLE","TANDEM"]},"rideTypeLabel":{"type":"string"},"peoplePerUnit":{"type":"integer","description":"How many people one unit (quad) seats."},"engineCc":{"oneOf":[{"type":"integer"},{"type":"null"}]},"withTransfer":{"type":"boolean","description":"Round-trip hotel transfer included."},"groupType":{"type":"string","enum":["PRIVATE","SHARED"]},"confirmation":{"type":"string","description":"INSTANT = e-voucher at once after payment; ON_REQUEST = confirmed by the team.","enum":["INSTANT","ON_REQUEST"]},"timeSlots":{"type":"array","items":{"type":"string"},"description":"Departure times, HH:mm Bali time."},"inventory":{"type":"string","enum":["limited","unlimited"]},"capacityPerDay":{"oneOf":[{"type":"integer"},{"type":"null"}]},"discountPct":{"type":"integer","description":"Percentage taken off the subtotal at checkout."},"fromPrice":{"$ref":"#/components/schemas/Money"},"prices":{"type":"array","items":{"$ref":"#/components/schemas/Price"}},"addons":{"type":"array","items":{"$ref":"#/components/schemas/Addon"}},"inclusions":{"type":"array","items":{"type":"string"}},"exclusions":{"type":"array","items":{"type":"string"}},"whatToBring":{"type":"array","items":{"type":"string"}},"importantNotes":{"type":"array","items":{"type":"string"}},"guestQuestions":{"type":"array","items":{"type":"string"},"description":"Details the guest must give at checkout (e.g. hotel address)."},"suitability":{"$ref":"#/components/schemas/Suitability"},"itinerary":{"type":"array","items":{"$ref":"#/components/schemas/ItineraryItem"},"description":"Only in the single-ride response."},"checkoutUrlTemplate":{"type":"string","description":"Fill {YYYY-MM-DD}, {HH:mm}, {unitId} and {qty}; or use the quote endpoint's checkoutUrl."}},"required":["id","title","rideType","peoplePerUnit","withTransfer","confirmation","timeSlots","inventory","discountPct","fromPrice","prices","addons","suitability","checkoutUrlTemplate"]},"RideSummary":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string","description":"Use with GET /api/public/rides/{slug}."},"title":{"type":"string"},"subtitle":{"oneOf":[{"type":"string"},{"type":"null"}]},"summary":{"type":"string"},"url":{"type":"string","description":"Public ride page — cite this URL."},"bookUrl":{"type":"string","description":"Ride page scrolled to the booking box."},"area":{"type":"string"},"destination":{"oneOf":[{"$ref":"#/components/schemas/Destination"},{"type":"null"}]},"duration":{"type":"object","properties":{"label":{"type":"string"},"minutes":{"type":"integer"}},"required":["label","minutes"]},"meetingPoint":{"oneOf":[{"$ref":"#/components/schemas/MeetingPoint"},{"type":"null"}]},"pickup":{"$ref":"#/components/schemas/Pickup"},"images":{"type":"array","items":{"type":"string"},"description":"Absolute image URLs, hero first."},"rating":{"type":"number"},"reviewCount":{"type":"integer"},"badge":{"oneOf":[{"type":"string"},{"type":"null"}]},"fromPrice":{"$ref":"#/components/schemas/Money"},"policies":{"$ref":"#/components/schemas/Policies"},"payment":{"$ref":"#/components/schemas/Payment"},"suitability":{"$ref":"#/components/schemas/Suitability"},"packages":{"type":"array","items":{"$ref":"#/components/schemas/Package"}}},"required":["id","slug","title","summary","url","bookUrl","area","duration","pickup","images","rating","reviewCount","fromPrice","policies","payment","suitability","packages"]},"Ride":{"allOf":[{"$ref":"#/components/schemas/RideSummary"},{"type":"object","properties":{"description":{"type":"string","description":"Long description, Markdown."},"highlights":{"type":"array","items":{"type":"string"}},"goodToKnow":{"type":"array","items":{"type":"string"}},"whatToExpect":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"text":{"type":"string"}},"required":["title","text"]}},"faqs":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string"},"answer":{"type":"string","description":"Markdown."}},"required":["question","answer"]}},"reviews":{"type":"array","items":{"type":"object","properties":{"author":{"type":"string"},"country":{"oneOf":[{"type":"string"},{"type":"null"}]},"rating":{"type":"integer"},"title":{"oneOf":[{"type":"string"},{"type":"null"}]},"text":{"type":"string"},"date":{"type":"string"}},"required":["author","rating","text","date"]},"description":"Up to five recent published reviews."}}}]},"RidesResponse":{"type":"object","properties":{"generatedAt":{"type":"string"},"site":{"$ref":"#/components/schemas/Site"},"currency":{"$ref":"#/components/schemas/Currency"},"count":{"type":"integer"},"rides":{"type":"array","items":{"$ref":"#/components/schemas/RideSummary"}}},"required":["generatedAt","site","currency","count","rides"]},"RideResponse":{"type":"object","properties":{"generatedAt":{"type":"string"},"site":{"$ref":"#/components/schemas/Site"},"currency":{"$ref":"#/components/schemas/Currency"},"ride":{"$ref":"#/components/schemas/Ride"}},"required":["generatedAt","site","currency","ride"]},"PackageRef":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"rideType":{"type":"string"},"peoplePerUnit":{"type":"integer"},"timeSlots":{"type":"array","items":{"type":"string"}},"ride":{"type":"object","properties":{"slug":{"type":"string"},"title":{"type":"string"},"url":{"type":"string"}},"required":["slug","title","url"]}},"required":["id","title","rideType","peoplePerUnit","timeSlots","ride"]},"Slot":{"type":"object","properties":{"time":{"type":"string","description":"HH:mm Bali time."},"startsAt":{"type":"string","description":"ISO 8601 instant of the departure."},"available":{"type":"boolean"},"reason":{"type":"string","description":"Why it is not bookable (cut-off passed, closed, full)."},"checkoutUrl":{"type":"string","description":"Prefilled checkout link for the default unit × quads needed — only when available."}},"required":["time","startsAt","available"]},"AvailabilityDayMode":{"type":"object","properties":{"package":{"$ref":"#/components/schemas/PackageRef"},"date":{"type":"string"},"guests":{"type":"integer"},"unitsNeeded":{"type":"integer","description":"Quads needed for the guests (tandem = 2 people per quad), never below the unit minimum."},"unitLabel":{"oneOf":[{"type":"string"},{"type":"null"}]},"timezone":{"type":"string"},"cutoffHours":{"type":"integer"},"holdMinutes":{"type":"integer"},"closed":{"type":"boolean"},"seatsLeft":{"oneOf":[{"type":"integer","description":"Quads left that day; null = unlimited."},{"type":"null"}]},"price":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"priceNote":{"type":"string"},"slots":{"type":"array","items":{"$ref":"#/components/schemas/Slot"}},"nextStep":{"type":"string"}},"required":["package","date","guests","unitsNeeded","timezone","cutoffHours","holdMinutes","closed","slots","nextStep"]},"AvailabilityDay":{"type":"object","properties":{"date":{"type":"string"},"closed":{"type":"boolean"},"seatsLeft":{"oneOf":[{"type":"integer"},{"type":"null"}]},"enoughForGuests":{"type":"boolean"},"price":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"closedSlots":{"type":"array","items":{"type":"string"},"description":"Departure times closed that day."}},"required":["date","closed","enoughForGuests","closedSlots"]},"AvailabilityCalendar":{"type":"object","properties":{"package":{"$ref":"#/components/schemas/PackageRef"},"from":{"type":"string"},"days":{"type":"integer"},"guests":{"type":"integer"},"unitsNeeded":{"type":"integer"},"timezone":{"type":"string"},"cutoffHours":{"type":"integer"},"holdMinutes":{"type":"integer"},"note":{"type":"string"},"calendar":{"type":"array","items":{"$ref":"#/components/schemas/AvailabilityDay"}}},"required":["package","from","days","guests","unitsNeeded","timezone","cutoffHours","holdMinutes","calendar"]},"QuoteLine":{"type":"object","properties":{"unitId":{"oneOf":[{"type":"string"},{"type":"null"}]},"addonId":{"oneOf":[{"type":"string"},{"type":"null"}]},"label":{"type":"string"},"qty":{"type":"integer"},"unitPrice":{"$ref":"#/components/schemas/Money"},"total":{"$ref":"#/components/schemas/Money"}},"required":["label","qty","unitPrice","total"]},"Quote":{"type":"object","properties":{"packageId":{"type":"string"},"rideSlug":{"type":"string"},"activityTitle":{"type":"string"},"packageTitle":{"type":"string"},"date":{"type":"string"},"timeSlot":{"type":"string"},"timezone":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/QuoteLine"}},"addons":{"type":"array","items":{"$ref":"#/components/schemas/QuoteLine"}},"subtotal":{"$ref":"#/components/schemas/Money"},"discountPct":{"type":"integer"},"discount":{"$ref":"#/components/schemas/Money"},"total":{"$ref":"#/components/schemas/Money"},"usdRate":{"type":"number"},"quadsBooked":{"type":"integer"},"peopleRiding":{"type":"integer"},"guestQuestions":{"type":"array","items":{"type":"string"}},"withTransfer":{"type":"boolean"},"pickupArea":{"oneOf":[{"type":"string"},{"type":"null"}]}},"required":["packageId","rideSlug","activityTitle","packageTitle","date","timeSlot","items","addons","subtotal","discountPct","discount","total","quadsBooked","peopleRiding","withTransfer"]},"QuotePaymentPlan":{"allOf":[{"$ref":"#/components/schemas/PaymentPlan"},{"type":"object","properties":{"payNow":{"$ref":"#/components/schemas/Money"},"payAtVenue":{"$ref":"#/components/schemas/Money"}},"required":["payNow","payAtVenue"]}]},"QuotePayment":{"allOf":[{"$ref":"#/components/schemas/Payment"},{"type":"object","properties":{"plans":{"type":"array","items":{"$ref":"#/components/schemas/QuotePaymentPlan"}},"depositAmount":{"$ref":"#/components/schemas/Money"}},"required":["plans","depositAmount"]}]},"QuoteResponse":{"type":"object","properties":{"generatedAt":{"type":"string"},"quote":{"$ref":"#/components/schemas/Quote"},"availability":{"type":"object","properties":{"ok":{"type":"boolean"},"reason":{"type":"string"}},"required":["ok"]},"payment":{"$ref":"#/components/schemas/QuotePayment"},"checkoutUrl":{"type":"string","description":"Hand this to the guest — it opens the website's checkout with the selection prefilled."},"rideUrl":{"type":"string"},"nextStep":{"type":"string"}},"required":["generatedAt","quote","availability","payment","checkoutUrl","rideUrl","nextStep"]}}},"x-agent-guidance":"Quote prices in IDR; USD is approximate. Never invent prices, departure times, ages or policies — use the fields in the responses and cite the ride url. guests = people; a TANDEM quad seats two, so unitsNeeded = ceil(guests / peoplePerUnit). Call checkAvailability before getQuote; getQuote tells whether the slot is bookable and returns the checkoutUrl. Bookings happen only on the checkoutUrl — there is no write API. Seats are held for payment.holdMinutes once the guest starts checkout. Payment plans: FULL (all online), DEPOSIT (depositPct online, balance in cash at the venue) and, where payment.allowPayLater is true, PAY_LATER (nothing online — reserve now, pay in full in cash at the venue on the day). For questions a response cannot answer, give the guest the site's WhatsApp number (site.bookingHelpWhatsapp).","x-rate-limit":{"requestsPerMinutePerIp":60,"headers":["X-RateLimit-Limit","X-RateLimit-Remaining","Retry-After"]},"x-discovery":{"manifest":"https://www.atvinbali.com/.well-known/ai-plugin.json","llmsTxt":"https://www.atvinbali.com/llms.txt","docs":"https://www.atvinbali.com/developers"}}