{"components":{"responses":{},"schemas":{"CategoriesResponse":{"description":"List of bookable categories with availability and default price.","properties":{"data":{"items":{"properties":{"available":{"type":"boolean"},"booking_url":{"description":"Absolute deeplink that opens this category in the interactive booking portal with the searched timeframe + guests prefilled","type":"string"},"external_id":{"nullable":true,"type":"string"},"extras":{"items":{"$ref":"#/components/schemas/Extra"},"type":"array"},"id":{"type":"integer"},"max_guests":{"nullable":true,"type":"integer"},"name":{"nullable":true,"type":"string"},"price":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"selection_options":{"items":{"properties":{"id":{"nullable":true,"type":"integer"},"name":{"nullable":true,"type":"string"},"package_external_id":{"nullable":true,"type":"string"},"package_name":{"nullable":true,"type":"string"},"type":{"enum":["default","package","unknown"],"type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"type":"array"}},"required":["data"],"title":"CategoriesResponse","type":"object"},"ErrorResponse":{"description":"Single-error response shape for the booking-portal API.","example":{"error":{"code":"invalid_param","field":"from","message":"'from' is required"}},"properties":{"error":{"properties":{"code":{"description":"Machine-readable error code","type":"string"},"field":{"description":"Offending field, if any","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"retry_after":{"description":"Seconds to wait before retry (rate-limit only)","type":"integer"}},"required":["code","message"],"type":"object"}},"required":["error"],"title":"ErrorResponse","type":"object"},"Extra":{"description":"A bookable add-on (service, consumable, package, …) offered by the portal.","properties":{"external_id":{"nullable":true,"type":"string"},"id":{"type":"integer"},"name":{"nullable":true,"type":"string"},"type":{"description":"Extra type","enum":["package","accommodation","service","consumable","accommodation_tags","housekeeping","preorder","rental","upgrade","bundle"],"type":"string"}},"required":["id","type"],"title":"Extra","type":"object"},"GuestsSlot":{"description":"Guest configuration for one accommodation slot.","properties":{"dogs":{"default":0,"minimum":0,"type":"integer"},"people":{"description":"List of guests — each entry is either the string `'adult'` or an integer (age in years)","items":{"oneOf":[{"enum":["adult"],"type":"string"},{"minimum":0,"type":"integer"}]},"type":"array"},"vehicles":{"description":"List of vehicle type IDs (one per vehicle)","items":{"type":"integer"},"type":"array"}},"required":["people"],"title":"GuestsSlot","type":"object"},"Money":{"description":"Money value with currency.","example":{"amount":12345,"currency":"EUR","gross":123.45},"properties":{"amount":{"description":"Amount in the currency's minor unit (cents for EUR)","type":"integer"},"currency":{"description":"ISO 4217 currency code","example":"EUR","type":"string"},"gross":{"description":"Convenience: amount as decimal in the major unit","format":"float","type":"number"}},"required":["amount","currency","gross"],"title":"Money","type":"object"},"Portal":{"description":"Configuration of a booking portal.","properties":{"data":{"properties":{"blocked_periods":{"items":{"items":{"format":"date","type":"string"},"type":"array"},"type":"array"},"children":{"properties":{"enabled":{"type":"boolean"},"max_age":{"nullable":true,"type":"integer"},"max_per_accommodation":{"nullable":true,"type":"integer"}},"type":"object"},"data_privacy_mode":{"description":"How data-privacy acceptance is handled","type":"string"},"dogs":{"properties":{"enabled":{"type":"boolean"},"max_per_accommodation":{"nullable":true,"type":"integer"},"product_id":{"nullable":true,"type":"integer"}},"type":"object"},"has_extras":{"type":"boolean"},"identifier":{"description":"Portal slug as used in URLs","type":"string"},"languages":{"description":"Supported language codes","items":{"type":"string"},"type":"array"},"max_accommodations":{"type":"integer"},"name":{"description":"Display name of the portal","type":"string"},"payment_methods":{"items":{"properties":{"id":{"type":"integer"}},"required":["id"],"type":"object"},"type":"array"},"terms_mode":{"description":"How terms acceptance is handled","type":"string"},"url":{"description":"Absolute URL of the interactive booking-portal landing page","type":"string"},"vehicles":{"properties":{"default_type_id":{"nullable":true,"type":"integer"},"enabled":{"type":"boolean"},"license_plate_input":{"type":"boolean"},"max_per_accommodation":{"nullable":true,"type":"integer"},"required":{"type":"boolean"},"vehicle_type_ids":{"items":{"type":"integer"},"type":"array"}},"type":"object"}},"type":"object"}},"required":["data"],"title":"Portal","type":"object"},"QuoteRequest":{"description":"Inputs for a price preview.","example":{"guests_per_slot":[{"dogs":1,"people":["adult","adult",10],"vehicles":[1]}],"selection":[{"category_id":12,"extras":[{"id":42,"modifier":{"kind":"amount","value":14},"type":"consumable"}],"mode":"category"}],"timeframe":{"from":"2026-08-01","to":"2026-08-08"}},"properties":{"guests_per_slot":{"description":"One entry per `category`-mode selection slot, in the same order","items":{"$ref":"#/components/schemas/GuestsSlot"},"type":"array"},"selection":{"items":{"$ref":"#/components/schemas/SelectionItem"},"type":"array"},"timeframe":{"properties":{"from":{"format":"date","type":"string"},"to":{"format":"date","type":"string"}},"required":["from","to"],"type":"object"}},"required":["timeframe","guests_per_slot","selection"],"title":"QuoteRequest","type":"object"},"QuoteResponse":{"description":"Price preview for the submitted selection.","properties":{"data":{"properties":{"booking_url":{"description":"Absolute deeplink into the interactive booking portal with the whole selection (timeframe, guests per slot, categories, packages and extras) prefilled — hand this to the human to complete the booking","type":"string"},"items":{"items":{"properties":{"amount":{"nullable":true,"type":"number"},"name":{"nullable":true,"type":"string"},"total":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"type":{"nullable":true,"type":"string"},"unit_price":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]}},"type":"object"},"type":"array"},"net_total":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"tax_rates":{"items":{"properties":{"rate":{"type":"integer"},"taxes":{"$ref":"#/components/schemas/Money"}},"type":"object"},"type":"array"},"taxes":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]},"timeframe":{"properties":{"from":{"format":"date","type":"string"},"to":{"format":"date","type":"string"}},"type":"object"},"total":{"oneOf":[{"$ref":"#/components/schemas/Money"},{"type":"null"}]}},"type":"object"}},"required":["data"],"title":"QuoteResponse","type":"object"},"SelectionExtra":{"description":"An extra (or package) selected for a slot or globally.","properties":{"id":{"description":"Extra/Package internal ID","type":"integer"},"modifier":{"description":"Optional configuration for complex extras:\n  * `{kind: 'guests', indices: [0,2]}`\n  * `{kind: 'amount', value: 14}`\n  * `{kind: 'daterange', from: 'YYYY-MM-DD', to: 'YYYY-MM-DD'}`\n  * `{kind: 'date_amounts', entries: [{date: 'YYYY-MM-DD', amount: 3}]}`\n  * `{kind: 'datetime', value: 'YYYY-MM-DDTHH:MM:SS'}`\n  * `{kind: 'time_window', start: 'YYYY-MM-DDTHH:MM:SS', duration: 'HH:MM:SS'}`\n","nullable":true,"properties":{"kind":{"enum":["guests","amount","daterange","date_amounts","datetime","time_window"],"type":"string"}},"required":["kind"],"type":"object"},"type":{"enum":["package","accommodation","service","consumable","accommodation_tags","housekeeping","preorder","rental","upgrade","bundle"],"type":"string"}},"required":["type","id"],"title":"SelectionExtra","type":"object"},"SelectionItem":{"description":"A single selection entry. Either a `category` selection (one slot per\n`guests_per_slot` entry in the same order) or a `global` selection\n(extras that apply to the booking as a whole).\n","properties":{"accommodation_id":{"description":"Optional plot/unit lock","nullable":true,"type":"integer"},"category_id":{"nullable":true,"type":"integer"},"extras":{"items":{"$ref":"#/components/schemas/SelectionExtra"},"type":"array"},"group_id":{"description":"Optional plot-plan area lock","nullable":true,"type":"integer"},"mode":{"enum":["category","global"],"type":"string"}},"required":["mode"],"title":"SelectionItem","type":"object"}}},"info":{"contact":{"name":"Gastmanager","url":"https://www.gastmanager.com"},"description":"Read-only JSON API for AI agents to discover availability and\npricing of a Gastmanager booking portal.\n\nThe client is identified by the request host\n(`<client>.gastmanager.<tld>`), so it never appears in the path.\n\nQuickstart:\n  1. `GET /portals/:portal` — load the portal config\n     (languages, payment methods, guest config, blocked dates).\n  2. `GET /portals/:portal/categories?from=…&to=…&guests[]=adult`\n     — list bookable categories with availability flag and\n     default price.\n  3. `POST /portals/:portal/quote` — get a precise price\n     preview for a concrete selection (timeframe +\n     guests_per_slot + selection).\n\nDiscovery: `GET /openapi.json` (this spec),\n`GET /booking/.well-known/ai-plugin.json` (ChatGPT\nplugin manifest), `GET /booking/llms.txt` (LLM\nquickstart with selection-JSON + modifier-kind reference).\n\nConventions:\n  * Dates are ISO 8601 (`YYYY-MM-DD`).\n  * Datetimes are naive ISO 8601 (no timezone suffix); the\n    server interprets them in Europe/Vienna.\n  * Money is reported as integer minor unit (`amount`) plus a\n    decimal convenience field (`gross`).\n  * No authentication — rate-limited per source IP.\n","license":{"name":"Proprietary"},"title":"Gastmanager Booking Portal API","version":"1.0"},"openapi":"3.0.0","paths":{"/booking/api/v1/portals/{portal}":{"get":{"callbacks":{},"description":"Returns the portal configuration (name, supported languages, payment methods, terms/data-privacy mode, children/dogs/vehicles config, blocked periods) plus an absolute `url` to the portal landing page.","operationId":"PortalsWeb.BookingPortal.API.PortalController.show","parameters":[{"description":"Portal identifier","example":"sommer","in":"path","name":"portal","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Portal"}}},"description":"Portal configuration"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Portal not found or inactive"}},"summary":"Get portal configuration","tags":["booking-api"]}},"/booking/api/v1/portals/{portal}/categories":{"get":{"callbacks":{},"description":"Lists the bookable categories for a search timeframe + party composition. Per category: an `available` boolean, selection options (default vs. package), embedded extras, a default `price` and an absolute `booking_url` that opens the category with the dates + guests prefilled.","operationId":"PortalsWeb.BookingPortal.API.CategoryController.index","parameters":[{"description":"Portal identifier","example":"sommer","in":"path","name":"portal","required":true,"schema":{"type":"string"}},{"description":"Arrival date (ISO 8601)","example":"2026-08-01","in":"query","name":"from","required":true,"schema":{"type":"string"}},{"description":"Departure date (ISO 8601)","example":"2026-08-08","in":"query","name":"to","required":true,"schema":{"type":"string"}},{"description":"Repeatable: `adult` or an integer age. Defaults to two adults.","example":["adult","adult"],"in":"query","name":"guests","required":false,"schema":{"items":{"type":"string"},"type":"array"}},{"description":"Number of dogs (default 0)","example":0,"in":"query","name":"dogs","required":false,"schema":{"type":"integer"}},{"description":"Repeatable vehicle type IDs","in":"query","name":"vehicles","required":false,"schema":{"items":{"type":"integer"},"type":"array"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoriesResponse"}}},"description":"Categories with availability + price"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid query parameter"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Portal not found or inactive"}},"summary":"List bookable categories","tags":["booking-api"]}},"/booking/api/v1/portals/{portal}/quote":{"post":{"callbacks":{},"description":"Computes a precise price preview for a concrete selection (timeframe + guests_per_slot + selection). Returns totals, per-rate tax breakdown, line items and an absolute `booking_url` with the whole selection prefilled. Read-only — no booking is created.","operationId":"PortalsWeb.BookingPortal.API.QuoteController.create","parameters":[{"description":"Portal identifier","example":"sommer","in":"path","name":"portal","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequest"}}},"description":"Quote request","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}},"description":"Price preview"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid request body"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Portal not found or inactive"}},"summary":"Price preview for a selection","tags":["booking-api"]}}},"security":[],"servers":[{"url":"/booking/api/v1","variables":{}}],"tags":[{"description":"Read-only availability and pricing for AI agents","name":"booking-api"}]}