{
  "openapi": "3.1.0",
  "info": {
    "title": "Pensjonat Korona AI & Public REST API",
    "version": "1.0.0",
    "description": "Oficjalne API Pensjonatu Korona w Modrzycy k. Nowej Soli (woj. lubuskie). Umożliwia agentom AI odczytywanie oferty pokoi (25 pokoi / 50 miejsc), cennika (od 190 PLN), sprawdzanie dostępności, parametrów sali weselno-bankietowej (do 200 osób), karty menu restauracji oraz składanie bezpłatnych zapytań w środowisku produkcyjnym i sandbox.",
    "contact": {
      "name": "Pensjonat Korona Support",
      "email": "kontakt@pensjonat-korona.pl",
      "url": "https://pensjonat-korona.pl/docs"
    },
    "license": {
      "name": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://pensjonat-korona.pl",
      "description": "Serwer produkcyjny i testowy sandbox Pensjonatu Korona"
    }
  ],
  "tags": [
    {
      "name": "Info",
      "description": "Podstawowe informacje o obiekcie i lokalizacji"
    },
    {
      "name": "Pokoje",
      "description": "Typy pokoi, wyposażenie, ceny i sprawdzanie dostępności"
    },
    {
      "name": "Przyjęcia i Wesela",
      "description": "Sala bankietowa do 200 osób, altana grillowa i pakiety imprez"
    },
    {
      "name": "Restauracja",
      "description": "Karta dań kuchni polskiej i europejskiej oraz catering"
    },
    {
      "name": "Rezerwacje i Sandbox",
      "description": "Składanie zapytań, generowanie kluczy i obsługa środowiska sandbox"
    }
  ],
  "paths": {
    "/api/v1/info": {
      "get": {
        "tags": ["Info"],
        "summary": "Pobierz informacje o obiekcie Pensjonat Korona",
        "description": "Zwraca pełne dane teleadresowe, współrzędne geograficzne GPS, godziny zameldowania i wymeldowania oraz wykaz udogodnień.",
        "operationId": "getPensjonatInfo",
        "responses": {
          "200": {
            "description": "Informacje o obiekcie pobrane pomyślnie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PensjonatInfo"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/rooms": {
      "get": {
        "tags": ["Pokoje"],
        "summary": "Pobierz listę typów pokoi i wyposażenie",
        "description": "Zwraca listę rodzajów pokoi (1-, 2-, 3-osobowe), bazowe ceny za dobę, opcję śniadania (+20 zł), wyposażenie oraz łączną pojemność.",
        "operationId": "getRoomsList",
        "responses": {
          "200": {
            "description": "Lista pokoi pobrana pomyślnie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoomsResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/availability": {
      "get": {
        "tags": ["Pokoje"],
        "summary": "Sprawdź dostępność pokoi i skalkuluj koszt",
        "description": "Weryfikuje orientacyjną dostępność pokoi dla zadanych dat pobytu oraz liczby gości, obliczając całkowity koszt.",
        "operationId": "checkRoomAvailability",
        "parameters": [
          {
            "name": "checkIn",
            "in": "query",
            "required": true,
            "description": "Data przyjazdu w formacie ISO (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-11-01"
            }
          },
          {
            "name": "checkOut",
            "in": "query",
            "required": true,
            "description": "Data wyjazdu w formacie ISO (YYYY-MM-DD)",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-11-03"
            }
          },
          {
            "name": "guests",
            "in": "query",
            "required": false,
            "description": "Liczba gości (domyślnie 2)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 2,
              "example": 2
            }
          },
          {
            "name": "roomType",
            "in": "query",
            "required": false,
            "description": "Preferowany typ pokoju",
            "schema": {
              "type": "string",
              "enum": ["single", "double", "triple", "any"],
              "default": "any"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Kalkulacja dostępności i kosztu",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailabilityResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/pricing": {
      "get": {
        "tags": ["Pokoje"],
        "summary": "Pobierz pełną tabelę cennikową",
        "description": "Zwraca oficjalny cennik wszystkich usług: noclegi, śniadania, pakiety weselne i okolicznościowe.",
        "operationId": "getPricingDetails",
        "responses": {
          "200": {
            "description": "Cennik pobrany pomyślnie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricingResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/events": {
      "get": {
        "tags": ["Przyjęcia i Wesela"],
        "summary": "Pobierz informacje o sali weselnej i organizacji imprez",
        "description": "Zwraca specyfikację sali bankietowej (do 200 osób), wyposażenie (klimatyzacja, parkiet, nagłośnienie), altany grillowej oraz ofertę przyjęć (komunie, chrzciny, stypy, 18-stki, imprezy firmowe).",
        "operationId": "getBanquetAndEventInfo",
        "responses": {
          "200": {
            "description": "Informacje o sali weselnej i imprezach",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventInfoResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/restaurant/menu": {
      "get": {
        "tags": ["Restauracja"],
        "summary": "Pobierz kartę dań restauracji",
        "description": "Zwraca kartę dań restauracji kuchni polskiej i europejskiej, zupy, dania główne, dania dla dzieci oraz desery.",
        "operationId": "getRestaurantMenu",
        "responses": {
          "200": {
            "description": "Menu pobrane pomyślnie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestaurantMenuResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/inquiries": {
      "post": {
        "tags": ["Rezerwacje i Sandbox"],
        "summary": "Prześlij zapytanie o rezerwację lub przyjęcie",
        "description": "Pozwala agentom AI złożyć zapytanie rezerwacyjne lub wycenę imprezy. W środowisku sandbox natychmiast generuje potwierdzenie z kodem referencyjnym.",
        "operationId": "createBookingInquiry",
        "requestBody": {
          "required": true,
          "description": "Dane zgłoszenia rezerwacji",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InquiryRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Zapytanie przyjęte pomyślnie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InquiryResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequestError"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/auth/sandbox-key": {
      "post": {
        "tags": ["Rezerwacje i Sandbox"],
        "summary": "Wygeneruj natychmiastowy darmowy klucz API do sandboxa",
        "description": "Bezpłatne, natychmiastowe generowanie klucza testowego dla agentów AI bez kontaktu z obsługą (self-serve onboarding).",
        "operationId": "createSandboxApiKey",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxKeyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Klucz sandbox wygenerowany pomyślnie",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxKeyResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    },
    "/api/v1/sandbox": {
      "get": {
        "tags": ["Rezerwacje i Sandbox"],
        "summary": "Pobierz status środowiska sandbox i instrukcje",
        "description": "Zwraca parametry środowiska sandbox, zasady testowania, limity zapytań (100 zapytań/min) oraz przykłady nagłówków.",
        "operationId": "getSandboxEnvironmentStatus",
        "responses": {
          "200": {
            "description": "Informacje o środowisku testowym",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxStatusResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PensjonatInfo": {
        "type": "object",
        "required": ["name", "address", "phone", "email", "coordinates", "capacity"],
        "properties": {
          "name": {
            "type": "string",
            "example": "Pensjonat Korona"
          },
          "legalName": {
            "type": "string",
            "example": "PENSJONAT KORONA S.C. BOGUMIŁA, MONIKA I SYLWESTER BUGAJ"
          },
          "address": {
            "type": "object",
            "required": ["street", "city", "postalCode", "region", "country"],
            "properties": {
              "street": { "type": "string", "example": "ul. Konopnickiej 43, Modrzyca" },
              "city": { "type": "string", "example": "Nowa Sól" },
              "postalCode": { "type": "string", "example": "67-106" },
              "region": { "type": "string", "example": "woj. lubuskie" },
              "country": { "type": "string", "example": "Polska" }
            }
          },
          "phone": { "type": "string", "example": "+48 68 355 04 65" },
          "email": { "type": "string", "format": "email", "example": "kontakt@pensjonat-korona.pl" },
          "website": { "type": "string", "format": "uri", "example": "https://pensjonat-korona.pl" },
          "coordinates": {
            "type": "object",
            "required": ["latitude", "longitude"],
            "properties": {
              "latitude": { "type": "number", "example": 51.8346313 },
              "longitude": { "type": "number", "example": 15.7198034 }
            }
          },
          "checkInTime": { "type": "string", "example": "14:00" },
          "checkOutTime": { "type": "string", "example": "12:00" },
          "capacity": {
            "type": "object",
            "required": ["totalRooms", "totalBeds", "banquetCapacity"],
            "properties": {
              "totalRooms": { "type": "integer", "example": 25 },
              "totalBeds": { "type": "integer", "example": 50 },
              "banquetCapacity": { "type": "integer", "example": 200 }
            }
          },
          "amenities": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["Free WiFi", "Free Parking", "Private Bathroom", "TV", "Air Conditioned Hall", "Garden & BBQ Gazebo", "Restaurant"]
          }
        }
      },
      "RoomType": {
        "type": "object",
        "required": ["id", "name", "capacity", "pricePerNightPln", "breakfastOptionPln", "amenities"],
        "properties": {
          "id": { "type": "string", "example": "single" },
          "name": { "type": "string", "example": "Pokój 1-osobowy" },
          "capacity": { "type": "integer", "example": 1 },
          "pricePerNightPln": { "type": "number", "example": 190 },
          "breakfastOptionPln": { "type": "number", "example": 20 },
          "description": { "type": "string", "example": "Wygodny pokój jednoosobowy z prywatną łazienką i biurkiem do pracy." },
          "amenities": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["Prywatna łazienka z prysznicem", "Telewizor LCD", "Szybkie Wi-Fi", "Ręczniki", "Kosmetyki"]
          }
        }
      },
      "RoomsResponse": {
        "type": "object",
        "required": ["success", "totalRooms", "rooms"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "totalRooms": { "type": "integer", "example": 25 },
          "rooms": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/RoomType" }
          }
        }
      },
      "AvailabilityResponse": {
        "type": "object",
        "required": ["success", "available", "checkIn", "checkOut", "nights", "guests", "recommendedRoom", "estimatedTotalPln"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "available": { "type": "boolean", "example": true },
          "checkIn": { "type": "string", "format": "date", "example": "2026-11-01" },
          "checkOut": { "type": "string", "format": "date", "example": "2026-11-03" },
          "nights": { "type": "integer", "example": 2 },
          "guests": { "type": "integer", "example": 2 },
          "recommendedRoom": { "$ref": "#/components/schemas/RoomType" },
          "estimatedTotalPln": { "type": "number", "example": 480 },
          "estimatedWithBreakfastPln": { "type": "number", "example": 560 },
          "bookingHint": { "type": "string", "example": "Zadzwoń pod 68 355 04 65 lub wyślij zapytanie przez POST /api/v1/inquiries." }
        }
      },
      "PricingResponse": {
        "type": "object",
        "required": ["success", "currency", "rooms", "breakfast", "events"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "currency": { "type": "string", "example": "PLN" },
          "rooms": {
            "type": "object",
            "required": ["single", "double", "triple"],
            "properties": {
              "single": { "type": "number", "example": 190 },
              "double": { "type": "number", "example": 240 },
              "triple": { "type": "number", "example": 300 }
            }
          },
          "breakfast": { "type": "number", "example": 20 },
          "events": {
            "type": "object",
            "properties": {
              "weddingPackageFrom": { "type": "number", "example": 220 },
              "communionFrom": { "type": "number", "example": 140 },
              "wakeFrom": { "type": "number", "example": 65 },
              "gazeboRentalFrom": { "type": "number", "example": 500 }
            }
          }
        }
      },
      "EventInfoResponse": {
        "type": "object",
        "required": ["success", "hallName", "capacityMax", "supportedEvents", "features"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "hallName": { "type": "string", "example": "Sala Bankietowa Pensjonat Korona" },
          "capacityMax": { "type": "integer", "example": 200 },
          "supportedEvents": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["Wesela", "Komunie", "Chrzciny", "18-stki i Urodziny", "Jubileusze", "Stypy i konsolacje", "Wigilie firmowe", "Biesiady grillowe"]
          },
          "features": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["Wydajna klimatyzacja", "Parkiet taneczny", "Nagłośnienie estradowe", "Zadaszona altana grillowa", "Ogród z sercem kwiatowym", "Baza 50 noclegów na miejscu"]
          }
        }
      },
      "RestaurantMenuResponse": {
        "type": "object",
        "required": ["success", "cuisineType", "categories"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "cuisineType": { "type": "string", "example": "Polska i Europejska" },
          "categories": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["categoryName", "items"],
              "properties": {
                "categoryName": { "type": "string" },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": ["name", "pricePln"],
                    "properties": {
                      "name": { "type": "string" },
                      "pricePln": { "type": "number" },
                      "description": { "type": "string" }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "InquiryRequest": {
        "type": "object",
        "required": ["name", "phone", "inquiryType"],
        "properties": {
          "name": { "type": "string", "example": "Jan Kowalski" },
          "phone": { "type": "string", "example": "+48 500 600 700" },
          "email": { "type": "string", "format": "email", "example": "jan.kowalski@example.com" },
          "inquiryType": {
            "type": "string",
            "enum": ["room", "wedding", "event", "restaurant"],
            "example": "room"
          },
          "dateFrom": { "type": "string", "format": "date", "example": "2026-11-01" },
          "dateTo": { "type": "string", "format": "date", "example": "2026-11-03" },
          "guests": { "type": "integer", "example": 2 },
          "notes": { "type": "string", "example": "Rezerwacja pokoju 2-osobowego ze śniadaniem." }
        }
      },
      "InquiryResponse": {
        "type": "object",
        "required": ["success", "referenceNumber", "status", "mode", "summary"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "referenceNumber": { "type": "string", "example": "KORONA-TEST-8492" },
          "status": { "type": "string", "example": "CONFIRMED_SANDBOX" },
          "mode": { "type": "string", "example": "sandbox" },
          "summary": { "type": "string", "example": "Zapytanie testowe przyjęte. W trybie produkcyjnym obsługa obiektu potwierdza rezerwację telefonicznie w ciągu 24h." }
        }
      },
      "SandboxKeyRequest": {
        "type": "object",
        "properties": {
          "agentName": { "type": "string", "example": "claude-agent" }
        }
      },
      "SandboxKeyResponse": {
        "type": "object",
        "required": ["success", "apiKey", "rateLimit", "environment", "expiresAt"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "apiKey": { "type": "string", "example": "pk_sandbox_3f9a7b2c" },
          "rateLimit": { "type": "string", "example": "100 requests per minute" },
          "environment": { "type": "string", "example": "sandbox" },
          "expiresAt": { "type": "string", "format": "date-time", "example": "2027-10-30T00:00:00Z" }
        }
      },
      "SandboxStatusResponse": {
        "type": "object",
        "required": ["success", "sandboxActive", "freeTier", "rateLimit", "testEndpoints"],
        "properties": {
          "success": { "type": "boolean", "example": true },
          "sandboxActive": { "type": "boolean", "example": true },
          "freeTier": { "type": "string", "example": "100% otwarty dostęp do GET bez klucza, self-serve klucze dla POST" },
          "rateLimit": { "type": "string", "example": "100 req/min" },
          "testEndpoints": {
            "type": "array",
            "items": { "type": "string" },
            "example": ["/api/v1/info", "/api/v1/rooms", "/api/v1/availability", "/api/v1/inquiries"]
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": ["success", "error"],
        "properties": {
          "success": { "type": "boolean", "example": false },
          "error": {
            "type": "object",
            "required": ["code", "message", "resolution_hint"],
            "properties": {
              "code": { "type": "string", "example": "INVALID_QUERY_PARAMS" },
              "message": { "type": "string", "example": "checkIn and checkOut parameters are required." },
              "resolution_hint": { "type": "string", "example": "Provide query parameters checkIn and checkOut in YYYY-MM-DD format." }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequestError": {
        "description": "Nieprawidłowe zapytanie lub brakujące parametry",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFoundError": {
        "description": "Zasób lub punkt końcowy nie istnieje",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Wewnętrzny błąd serwera",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}
