{"openapi":"3.0.3","info":{"title":"Pobytovka Core API","version":"0.1.0","description":"Agent-first rezervační API. REST endpointy jsou 1:1 zrcadlem MCP toolů (streamable HTTP na /mcp). Deterministické error kódy, idempotentní create_hold, quote s garantovanou platností."},"servers":[{"url":"https://www.pobytovka.cz","description":"test/prod dle BASE_PATH"}],"tags":[{"name":"reservations","description":"Rezervační core tools (1:1 zrcadlo MCP)"},{"name":"owners","description":"Registrace a správa vlastníků (owner-facing; mimo MCP)"},{"name":"properties","description":"Nemovitosti vlastníka — create/list (owner-facing; mimo MCP)"},{"name":"surcharges","description":"Fixní příplatky nemovitosti — ceník krok ③ (owner-facing; mimo MCP)"},{"name":"photos","description":"Fotky nemovitosti — per-foto AI moderation_status; owner CRUD, veřejně jen approved (I14a; mimo MCP)"},{"name":"tourist-tax","description":"Poplatek z pobytu (místní daň) nemovitosti — sazba dle vyhlášky obce, onboarding krok ⑤ (owner-facing; mimo MCP)"},{"name":"calendar","description":"Kalendářní blokace nemovitosti — ruční blokace vlastníkem (owner-facing; mimo MCP)"},{"name":"ical","description":"iCal import — zaregistrované externí feedy (Booking/Airbnb/Google) + sync (owner-facing; mimo MCP)"},{"name":"messaging","description":"Vlákno zpráv u rezervace — host ⇄ vlastník (owner/host-facing; mimo MCP)"},{"name":"payments","description":"Platební instrukce rezervace — režim A přímá platba (celý total) + režim B záloha (deposit) + SPAYD/QR (host-facing) + ruční potvrzení přijaté zálohy vlastníkem (owner-facing, I5b-3); mimo MCP"},{"name":"checkin","description":"Online check-in — zákonná evidence hostů u rezervace (host zapisuje, vlastník čte; mimo MCP)"},{"name":"billing","description":"Monetizace — hodnotové počítadlo vlastníka (usage read-model; pilot bez fakturace; mimo MCP)"},{"name":"admin","description":"Interní admin — foto-moderační fronta (manuální approve/reject); shared-secret X-Admin-Token, mimo MCP (I17a)"},{"name":"owner-auth","description":"Přihlášení vlastníka magic-linkem — pb_owner session (issue → verify → whoami); JINÁ identita než host, mimo MCP (I18a)"}],"paths":{"/api/search":{"get":{"operationId":"search_properties","summary":"Hledat nemovitosti","description":"Vyhledá ubytování dle lokality, termínu a kapacity. Vrací public_id, název, URL property page, kapacitu, cenu od, typ storna a příznak ověřeného vlastníka. Se zadaným termínem přidá dostupnost a odhad celkové ceny.\n\n(MCP tool: `search_properties` — REST je 1:1 zrcadlo.)","tags":["reservations"],"responses":{"200":{"description":"OK"},"400":{"description":"Chyba vstupu / doménová chyba","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"parameters":[{"name":"location","in":"query","required":false,"schema":{"type":"string","minLength":1,"description":"Lokalita / region / název (např. \"Beskydy\")"},"description":"Lokalita / region / název (např. \"Beskydy\")"},{"name":"date_from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Příjezd — pokud zadáno s date_to, vrátí i dostupnost a odhad ceny"},"description":"Příjezd — pokud zadáno s date_to, vrátí i dostupnost a odhad ceny"},{"name":"date_to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Odjezd (den odjezdu, exkluzivně)"},"description":"Odjezd (den odjezdu, exkluzivně)"},{"name":"guests","in":"query","required":false,"schema":{"type":"integer","exclusiveMinimum":true,"minimum":0,"maximum":50,"description":"Počet hostů (kapacita ≥ guests)"},"description":"Počet hostů (kapacita ≥ guests)"},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["chata","chalupa","apartman","penzion"]}},{"name":"verified_only","in":"query","required":false,"schema":{"type":"boolean","description":"Jen ověření vlastníci"},"description":"Jen ověření vlastníci"},{"name":"price_max_czk","in":"query","required":false,"schema":{"type":"integer","exclusiveMinimum":true,"minimum":0,"description":"Max cena za noc (Kč)"},"description":"Max cena za noc (Kč)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","exclusiveMinimum":true,"minimum":0,"maximum":50}}]}},"/api/availability":{"get":{"operationId":"get_availability","summary":"Dostupnost","description":"Vrátí volné/blokované dny nemovitosti v rozsahu (zdroj blokace: manual/ical/booking). Volitelný `unit` (public_id/slug jednotky z units[] v search) zúží dostupnost na konkrétní pokoj/apartmán; vynecháno/null = celá nemovitost. Neexistující/nepublikovaná/nebookovatelná jednotka nebo objekt bez samostatných jednotek → 404 UNIT_NOT_FOUND.\n\n(MCP tool: `get_availability` — REST je 1:1 zrcadlo.)","tags":["reservations"],"responses":{"200":{"description":"OK"},"400":{"description":"Chyba vstupu / doménová chyba","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"parameters":[{"name":"property_id","in":"query","required":true,"schema":{"type":"string","minLength":1,"description":"public_id nebo slug nemovitosti"},"description":"public_id nebo slug nemovitosti"},{"name":"from","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Datum ve formátu YYYY-MM-DD"},"description":"Datum ve formátu YYYY-MM-DD"},{"name":"to","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Datum ve formátu YYYY-MM-DD"},"description":"Datum ve formátu YYYY-MM-DD"},{"name":"unit","in":"query","required":false,"schema":{"type":"string","minLength":1,"nullable":true,"description":"public_id/slug jednotky pro dostupnost konkrétního pokoje/apartmánu; vynecháno/null = celá nemovitost"},"description":"public_id/slug jednotky pro dostupnost konkrétního pokoje/apartmánu; vynecháno/null = celá nemovitost"}]}},"/api/quotes":{"post":{"operationId":"get_quote","summary":"Cenová nabídka","description":"Vytvoří závaznou cenovou nabídku (quote_id) s plným rozpadem ceny včetně poplatku z pobytu a strojově čitelnými storno podmínkami. Quote má garantovanou platnost (expires_at ≥ 30 min). Cena je finální — žádné překvapení na checkoutu. Volitelný `unit` (public_id/slug jednotky z units[] v search) spočítá nabídku ve scope konkrétního pokoje/apartmánu a quote si jednotku zapamatuje pro create_hold; vynecháno/null = celá nemovitost. Neexistující/nepublikovaná/nebookovatelná jednotka nebo objekt bez samostatných jednotek → 404 UNIT_NOT_FOUND. Objekt v režimu „jen po jednotkách\" bez zvolené jednotky → 422 UNIT_REQUIRED (zvol konkrétní jednotku).\n\n(MCP tool: `get_quote` — REST je 1:1 zrcadlo.)","tags":["reservations"],"responses":{"200":{"description":"OK"},"400":{"description":"Chyba vstupu / doménová chyba","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"property_id":{"type":"string","minLength":1,"description":"public_id nebo slug nemovitosti"},"date_from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Datum ve formátu YYYY-MM-DD"},"date_to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Datum ve formátu YYYY-MM-DD"},"adults":{"type":"integer","exclusiveMinimum":true,"minimum":0,"maximum":50,"description":"Počet dospělých (základ pro poplatek z pobytu)"},"children_ages":{"type":"array","items":{"type":"integer","minimum":0,"maximum":17},"description":"Věky dětí (osvobození od poplatku dle obce)"},"unit":{"type":"string","minLength":1,"nullable":true,"description":"public_id/slug jednotky pro rezervaci konkrétního pokoje/apartmánu; vynecháno/null = celá nemovitost"}},"required":["property_id","date_from","date_to","adults"],"additionalProperties":false}}}}}},"/api/holds":{"post":{"operationId":"create_hold","summary":"Vytvořit hold","description":"Podrží termín (TTL, blokuje dvojí rezervaci) a vrátí hold_id, checkout_url (kde člověk dokončí) a status_url. Idempotentní dle quote_id + guest_email — opakované volání vrátí stejný hold. Karta/údaje hosta NIKDY nejdou přes agenta. Rezervuje ve scope jednotky zvolené v get_quote (quote v sobě nese unit_id) — u rezervace konkrétní jednotky odpověď (a stejně tak get_booking_status) nese `unit`: {unit_id, name}; u rezervace celého objektu se `unit` vynechává. Chybové kódy (write-path): pokud vlastník mezi get_quote a create_hold přepnul režim rezervovatelnosti — unit quote na objektu vráceném na režim „celý objekt\" → 409 BOOKING_MODE_CONFLICT; rezervace celku na objektu v režimu „jen po jednotkách\" → 422 UNIT_REQUIRED (vyžádej si nový quote s konkrétní jednotkou); obsazený termín ve scope jednotky/celku mezitím → 409 DATES_UNAVAILABLE.\n\n(MCP tool: `create_hold` — REST je 1:1 zrcadlo.)","tags":["reservations"],"responses":{"200":{"description":"OK"},"400":{"description":"Chyba vstupu / doménová chyba","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"quote_id":{"type":"string","minLength":1,"description":"quote_id z get_quote (musí být platný)"},"guest_name":{"type":"string","minLength":2,"description":"Jméno hosta"},"guest_email":{"type":"string","format":"email","description":"E-mail hosta (idempotence: quote_id + email)"},"guest_phone":{"type":"string","minLength":4},"note":{"type":"string","maxLength":500,"description":"Poznámka pro vlastníka"}},"required":["quote_id","guest_name","guest_email"],"additionalProperties":false}}}}}},"/api/bookings/{id}":{"get":{"operationId":"get_booking_status","summary":"Stav rezervace","description":"Vrátí aktuální stav rezervace/holdu a doporučený další krok. Přijímá booking_id i hold_id (je to totéž ID). U rezervace konkrétní jednotky nese `unit`: {unit_id, name} (z uložené jednotky rezervace — drží i po potvrzení/stornu); u rezervace celého objektu se `unit` vynechává.\n\n(MCP tool: `get_booking_status` — REST je 1:1 zrcadlo.)","tags":["reservations"],"responses":{"200":{"description":"OK"},"400":{"description":"Chyba vstupu / doménová chyba","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/api/bookings/{id}/cancel":{"post":{"operationId":"cancel_booking","summary":"Storno rezervace","description":"Zruší rezervaci, aplikuje storno politiku a uvolní termín. Vrací konkrétní storno breakdown (`refund`): kolik Kč se z reálné ceny vrací a kolik propadá podle počtu dní do příjezdu a storno politiky — žádné překvapení.\n\n(MCP tool: `cancel_booking` — REST je 1:1 zrcadlo.)","tags":["reservations"],"responses":{"200":{"description":"OK"},"400":{"description":"Chyba vstupu / doménová chyba","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"booking_id":{"type":"string","minLength":1,"description":"booking_id / hold_id ke stornu"},"reason":{"type":"string","maxLength":255}},"required":["booking_id"],"additionalProperties":false}}}}}},"/api/owners":{"post":{"operationId":"register_owner","summary":"Registrace vlastníka","description":"Zaregistruje vlastníka s POVINNÝM verzovaným souhlasem (podmínky + GDPR). Idempotentní na e-mailu (duplicita → 409 OWNER_EXISTS). Bez souhlasu → 422 CONSENT_REQUIRED. Není MCP tool.","tags":["owners"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":160,"description":"Jméno nebo název vlastníka"},"email":{"type":"string","format":"email","maxLength":190,"description":"Kontaktní e-mail (unikátní; idempotence registrace)"},"phone":{"type":"string","minLength":4,"maxLength":40,"description":"Telefon (volitelný)"},"bank_account":{"type":"string","minLength":4,"maxLength":60,"description":"Číslo účtu pro platební instrukce (volitelné, fáze 1)"},"password":{"type":"string","minLength":8,"maxLength":200,"description":"Heslo pro přihlášení e-mailem (volitelné; min. délka dle konfigurace). Bez něj účet používá jen magic-link."},"consent":{"type":"boolean","default":false,"description":"Souhlas s Podmínkami užití a zpracováním osobních údajů (GDPR) — POVINNÝ, musí být true"}},"required":["name","email"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Vlastník (bez citlivých polí) se stavem verzovaného souhlasu.","properties":{"owner_id":{"type":"string","description":"Stabilní veřejné ID vlastníka (own_xxx)"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string","nullable":true},"verified_owner":{"type":"boolean","description":"Ověřen datovkou (fáze 1; zatím false)"},"created_at":{"type":"string","format":"date-time"},"consent":{"type":"object","properties":{"granted":{"type":"boolean"},"terms_version":{"type":"string"},"gdpr_version":{"type":"string"},"consented_at":{"type":"string","format":"date-time"}},"required":["granted"]}},"required":["owner_id","name","email","verified_owner","consent"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"409":{"description":"E-mail už registrován (OWNER_EXISTS)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Chybí souhlas (CONSENT_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/api/owners/{id}":{"get":{"operationId":"get_owner","summary":"Detail vlastníka","description":"Vrátí vlastníka (bez citlivých polí) a stav verzovaného souhlasu. Není MCP tool.","tags":["owners"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Vlastník (bez citlivých polí) se stavem verzovaného souhlasu.","properties":{"owner_id":{"type":"string","description":"Stabilní veřejné ID vlastníka (own_xxx)"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string","nullable":true},"verified_owner":{"type":"boolean","description":"Ověřen datovkou (fáze 1; zatím false)"},"created_at":{"type":"string","format":"date-time"},"consent":{"type":"object","properties":{"granted":{"type":"boolean"},"terms_version":{"type":"string"},"gdpr_version":{"type":"string"},"consented_at":{"type":"string","format":"date-time"}},"required":["granted"]}},"required":["owner_id","name","email","verified_owner","consent"]}}}},"404":{"description":"Vlastník neexistuje (OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/api/owners/{ownerId}/properties":{"post":{"operationId":"create_property","summary":"Založ nemovitost (draft)","description":"Vytvoří nemovitost pod vlastníkem jako DRAFT (nepublikovaná — live až po dokončení onboardingu). Cena/ceník sem nepatří (krok ③). Neexistující vlastník → 404 OWNER_NOT_FOUND. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":190,"description":"Název nemovitosti"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"],"default":"chalupa","description":"Typ objektu"},"region":{"type":"string","minLength":2,"maxLength":120,"description":"Region/oblast (Beskydy, Krkonoše…) — pro vyhledávání"},"address":{"type":"string","maxLength":255,"description":"Adresa (volitelné)"},"lat":{"type":"number","minimum":-90,"maximum":90,"description":"Zeměpisná šířka"},"lng":{"type":"number","minimum":-180,"maximum":180,"description":"Zeměpisná délka"},"capacity":{"type":"integer","minimum":1,"maximum":100,"description":"Maximální počet hostů"},"bedrooms":{"type":"integer","minimum":0,"maximum":50,"default":1,"description":"Počet ložnic"},"description":{"type":"string","maxLength":5000,"description":"Popis nemovitosti"},"amenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":40,"description":"Vybavení (wifi, krb, sauna…)"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"],"description":"Storno šablona (výběr ze 3 úrovní fáze 0)"},"payment_mode":{"type":"string","enum":["direct","deposit"],"description":"Platební režim: direct = přímá platba, deposit = záloha + doplatek"},"deposit_percent":{"type":"integer","minimum":1,"maximum":100,"description":"Záloha režimu B: procento z ceny placené předem (1–100); jen payment_mode=deposit"},"instant_book":{"type":"boolean","description":"Potvrzovací režim: true = instant-book (auto-potvrzení, opt-in vlastníka); false/nezadáno = manuální potvrzení do 24 h"}},"required":["name","region","capacity","cancellation_policy","payment_mode"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Vlastník neexistuje (OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"list_owner_properties","summary":"Seznam nemovitostí vlastníka","description":"Vrátí nemovitosti daného vlastníka (draft i published), nejnovější první. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"owner_id":{"type":"string"},"count":{"type":"integer"},"properties":{"type":"array","items":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}},"required":["owner_id","count","properties"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Vlastník neexistuje (OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}":{"patch":{"operationId":"update_property","summary":"Uprav nemovitost (částečně)","description":"Částečná úprava editovatelných polí kroku ② (pošle se jen podmnožina; nezaslaná pole se nemění). NEmění status/active/base_price ani slug (změna name slug NEpřegeneruje — stabilní URL). Prázdné tělo / neznámé pole / půl GPS → 400. Cizí nebo neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":190},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"region":{"type":"string","minLength":2,"maxLength":120},"address":{"type":"string","maxLength":255},"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"capacity":{"type":"integer","minimum":1,"maximum":100},"bedrooms":{"type":"integer","minimum":0,"maximum":50},"description":{"type":"string","maxLength":5000},"amenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":40},"maxItems":40},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":"integer","minimum":1,"maximum":100},"instant_book":{"type":"boolean"},"bathrooms":{"type":"integer","minimum":0,"maximum":50,"nullable":true},"house_rules":{"type":"string","maxLength":5000,"nullable":true},"website_url":{"type":"string","format":"uri","maxLength":255,"nullable":true},"heating":{"type":"string","enum":["centralni","tuha_paliva","elektro","tepelne_cerpadlo","krb","plyn","jine"],"nullable":true},"beds_note":{"type":"string","maxLength":255,"nullable":true},"pets":{"type":"string","enum":["yes","on_request","fee","no"],"nullable":true},"parking":{"type":"string","enum":["on_site","street","none"],"nullable":true}},"additionalProperties":false}}}},"responses":{"200":{"description":"Upraveno","content":{"application/json":{"schema":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/deactivate":{"post":{"operationId":"deactivate_property","summary":"Pozastav nemovitost (active=0)","description":"Pozastaví nemovitost (active=0) — zmizí ze všech veřejných povrchů (search/quote/property page), ale NENÍ smazána (historie/rezervace zůstávají). Idempotentní (2× → stále 200, active=0). Cizí/neexistující → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/reactivate":{"post":{"operationId":"reactivate_property","summary":"Obnov nemovitost (active=1)","description":"Obnoví pozastavenou nemovitost (active=1) — vrátí se do veřejných povrchů. Idempotentní. Cizí/neexistující → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/pricing":{"put":{"operationId":"set_property_pricing","summary":"Nastav ceník nemovitosti (základní cena + min. pobyt + úklid)","description":"Onboarding krok ③ (jádro ceníku): nastaví property-row pole, která create/PATCH neplní — base_price_czk (povinné, > 0), min_nights (volitelné ≥ 1), cleaning_fee_czk (volitelné ≥ 0). Funguje na draftu (poprvé mu dá cenu — prerekvizita publikace) i published (úprava ceníku kdykoli). Nezaslané min_nights/cleaning_fee se NEMĚNÍ (partial, jako PATCH). base_price chybí/≤0 / neznámé pole / prázdné tělo → 400. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"base_price_czk":{"type":"integer","minimum":1,"maximum":10000000,"description":"Základní cena za noc (Kč, > 0)"},"min_nights":{"type":"integer","minimum":1,"maximum":365,"description":"Minimální délka pobytu (nocí, ≥ 1)"},"cleaning_fee_czk":{"type":"integer","minimum":0,"maximum":10000000,"description":"Úklidový poplatek za pobyt (Kč, ≥ 0)"}},"required":["base_price_czk"],"additionalProperties":false}}}},"responses":{"200":{"description":"Ceník nastaven","content":{"application/json":{"schema":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/publish":{"post":{"operationId":"publish_property","summary":"Publikuj nemovitost (draft→published)","description":"Publikace (onboarding krok ④): draft→published — nemovitost se objeví ve vyhledávání (search), get_quote/create_hold, na property page i v iCal exportu. PODMÍNKA: musí mít nastavenou základní cenu (base_price_czk > 0, přes PUT …/pricing) — bez ní → 422 PRICING_REQUIRED (zůstane draft, aby se do search/quote nedostala property bez ceny). Idempotentní (už published → 200 no-op). Bez těla. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK — nový lifecycle stav ve `status`","content":{"application/json":{"schema":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Nemovitost nemá základní cenu (PRICING_REQUIRED) — nelze publikovat","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/unpublish":{"post":{"operationId":"unpublish_property","summary":"Stáhni nemovitost z veřejnosti (published→draft)","description":"Stažení z veřejnosti: published→draft — nemovitost zmizí z vyhledávání/quote/property page (vrátí se do rozpracovaného stavu, lze dál editovat). NESAHÁ na `active` (to je samostatná osa — deactivate = dočasná pauza published property). Idempotentní (už draft → 200 no-op). Bez těla. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["properties"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK — nový lifecycle stav ve `status`","content":{"application/json":{"schema":{"type":"object","description":"Nemovitost vlastníka (bez interního id). Draft po založení; publikace je pozdější krok.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID (prop_xxx)"},"slug":{"type":"string","description":"Slug pro property page URL /p/<slug>"},"name":{"type":"string"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"]},"status":{"type":"string","enum":["draft","published"],"description":"Lifecycle nemovitosti"},"region":{"type":"string"},"address":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"lat":{"type":"number"},"lng":{"type":"number"}}},"capacity":{"type":"integer"},"bedrooms":{"type":"integer"},"description":{"type":"string","nullable":true},"amenities":{"type":"array","items":{"type":"string"}},"photos":{"type":"array","items":{"type":"string"},"description":"URL APPROVED fotek (I14a): jen moderation_status=approved z property_photo, řazené dle sort_order. Pending/rejected/review se veřejně nezobrazí. Owner vidí všechny se stavem přes GET …/photos."},"base_price_czk":{"type":"integer","nullable":true,"description":"null u draftu (ceník = pozdější krok ③)"},"cleaning_fee_czk":{"type":"integer"},"min_nights":{"type":"integer"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"]},"payment_mode":{"type":"string","enum":["direct","deposit"]},"deposit_percent":{"type":["integer","null"],"description":"Záloha režimu B (I5b-1): procento z ceny placené předem (1–100); null = neurčeno / režim A. Propíše se do get_quote breakdownu (blok deposit) jen u payment_mode=deposit."},"instant_book":{"type":"boolean","description":"Potvrzovací režim (I11a): true = instant-book (auto-potvrzení, opt-in vlastníka); false = manuální potvrzení vlastníkem do 24 h (default). I11a jen persistuje flag — aplikaci v hold-flow (rovnou CONFIRMED) přidá I11b."},"checkin_time":{"type":"string"},"checkout_time":{"type":"string"},"active":{"type":"boolean"},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","status","region","capacity","cancellation_policy","payment_mode"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/surcharges":{"post":{"operationId":"create_surcharge","summary":"Přidej příplatek (fixní nebo procentní)","description":"Přidá příplatek k nemovitosti. `kind`=fixed → fixní částka `amount_czk` × `per` (booking/night/person/person_night); `kind`=percent → `percent` % (1–100) z ceny za ubytování (accommodation subtotal). `kind` lze vynechat (default fixed). Propíše se položkově do get_quote breakdownu (jen active=1). Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["surcharges"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":2,"maxLength":120,"description":"Název příplatku (zobrazí se v rozpadu ceny)"},"kind":{"type":"string","enum":["fixed","percent"],"default":"fixed","description":"fixed = fixní částka (amount_czk × per); percent = procento z ceny za ubytování"},"amount_czk":{"type":"integer","minimum":1,"maximum":1000000,"description":"Fixní částka v Kč (kladná) — jen pro kind=fixed"},"percent":{"type":"integer","minimum":1,"maximum":100,"description":"Procento 1–100 (celé %) z ceny za ubytování — jen pro kind=percent"},"per":{"type":"string","enum":["booking","night","person","person_night"],"description":"Jen fixed — jak se částka násobí: booking=celý pobyt, night=za noc, person=za osobu, person_night=za osobu a noc"}},"required":["label"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Příplatek nemovitosti (bez interního id). `kind`=fixed → amount_czk × `per`; `kind`=percent → procento z ceny za ubytování.","properties":{"surcharge_id":{"type":"string","description":"Stabilní veřejné ID (sur_xxx)"},"label":{"type":"string","description":"Název příplatku (zobrazí se v rozpadu ceny)"},"kind":{"type":"string","enum":["fixed","percent"],"description":"fixed = fixní částka; percent = procento z accommodation subtotalu"},"amount_czk":{"type":["integer","null"],"description":"Fixní částka v Kč (kind=fixed); null pro percent"},"percent":{"type":["integer","null"],"description":"Procento 1–100 z ceny za ubytování (kind=percent); null pro fixed"},"per":{"type":"string","enum":["booking","night","person","person_night"],"description":"Jen fixed: booking=celý pobyt, night=za noc, person=za osobu, person_night=za osobu a noc"},"active":{"type":"boolean","description":"Deaktivovaný (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"}},"required":["surcharge_id","label","kind","per","active"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"list_surcharges","summary":"Seznam příplatků nemovitosti","description":"Vrátí příplatky nemovitosti (fixní i procentní, vč. deaktivovaných), nejnovější první. Není MCP tool.","tags":["surcharges"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"property_id":{"type":"string"},"count":{"type":"integer"},"surcharges":{"type":"array","items":{"type":"object","description":"Příplatek nemovitosti (bez interního id). `kind`=fixed → amount_czk × `per`; `kind`=percent → procento z ceny za ubytování.","properties":{"surcharge_id":{"type":"string","description":"Stabilní veřejné ID (sur_xxx)"},"label":{"type":"string","description":"Název příplatku (zobrazí se v rozpadu ceny)"},"kind":{"type":"string","enum":["fixed","percent"],"description":"fixed = fixní částka; percent = procento z accommodation subtotalu"},"amount_czk":{"type":["integer","null"],"description":"Fixní částka v Kč (kind=fixed); null pro percent"},"percent":{"type":["integer","null"],"description":"Procento 1–100 z ceny za ubytování (kind=percent); null pro fixed"},"per":{"type":"string","enum":["booking","night","person","person_night"],"description":"Jen fixed: booking=celý pobyt, night=za noc, person=za osobu, person_night=za osobu a noc"},"active":{"type":"boolean","description":"Deaktivovaný (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"}},"required":["surcharge_id","label","kind","per","active"]}}},"required":["property_id","count","surcharges"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/surcharges/{surchargeId}/deactivate":{"post":{"operationId":"deactivate_surcharge","summary":"Deaktivuj příplatek (active=0)","description":"Deaktivuje příplatek (active=0) — přestane se propisovat do NOVÝCH quote (už zmrazené quoty se nemění). NENÍ hard delete. Idempotentní. Cizí/neexistující příplatek → 404 SURCHARGE_NOT_FOUND. Není MCP tool.","tags":["surcharges"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"surchargeId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id příplatku (sur_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Příplatek nemovitosti (bez interního id). `kind`=fixed → amount_czk × `per`; `kind`=percent → procento z ceny za ubytování.","properties":{"surcharge_id":{"type":"string","description":"Stabilní veřejné ID (sur_xxx)"},"label":{"type":"string","description":"Název příplatku (zobrazí se v rozpadu ceny)"},"kind":{"type":"string","enum":["fixed","percent"],"description":"fixed = fixní částka; percent = procento z accommodation subtotalu"},"amount_czk":{"type":["integer","null"],"description":"Fixní částka v Kč (kind=fixed); null pro percent"},"percent":{"type":["integer","null"],"description":"Procento 1–100 z ceny za ubytování (kind=percent); null pro fixed"},"per":{"type":"string","enum":["booking","night","person","person_night"],"description":"Jen fixed: booking=celý pobyt, night=za noc, person=za osobu, person_night=za osobu a noc"},"active":{"type":"boolean","description":"Deaktivovaný (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"}},"required":["surcharge_id","label","kind","per","active"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Příplatek/nemovitost/vlastník neexistuje (SURCHARGE_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/photos":{"post":{"operationId":"add_photo","summary":"Přidej fotku (moderation_status=pending)","description":"Přidá fotku k nemovitosti. Startuje `moderation_status=pending` → veřejně NEviditelná dokud ji AI moderace (I14b, reálné Haiku vision) neschválí (§14: verdikt nelze podvrhnout tělem). `sort_order` volitelné (absence = na konec galerie). URL model (fyzický upload = samostatná osa). Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["photos"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","maxLength":1024,"description":"URL fotky (http/https)"},"sort_order":{"type":"integer","minimum":0,"maximum":32767,"description":"Pořadí ve veřejné galerii; absence = připojit na konec"}},"required":["url"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno (pending)","content":{"application/json":{"schema":{"type":"object","description":"Fotka nemovitosti (bez interního id) s per-foto stavem AI moderace (I14a). Owner vidí všechny se stavem; veřejné povrchy jen approved.","properties":{"photo_id":{"type":"string","description":"Stabilní veřejné ID (pho_xxx)"},"url":{"type":"string","description":"URL fotky"},"sort_order":{"type":"integer","description":"Pořadí ve veřejné galerii"},"moderation_status":{"type":"string","enum":["pending","approved","rejected","review"],"description":"Stav moderace: pending (nově přidaná, čeká na vision I14b) / approved (veřejně viditelná) / rejected / review (hraniční, admin fronta)"},"moderation_reason":{"type":["string","null"],"description":"Důvod zamítnutí / hraničnosti (naplní I14b vision; teď null)"},"content_type":{"type":["string","null"],"enum":["image/jpeg","image/png","image/webp",null],"description":"I14c: mime binárně nahrané fotky z magic-byte sniffu (null = URL/legacy fotka)"},"byte_size":{"type":["integer","null"],"description":"I14c: velikost uložených bajtů (null = URL/legacy fotka)"},"created_at":{"type":"string","format":"date-time"}},"required":["photo_id","url","sort_order","moderation_status"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"list_photos","summary":"Seznam fotek nemovitosti (owner — všechny se stavem)","description":"Vrátí VŠECHNY fotky nemovitosti (vč. pending/rejected/review) se stavem moderace, řazené dle sort_order. Owner view — veřejné povrchy (property page / search / property.photos) vrací JEN approved. Není MCP tool.","tags":["photos"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"property_id":{"type":"string"},"count":{"type":"integer"},"photos":{"type":"array","items":{"type":"object","description":"Fotka nemovitosti (bez interního id) s per-foto stavem AI moderace (I14a). Owner vidí všechny se stavem; veřejné povrchy jen approved.","properties":{"photo_id":{"type":"string","description":"Stabilní veřejné ID (pho_xxx)"},"url":{"type":"string","description":"URL fotky"},"sort_order":{"type":"integer","description":"Pořadí ve veřejné galerii"},"moderation_status":{"type":"string","enum":["pending","approved","rejected","review"],"description":"Stav moderace: pending (nově přidaná, čeká na vision I14b) / approved (veřejně viditelná) / rejected / review (hraniční, admin fronta)"},"moderation_reason":{"type":["string","null"],"description":"Důvod zamítnutí / hraničnosti (naplní I14b vision; teď null)"},"content_type":{"type":["string","null"],"enum":["image/jpeg","image/png","image/webp",null],"description":"I14c: mime binárně nahrané fotky z magic-byte sniffu (null = URL/legacy fotka)"},"byte_size":{"type":["integer","null"],"description":"I14c: velikost uložených bajtů (null = URL/legacy fotka)"},"created_at":{"type":"string","format":"date-time"}},"required":["photo_id","url","sort_order","moderation_status"]}}},"required":["property_id","count","photos"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/photos/{photoId}":{"patch":{"operationId":"reorder_photo","summary":"Přeřaď fotku (sort_order)","description":"Změní pořadí fotky ve veřejné galerii (sort_order). NEMĚNÍ moderation_status (moderace = I14b). Cizí/neexistující fotka → 404 PHOTO_NOT_FOUND. Není MCP tool.","tags":["photos"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"photoId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id fotky (pho_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sort_order":{"type":"integer","minimum":0,"maximum":32767,"description":"Nové pořadí ve veřejné galerii"}},"required":["sort_order"],"additionalProperties":false}}}},"responses":{"200":{"description":"Přeřazeno","content":{"application/json":{"schema":{"type":"object","description":"Fotka nemovitosti (bez interního id) s per-foto stavem AI moderace (I14a). Owner vidí všechny se stavem; veřejné povrchy jen approved.","properties":{"photo_id":{"type":"string","description":"Stabilní veřejné ID (pho_xxx)"},"url":{"type":"string","description":"URL fotky"},"sort_order":{"type":"integer","description":"Pořadí ve veřejné galerii"},"moderation_status":{"type":"string","enum":["pending","approved","rejected","review"],"description":"Stav moderace: pending (nově přidaná, čeká na vision I14b) / approved (veřejně viditelná) / rejected / review (hraniční, admin fronta)"},"moderation_reason":{"type":["string","null"],"description":"Důvod zamítnutí / hraničnosti (naplní I14b vision; teď null)"},"content_type":{"type":["string","null"],"enum":["image/jpeg","image/png","image/webp",null],"description":"I14c: mime binárně nahrané fotky z magic-byte sniffu (null = URL/legacy fotka)"},"byte_size":{"type":["integer","null"],"description":"I14c: velikost uložených bajtů (null = URL/legacy fotka)"},"created_at":{"type":"string","format":"date-time"}},"required":["photo_id","url","sort_order","moderation_status"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Fotka/nemovitost/vlastník neexistuje (PHOTO_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"delete":{"operationId":"delete_photo","summary":"Odeber fotku","description":"Odebere fotku nemovitosti (hard delete — zmizí z galerie i owner výpisu). Cizí/neexistující fotka → 404 PHOTO_NOT_FOUND. Není MCP tool.","tags":["photos"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"photoId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id fotky (pho_xxx)"}],"responses":{"200":{"description":"Odebráno","content":{"application/json":{"schema":{"type":"object","properties":{"photo_id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["photo_id","deleted"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Fotka/nemovitost/vlastník neexistuje (PHOTO_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/photos/upload":{"post":{"operationId":"upload_photo","summary":"Nahraj fotku (binární soubor)","description":"Binární upload fotky (multipart/form-data, pole `file`). Typ se ověřuje z REÁLNÝCH magic bytes (JPEG/PNG/WebP) — NE z přípony/Content-Type (§14). Bajty se ukládají content-addressed (sha256) a řádek startuje `moderation_status=pending` (jako add_photo → veřejně viditelná až po approved z I14b vision). Idempotence: stejné bajty pro tutéž nemovitost → 200 s existující fotkou (1 soubor + 1 řádek). Nepovolený typ → 415, nadlimit (8 MB) → 413, cizí/neexistující nemovitost → 404 — vše bez osiřelého souboru/řádku. Servírování přes GET /media/property/{propertyId}/{sha256}.{ext}. Není MCP tool.","tags":["photos"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Obrázek JPEG/PNG/WebP (≤ 8 MB)"}},"required":["file"]}}}},"responses":{"200":{"description":"Idempotentní shoda — stejné bajty už existují (žádný duplicitní zápis)","content":{"application/json":{"schema":{"type":"object","description":"Fotka nemovitosti (bez interního id) s per-foto stavem AI moderace (I14a). Owner vidí všechny se stavem; veřejné povrchy jen approved.","properties":{"photo_id":{"type":"string","description":"Stabilní veřejné ID (pho_xxx)"},"url":{"type":"string","description":"URL fotky"},"sort_order":{"type":"integer","description":"Pořadí ve veřejné galerii"},"moderation_status":{"type":"string","enum":["pending","approved","rejected","review"],"description":"Stav moderace: pending (nově přidaná, čeká na vision I14b) / approved (veřejně viditelná) / rejected / review (hraniční, admin fronta)"},"moderation_reason":{"type":["string","null"],"description":"Důvod zamítnutí / hraničnosti (naplní I14b vision; teď null)"},"content_type":{"type":["string","null"],"enum":["image/jpeg","image/png","image/webp",null],"description":"I14c: mime binárně nahrané fotky z magic-byte sniffu (null = URL/legacy fotka)"},"byte_size":{"type":["integer","null"],"description":"I14c: velikost uložených bajtů (null = URL/legacy fotka)"},"created_at":{"type":"string","format":"date-time"}},"required":["photo_id","url","sort_order","moderation_status"]}}}},"201":{"description":"Nahráno (nová fotka, pending)","content":{"application/json":{"schema":{"type":"object","description":"Fotka nemovitosti (bez interního id) s per-foto stavem AI moderace (I14a). Owner vidí všechny se stavem; veřejné povrchy jen approved.","properties":{"photo_id":{"type":"string","description":"Stabilní veřejné ID (pho_xxx)"},"url":{"type":"string","description":"URL fotky"},"sort_order":{"type":"integer","description":"Pořadí ve veřejné galerii"},"moderation_status":{"type":"string","enum":["pending","approved","rejected","review"],"description":"Stav moderace: pending (nově přidaná, čeká na vision I14b) / approved (veřejně viditelná) / rejected / review (hraniční, admin fronta)"},"moderation_reason":{"type":["string","null"],"description":"Důvod zamítnutí / hraničnosti (naplní I14b vision; teď null)"},"content_type":{"type":["string","null"],"enum":["image/jpeg","image/png","image/webp",null],"description":"I14c: mime binárně nahrané fotky z magic-byte sniffu (null = URL/legacy fotka)"},"byte_size":{"type":["integer","null"],"description":"I14c: velikost uložených bajtů (null = URL/legacy fotka)"},"created_at":{"type":"string","format":"date-time"}},"required":["photo_id","url","sort_order","moderation_status"]}}}},"400":{"description":"Chybí/prázdné pole `file` nebo není multipart/form-data (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"413":{"description":"Soubor nad limit 8 MB (PHOTO_TOO_LARGE)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"415":{"description":"Nepodporovaný typ — obsah není JPEG/PNG/WebP (PHOTO_TYPE_UNSUPPORTED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/media/property/{propertyId}/{filename}":{"get":{"operationId":"serve_photo","summary":"Streamuj binární fotku","description":"Vrátí uložené bajty fotky se správným Content-Type (image/jpeg|png|webp). Visibility guard: veřejně/agentem se streamují JEN fotky se stavem `approved`; pending/rejected/review → 404. Vlastník vidí i své nepublikované přes query `?owner=own_xxx`. `filename` = `<sha256>.<ext>` (content-addressed). Není MCP tool.","tags":["photos"],"parameters":[{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"filename","in":"path","required":true,"schema":{"type":"string"},"description":"Content-addressed jméno souboru: <sha256>.<jpg|png|webp>"},{"name":"owner","in":"query","required":false,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx) — zpřístupní i vlastní nepublikované fotky"}],"responses":{"200":{"description":"Bajty fotky","content":{"image/jpeg":{},"image/png":{},"image/webp":{}}},"404":{"description":"Fotka neexistuje / není approved (a žadatel není vlastník)"}}}},"/media/property/{propertyId}/thumb/{filename}":{"get":{"operationId":"serve_photo_thumbnail","summary":"Streamuj thumbnail fotky (reálný downscale)","description":"Vrátí REÁLNĚ zmenšenou variantu uložené fotky (šířka 400 px, zachovaný poměr stran) se správným Content-Type (image/jpeg|png|webp — formát originálu). Thumbnail vzniká skutečným převzorkováním uložených bajtů (Lanczos3), NE relabelem originálu (§14). Generuje se lazy při prvním requestu a kešuje na disk (druhý request čte z cache). Visibility guard IDENTICKÝ s /media/property/{propertyId}/{filename}: veřejně/agentem JEN `approved`; pending/rejected/review → 404; vlastník i své nepublikované přes `?owner=own_xxx`. `filename` = `<sha256>.<ext>` originálu (content-addressed). ETag → 304. Není MCP tool.","tags":["photos"],"parameters":[{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"filename","in":"path","required":true,"schema":{"type":"string"},"description":"Content-addressed jméno souboru ORIGINÁLU: <sha256>.<jpg|png|webp>"},{"name":"owner","in":"query","required":false,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx) — zpřístupní i vlastní nepublikované fotky"}],"responses":{"200":{"description":"Bajty thumbnailu","content":{"image/jpeg":{},"image/png":{},"image/webp":{}}},"304":{"description":"Nezměněno (If-None-Match odpovídá ETagu)"},"404":{"description":"Fotka neexistuje / není approved (a žadatel není vlastník)"}}}},"/api/owners/{ownerId}/properties/{propertyId}/occupancy-pricing":{"post":{"operationId":"set_occupancy_pricing","summary":"Nastav/uprav cenu dle obsazenosti (upsert)","description":"Nastaví occupancy profil nemovitosti (max jeden per property → upsert). Základní cena pokrývá `base_occupancy` osob; host nad prahem platí `extra_person_fee_czk` za osobu a noc. Propíše se položkově do get_quote breakdownu (jen active=1; osoby do prahu = 0 navíc). Nový profil → 201, úprava → 200 (a reaktivuje). `base_occupancy<1` / záporný fee / neznámé pole → 400. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["occupancy"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"base_occupancy":{"type":"integer","minimum":1,"maximum":100,"description":"Počet osob, které pokrývá základní cena (prvních N osob = 0 navíc)"},"extra_person_fee_czk":{"type":"integer","minimum":0,"maximum":1000000,"description":"Příplatek za osobu NAD práh, za osobu a noc (Kč)"}},"required":["base_occupancy","extra_person_fee_czk"],"additionalProperties":false}}}},"responses":{"200":{"description":"Upraveno","content":{"application/json":{"schema":{"type":"object","description":"Cena dle obsazenosti nemovitosti (max jeden profil per property). Základní cena pokrývá `base_occupancy` osob; host nad prahem platí `extra_person_fee_czk` za osobu a noc. ≠ fixní příplatek per=person.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID nemovitosti (prop_xxx)"},"base_occupancy":{"type":"integer","description":"Počet osob v základní ceně (prvních N osob = 0 navíc)"},"extra_person_fee_czk":{"type":"integer","description":"Příplatek za osobu NAD práh, za osobu a noc (Kč)"},"active":{"type":"boolean","description":"Deaktivovaný (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["property_id","base_occupancy","extra_person_fee_czk","active"]}}}},"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Cena dle obsazenosti nemovitosti (max jeden profil per property). Základní cena pokrývá `base_occupancy` osob; host nad prahem platí `extra_person_fee_czk` za osobu a noc. ≠ fixní příplatek per=person.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID nemovitosti (prop_xxx)"},"base_occupancy":{"type":"integer","description":"Počet osob v základní ceně (prvních N osob = 0 navíc)"},"extra_person_fee_czk":{"type":"integer","description":"Příplatek za osobu NAD práh, za osobu a noc (Kč)"},"active":{"type":"boolean","description":"Deaktivovaný (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["property_id","base_occupancy","extra_person_fee_czk","active"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"get_occupancy_pricing","summary":"Aktuální cena dle obsazenosti","description":"Vrátí occupancy profil nemovitosti (vč. deaktivovaného) nebo `{ occupancy_pricing: null }`, pokud není nakonfigurovaný. Není MCP tool.","tags":["occupancy"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"property_id":{"type":"string"},"occupancy_pricing":{"type":"object","description":"Cena dle obsazenosti nemovitosti (max jeden profil per property). Základní cena pokrývá `base_occupancy` osob; host nad prahem platí `extra_person_fee_czk` za osobu a noc. ≠ fixní příplatek per=person.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID nemovitosti (prop_xxx)"},"base_occupancy":{"type":"integer","description":"Počet osob v základní ceně (prvních N osob = 0 navíc)"},"extra_person_fee_czk":{"type":"integer","description":"Příplatek za osobu NAD práh, za osobu a noc (Kč)"},"active":{"type":"boolean","description":"Deaktivovaný (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["property_id","base_occupancy","extra_person_fee_czk","active"],"nullable":true}},"required":["property_id","occupancy_pricing"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/occupancy-pricing/deactivate":{"post":{"operationId":"deactivate_occupancy_pricing","summary":"Deaktivuj cenu dle obsazenosti (active=0)","description":"Deaktivuje occupancy profil (active=0) — přestane se propisovat do NOVÝCH quote (už zmrazené se nemění). NENÍ hard delete. Idempotentní pro nakonfigurovaný profil. Nemovitost bez profilu → 404 OCCUPANCY_NOT_FOUND. Není MCP tool.","tags":["occupancy"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Cena dle obsazenosti nemovitosti (max jeden profil per property). Základní cena pokrývá `base_occupancy` osob; host nad prahem platí `extra_person_fee_czk` za osobu a noc. ≠ fixní příplatek per=person.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID nemovitosti (prop_xxx)"},"base_occupancy":{"type":"integer","description":"Počet osob v základní ceně (prvních N osob = 0 navíc)"},"extra_person_fee_czk":{"type":"integer","description":"Příplatek za osobu NAD práh, za osobu a noc (Kč)"},"active":{"type":"boolean","description":"Deaktivovaný (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["property_id","base_occupancy","extra_person_fee_czk","active"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Profil/nemovitost/vlastník neexistuje (OCCUPANCY_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/tourist-tax":{"put":{"operationId":"set_tourist_tax","summary":"Nastav/uprav poplatek z pobytu (upsert)","description":"Nastaví sazbu poplatku z pobytu (místní daň) nemovitosti dle vyhlášky obce (max jeden config per property → upsert). Propíše se do get_quote breakdownu jako `taxable_persons × noci × sazba` (osoby mladší `child_exempt_under` osvobozeny; `child_exempt_under` default 18). Nový config → 201, úprava → 200. Nulová/záporná/nad-sanity sazba, neznámé/chybějící pole → 400. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["tourist-tax"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"municipality":{"type":"string","minLength":1,"maxLength":120,"description":"Obec, jejíž vyhláška poplatek stanoví (zobrazí se v rozpadu ceny)"},"rate_czk_per_person_night":{"type":"integer","exclusiveMinimum":true,"minimum":0,"maximum":200,"description":"Sazba poplatku za osobu a noc (Kč), dle vyhlášky obce; horní mez = anti-typo guard, ne zákonný strop"},"child_exempt_under":{"type":"integer","minimum":0,"maximum":26,"default":18,"description":"Věková hranice osvobození dětí (osvobozeny osoby MLADŠÍ než tato hodnota); default 18"}},"required":["municipality","rate_czk_per_person_night"],"additionalProperties":false}}}},"responses":{"200":{"description":"Upraveno","content":{"application/json":{"schema":{"type":"object","description":"Poplatek z pobytu (místní daň) nemovitosti — max jeden config per property. Sazba za osobu a noc dle vyhlášky obce; osoby mladší `child_exempt_under` osvobozeny. Propíše se do get_quote breakdownu (řádek tourist_tax) jako `taxable_persons × noci × sazba`.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID nemovitosti (prop_xxx)"},"municipality":{"type":"string","description":"Obec, jejíž vyhláška poplatek stanoví"},"rate_czk_per_person_night":{"type":"integer","description":"Sazba poplatku za osobu a noc (Kč)"},"child_exempt_under":{"type":"integer","description":"Věková hranice osvobození dětí (osvobozeny osoby MLADŠÍ než tato hodnota)"}},"required":["property_id","municipality","rate_czk_per_person_night","child_exempt_under"]}}}},"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Poplatek z pobytu (místní daň) nemovitosti — max jeden config per property. Sazba za osobu a noc dle vyhlášky obce; osoby mladší `child_exempt_under` osvobozeny. Propíše se do get_quote breakdownu (řádek tourist_tax) jako `taxable_persons × noci × sazba`.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID nemovitosti (prop_xxx)"},"municipality":{"type":"string","description":"Obec, jejíž vyhláška poplatek stanoví"},"rate_czk_per_person_night":{"type":"integer","description":"Sazba poplatku za osobu a noc (Kč)"},"child_exempt_under":{"type":"integer","description":"Věková hranice osvobození dětí (osvobozeny osoby MLADŠÍ než tato hodnota)"}},"required":["property_id","municipality","rate_czk_per_person_night","child_exempt_under"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"get_tourist_tax","summary":"Aktuální poplatek z pobytu","description":"Vrátí config poplatku z pobytu nemovitosti. Nenastaveno → 404 TOURIST_TAX_NOT_SET (deterministicky, ne prázdný objekt). Není MCP tool.","tags":["tourist-tax"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Poplatek z pobytu (místní daň) nemovitosti — max jeden config per property. Sazba za osobu a noc dle vyhlášky obce; osoby mladší `child_exempt_under` osvobozeny. Propíše se do get_quote breakdownu (řádek tourist_tax) jako `taxable_persons × noci × sazba`.","properties":{"property_id":{"type":"string","description":"Stabilní veřejné ID nemovitosti (prop_xxx)"},"municipality":{"type":"string","description":"Obec, jejíž vyhláška poplatek stanoví"},"rate_czk_per_person_night":{"type":"integer","description":"Sazba poplatku za osobu a noc (Kč)"},"child_exempt_under":{"type":"integer","description":"Věková hranice osvobození dětí (osvobozeny osoby MLADŠÍ než tato hodnota)"}},"required":["property_id","municipality","rate_czk_per_person_night","child_exempt_under"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Poplatek nenastaven / nemovitost / vlastník neexistuje (TOURIST_TAX_NOT_SET / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/tourist-tax-report":{"get":{"operationId":"get_tourist_tax_report","summary":"Kvartální výkaz poplatku z pobytu (podklad pro odvod obci)","description":"Vrátí položkový výkaz poplatku z pobytu za daný kvartál: reálné CONFIRMED/COMPLETED rezervace té nemovitosti (zařazené dle data příjezdu) × zpoplatnitelné osoby z evidence check-inu (booking_guest: věk k příjezdu vs. child_exempt_under) × sazba obce → dílčí částky + celkový součet k odvodu. Součet je cross-checkován proti tourist_tax z quote breakdownů (pole `consistent`/`matches_quote`, §14). `?format=csv` vrátí týž číselný obsah jako CSV. Prázdný kvartál → 0 položek, součet 0 (ne chyba). Poplatek nenastaven → 404 TOURIST_TAX_NOT_SET. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["tourist-tax"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"year","in":"query","required":true,"schema":{"type":"integer"},"description":"Rok výkazu (YYYY)"},{"name":"quarter","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":4},"description":"Kvartál 1..4 (dle data příjezdu)"},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"]},"description":"csv = stejná čísla jako JSON, jako příloha"}],"responses":{"200":{"description":"OK (JSON nebo text/csv dle ?format)","content":{"application/json":{"schema":{"type":"object","description":"Kvartální výkaz poplatku z pobytu pro odvod obci (I9b). Agregace nad REÁLNÝMI CONFIRMED/COMPLETED rezervacemi (dle data příjezdu) + booking_guest (věk → výjimka dětí). `total_czk` = celkem k odvodu z evidence; `quote_total_czk` + `consistent` = invariant cross-check proti quote (§14).","properties":{"property_id":{"type":"string"},"municipality":{"type":"string"},"year":{"type":"integer"},"quarter":{"type":"integer"},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"label":{"type":"string"}}},"rate_czk_per_person_night":{"type":"integer"},"child_exempt_under":{"type":"integer"},"currency":{"type":"string"},"bookings":{"type":"integer","description":"Počet rezervací ve výkazu"},"bookings_without_checkin":{"type":"integer","description":"Z nich bez vyplněného check-inu (přispívají 0 — doplnit před odvodem)"},"total_taxable_persons":{"type":"integer"},"total_czk":{"type":"integer","description":"CELKEM k odvodu obci za kvartál (z reálné evidence booking_guest)"},"quote_total_czk":{"type":"integer","description":"Součet quote tourist_tax (cross-check)"},"consistent":{"type":"boolean","description":"total_czk === quote_total_czk (invariant §14)"},"items":{"type":"array","items":{"type":"object","description":"Jedna rezervace ve výkazu — reálný řádek z booking + booking_guest + quote (ne fixture).","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"status":{"type":"string","description":"CONFIRMED | COMPLETED"},"date_from":{"type":"string","description":"Datum příjezdu (řídí zařazení do kvartálu)"},"date_to":{"type":"string","description":"Datum odjezdu (exkluzivně)"},"nights":{"type":"integer"},"guests_registered":{"type":"integer","description":"Počet osob v evidenci (booking_guest); 0 = check-in nevyplněn"},"taxable_persons":{"type":"integer","description":"Osoby zpoplatněné (věk ≥ child_exempt_under k příjezdu)"},"exempt_persons":{"type":"integer","description":"Osoby osvobozené (děti pod prahem)"},"rate_czk_per_person_night":{"type":"integer"},"tax_czk":{"type":"integer","description":"Dílčí částka k odvodu = osoby × noci × sazba (sdílené jádro s quote)"},"quote_tax_czk":{"type":"integer","description":"tourist_tax té rezervace z quote breakdownu — cross-check (I9a)"},"matches_quote":{"type":"boolean","description":"tax_czk === quote_tax_czk (false = reálná divergence vstupů)"},"checkin_complete":{"type":"boolean","description":"guests_registered > 0 (evidence hostů vyplněna)"}}}}},"required":["property_id","year","quarter","total_czk","consistent","items"]}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Neplatné year/quarter (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Poplatek nenastaven / nemovitost / vlastník neexistuje (TOURIST_TAX_NOT_SET / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/guest-book":{"get":{"operationId":"get_guest_book","summary":"Evidenční kniha ubytovaných § 3g (owner export pro kontrolu z obce/policie)","description":"Vrátí evidenční knihu ubytovaných dle § 3g zák. 565/1990 Sb. za okno [from, to): reálné evidované osoby z check-inu (booking_guest) u CONFIRMED/COMPLETED rezervací té nemovitosti, jejichž pobyt do okna zasahuje (půlotevřený překryv `date_from < to AND date_to > from`; `to` je výlučná horní mez). Řádek = jedna osoba (§ 3g pole: jméno, příjmení, datum narození, adresa; u cizince navíc citizenship/document_number/visa_number, jinak null). Rezervace bez check-inu se NEfabrikují jako prázdné osoby — jen se přiznají v `bookings_without_checkin` (§14). `?format=csv` vrátí týž obsah jako CSV. Prázdné okno → 0 osob (ne chyba). from>=to / nevalidní datum → 400. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["checkin"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"Počátek okna (inkluzivně, YYYY-MM-DD)"},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"Konec okna (VÝLUČNĚ — den odjezdu, YYYY-MM-DD)"},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"]},"description":"csv = táž pole jako JSON, jako příloha"}],"responses":{"200":{"description":"OK (JSON nebo text/csv dle ?format)","content":{"application/json":{"schema":{"type":"object","description":"Evidenční kniha ubytovaných § 3g zák. 565/1990 Sb. (I8b) — per nemovitost, za okno [from, to). Řádek = jedna reálně evidovaná osoba z booking_guest (CONFIRMED/COMPLETED pobyty, jejichž stay zasahuje do okna). Rezervace bez check-inu se NEfabrikují jako prázdné osoby — jen se přiznají v `bookings_without_checkin` (§14).","properties":{"property_id":{"type":"string","description":"public_id nemovitosti (prop_xxx)"},"property":{"type":"string","description":"Název nemovitosti (kniha je per nemovitost)"},"range":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date","description":"Výlučná horní mez (den odjezdu)"}},"required":["from","to"]},"persons":{"type":"integer","description":"Počet evidovaných osob v knize"},"bookings_without_checkin":{"type":"integer","description":"CONFIRMED/COMPLETED rezervace v okně BEZ check-inu (přiznaná díra, ne fabrikace)"},"guests":{"type":"array","items":{"type":"object","description":"Jedna reálně evidovaná osoba v evidenční knize § 3g (z booking_guest). Cizinecká pole (citizenship/document_number/visa_number) jsou u CZ hosta null — nikdy dopočítaná hodnota.","properties":{"booking_id":{"type":"string","description":"public_id rezervace pobytu (bkg_xxx)"},"date_from":{"type":"string","format":"date","description":"Datum příjezdu (nástup pobytu)"},"date_to":{"type":"string","format":"date","description":"Datum odjezdu (exkluzivně)"},"last_name":{"type":"string","description":"Příjmení (§ 3g)"},"first_name":{"type":"string","description":"Jméno (§ 3g)"},"birth_date":{"type":"string","format":"date","description":"Datum narození (§ 3g)"},"address":{"type":"string","description":"Adresa trvalého pobytu / u cizince adresa v zahraničí (§ 3g)"},"is_foreigner":{"type":"boolean","description":"true = cizinec (má vyplněná cizinecká pole)"},"is_child":{"type":"boolean","description":"Uložené z check-inu: osoba <18 k datu příjezdu"},"citizenship":{"type":"string","nullable":true,"description":"Státní příslušnost — jen cizinec, jinak null (§ 3g)"},"document_number":{"type":"string","nullable":true,"description":"Číslo cestovního dokladu — jen cizinec, jinak null (§ 3g)"},"visa_number":{"type":"string","nullable":true,"description":"Číslo víza — jen je-li vyplněno, jinak null (§ 3g)"},"registered_at":{"type":"string","format":"date-time","description":"Kdy host osobu vložil do evidence (audit)"}},"required":["booking_id","date_from","date_to","last_name","first_name","birth_date","address","is_foreigner","is_child"]}}},"required":["property_id","property","range","persons","bookings_without_checkin","guests"]}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Neplatné from/to (VALIDATION_ERROR / INVALID_DATES)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost / vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/ubyport":{"get":{"operationId":"owner_ubyport_export","summary":"Podklad pro Ubyport u cizinců (owner export pro ruční oznámení cizinecké policii)","description":"Vrátí podklad pro Ubyport (oznámení o ubytování cizince, § 99–102 zák. 326/1999 Sb.) za okno [from, to): JEN cizinci (is_foreigner=1) z reálného check-inu (booking_guest) u CONFIRMED/COMPLETED rezervací té nemovitosti, jejichž pobyt do okna zasahuje (půlotevřený překryv `date_from < to AND date_to > from`; `to` je výlučná horní mez). Řádek = jeden cizinec (jméno, příjmení, datum narození, citizenship, document_number, visa_number — bezvízový cizinec null, adresa v zahraničí, doba pobytu). Adresa ubytování je v hlavičce (property_address). CZ hosté a děti-občané se do podkladu nedostanou (nejsou předmětem cizineckého hlášení). Rezervace bez check-inu se NEfabrikují — jen se přiznají v `bookings_without_checkin` (mohly nést cizince; §14). `?format=csv` vrátí týž obsah jako CSV. Prázdné okno / žádný cizinec → 0 osob (ne chyba). from>=to / nevalidní datum → 400. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool (regulovaný owner READ; přímá Ubyport integrace = fáze 2).","tags":["checkin"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"Počátek okna (inkluzivně, YYYY-MM-DD)"},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"Konec okna (VÝLUČNĚ — den odjezdu, YYYY-MM-DD)"},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"]},"description":"csv = táž pole jako JSON, jako příloha"}],"responses":{"200":{"description":"OK (JSON nebo text/csv dle ?format)","content":{"application/json":{"schema":{"type":"object","description":"Podklad pro Ubyport (I8c) — oznámení o ubytování cizince (§ 99–102 zák. 326/1999 Sb.), per nemovitost, za okno [from, to). Zúžení evidenční knihy § 3g na JEN cizince (is_foreigner=1) z reálných booking_guest řádků CONFIRMED/COMPLETED pobytů, jejichž stay zasahuje do okna. Rezervace bez check-inu se NEfabrikují jako osoby — jen se přiznají v `bookings_without_checkin` (mohly nést cizince; §14). Vlastník podklad ručně oznámí cizinecké policii; přímá Ubyport integrace = fáze 2.","properties":{"property_id":{"type":"string","description":"public_id nemovitosti (prop_xxx)"},"property":{"type":"string","description":"Název nemovitosti"},"property_address":{"type":"string","nullable":true,"description":"Adresa ubytování (z property.address; null = nevyplněna, ne fabrikace)"},"region":{"type":"string","description":"Kraj/oblast nemovitosti (kontext adresy ubytování)"},"range":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date","description":"Výlučná horní mez (den odjezdu)"}},"required":["from","to"]},"foreigners":{"type":"integer","description":"Počet cizinců v podkladu"},"bookings_without_checkin":{"type":"integer","description":"CONFIRMED/COMPLETED rezervace v okně BEZ check-inu (přiznaná díra — mohla nést cizince)"},"guests":{"type":"array","items":{"type":"object","description":"Jeden reálně evidovaný cizinec (is_foreigner=1 z booking_guest) pro podklad Ubyport. visa_number u bezvízového cizince je null — nikdy fabrikovaná hodnota.","properties":{"booking_id":{"type":"string","description":"public_id rezervace pobytu (bkg_xxx)"},"date_from":{"type":"string","format":"date","description":"Datum příjezdu (nástup pobytu)"},"date_to":{"type":"string","format":"date","description":"Datum odjezdu (exkluzivně)"},"last_name":{"type":"string","description":"Příjmení cizince"},"first_name":{"type":"string","description":"Jméno cizince"},"birth_date":{"type":"string","format":"date","description":"Datum narození"},"citizenship":{"type":"string","nullable":true,"description":"Státní občanství (u cizince vyplněno)"},"document_number":{"type":"string","nullable":true,"description":"Číslo cestovního dokladu (u cizince vyplněno)"},"visa_number":{"type":"string","nullable":true,"description":"Číslo víza — bezvízový cizinec → null (ne fabrikace)"},"residence_address":{"type":"string","description":"Adresa cizince v zahraničí / trvalého pobytu (booking_guest.address)"},"registered_at":{"type":"string","format":"date-time","description":"Kdy host osobu vložil do evidence (audit)"}},"required":["booking_id","date_from","date_to","last_name","first_name","birth_date","residence_address","registered_at"]}}},"required":["property_id","property","property_address","region","range","foreigners","bookings_without_checkin","guests"]}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"Neplatné from/to (VALIDATION_ERROR / INVALID_DATES)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost / vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/billing/usage":{"get":{"operationId":"get_billing_usage","summary":"Hodnotové počítadlo monetizace vlastníka (usage read-model, pilot bez fakturace)","description":"Vrátí hodnotové počítadlo vlastníka za daný měsíc: per nemovitost reálný počet CONFIRMED/COMPLETED rezervací (zařazených dle data potvrzení `confirmed_at`) × `fee_per_booking_czk` (39 Kč) → gross, capnutý per nemovitost na `monthly_cap_czk` (299 Kč) — plus agregovaný součet přes všechny nemovitosti vlastníka. `billable=false` (PILOT — grandfather; fakturace vypnutá, jen počítáme hodnotu). HOLD/PENDING_OWNER/CANCELLED_* se NEpočítají. Owner bez rezervací v měsíci → nulové položky (ne chyba). Nevalidní month (formát/měsíc mimo 01–12/rok mimo rozsah) → 400 VALIDATION_ERROR. Neexistující vlastník → 404 OWNER_NOT_FOUND. Není MCP tool (agenti neplatí).","tags":["billing"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"month","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"description":"Měsíc počítadla YYYY-MM (dle data potvrzení rezervace)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Hodnotové počítadlo monetizace vlastníka za měsíc (I10a). Agregace nad REÁLNÝMI CONFIRMED/COMPLETED rezervacemi (dle data potvrzení `confirmed_at`) přes všechny nemovitosti vlastníka. `billable=false` = PILOT (grandfather; fakturace vypnutá) — jen počítáme hodnotu. Cap `monthly_cap_czk` je PER NEMOVITOST; owner-agregát `total_capped_value_czk` je součet už capnutých per-property hodnot.","properties":{"owner_id":{"type":"string"},"month":{"type":"string","description":"YYYY-MM"},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}}},"currency":{"type":"string"},"fee_per_booking_czk":{"type":"integer","description":"Poplatek za potvrzenou rezervaci (zdroj obchodni-model.md)"},"monthly_cap_czk":{"type":"integer","description":"Měsíční strop per nemovitost"},"billable":{"type":"boolean","description":"false — pilot (fakturace vypnutá); počítadlo, ne faktura"},"properties_count":{"type":"integer"},"total_confirmed_bookings":{"type":"integer"},"total_gross_value_czk":{"type":"integer","description":"Σ gross přes nemovitosti (před capem)"},"total_capped_value_czk":{"type":"integer","description":"Σ capped PER NEMOVITOST (hodnota, kdyby se v pilotu fakturovalo)"},"items":{"type":"array","items":{"type":"object","description":"Jedna nemovitost v počítadle — reálný COUNT potvrzených rezervací v měsíci (ne fixture). Cap je per nemovitost.","properties":{"property_id":{"type":"string","description":"public_id nemovitosti (prop_xxx)"},"name":{"type":"string"},"confirmed_bookings":{"type":"integer","description":"Reálný počet CONFIRMED/COMPLETED rezervací v měsíci (dle confirmed_at)"},"gross_value_czk":{"type":"integer","description":"confirmed_bookings × fee_per_booking_czk (před capem)"},"capped_value_czk":{"type":"integer","description":"min(gross, monthly_cap_czk) — per-nemovitost strop"},"capped":{"type":"boolean","description":"gross > monthly_cap_czk (cap reálně bind — od 8. rezervace)"}}}}},"required":["owner_id","month","billable","total_confirmed_bookings","total_capped_value_czk","items"]}}}},"400":{"description":"Neplatné month (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Vlastník neexistuje (OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/los-discounts":{"post":{"operationId":"create_los_discount","summary":"Přidej slevu za délku pobytu","description":"Přidá slevu za délku pobytu (práh `min_nights` ≥ 2 → sleva `discount_percent` %). Víc prahů per property (7+ −10 %, 28+ −20 %). Sleva se počítá JEN z ceny za ubytování (ne úklid/příplatky/occupancy/poplatek z pobytu) a propíše se jako ZÁPORNÁ položka do get_quote breakdownu (jen active=1); při víc splněných prazích platí nejvyšší (právě jeden, bez kumulace). `min_nights<2` / `discount_percent` mimo 1–100 / neznámé pole → 400. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Není MCP tool.","tags":["los-discounts"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"min_nights":{"type":"integer","minimum":2,"maximum":365,"description":"Práh délky pobytu — od kolika nocí sleva platí (≥2, inkluzivně)"},"discount_percent":{"type":"integer","minimum":1,"maximum":100,"description":"Procentní sleva z ceny za ubytování (1–100 %, celé procento)"}},"required":["min_nights","discount_percent"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Sleva za délku pobytu (1:N per property). Práh `min_nights` → sleva `discount_percent` %. Počítá se JEN z ceny za ubytování; aplikuje se právě jedno pravidlo (nejvyšší splněný práh).","properties":{"los_discount_id":{"type":"string","description":"Stabilní veřejné ID (los_xxx)"},"min_nights":{"type":"integer","description":"Práh délky pobytu — od kolika nocí sleva platí (≥2, inkluzivně)"},"discount_percent":{"type":"integer","description":"Procentní sleva z ceny za ubytování (1–100 %)"},"active":{"type":"boolean","description":"Deaktivovaná (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"}},"required":["los_discount_id","min_nights","discount_percent","active"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"list_los_discounts","summary":"Seznam slev za délku pobytu","description":"Vrátí slevy za délku pobytu nemovitosti (vč. deaktivovaných), nejvyšší práh první. Není MCP tool.","tags":["los-discounts"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"property_id":{"type":"string"},"count":{"type":"integer"},"los_discounts":{"type":"array","items":{"type":"object","description":"Sleva za délku pobytu (1:N per property). Práh `min_nights` → sleva `discount_percent` %. Počítá se JEN z ceny za ubytování; aplikuje se právě jedno pravidlo (nejvyšší splněný práh).","properties":{"los_discount_id":{"type":"string","description":"Stabilní veřejné ID (los_xxx)"},"min_nights":{"type":"integer","description":"Práh délky pobytu — od kolika nocí sleva platí (≥2, inkluzivně)"},"discount_percent":{"type":"integer","description":"Procentní sleva z ceny za ubytování (1–100 %)"},"active":{"type":"boolean","description":"Deaktivovaná (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"}},"required":["los_discount_id","min_nights","discount_percent","active"]}}},"required":["property_id","count","los_discounts"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/los-discounts/{losId}/deactivate":{"post":{"operationId":"deactivate_los_discount","summary":"Deaktivuj slevu za délku pobytu (active=0)","description":"Deaktivuje slevu (active=0) — přestane se propisovat do NOVÝCH quote (už zmrazené quoty se nemění). NENÍ hard delete. Idempotentní. Cizí/neexistující sleva → 404 LOS_DISCOUNT_NOT_FOUND. Není MCP tool.","tags":["los-discounts"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"losId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id slevy (los_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Sleva za délku pobytu (1:N per property). Práh `min_nights` → sleva `discount_percent` %. Počítá se JEN z ceny za ubytování; aplikuje se právě jedno pravidlo (nejvyšší splněný práh).","properties":{"los_discount_id":{"type":"string","description":"Stabilní veřejné ID (los_xxx)"},"min_nights":{"type":"integer","description":"Práh délky pobytu — od kolika nocí sleva platí (≥2, inkluzivně)"},"discount_percent":{"type":"integer","description":"Procentní sleva z ceny za ubytování (1–100 %)"},"active":{"type":"boolean","description":"Deaktivovaná (false) se do nových quote nepropíše"},"created_at":{"type":"string","format":"date-time"}},"required":["los_discount_id","min_nights","discount_percent","active"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Sleva/nemovitost/vlastník neexistuje (LOS_DISCOUNT_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/calendar-blocks":{"post":{"operationId":"create_calendar_block","summary":"Vytvoř ruční kalendářní blokaci","description":"Zablokuje interval [date_from, date_to) vlastníkem (server nastaví source=manual). Blokace se okamžitě promítne do dostupnosti — get_quote/create_hold na překrývající termín vrátí 409 DATES_UNAVAILABLE. date_from ≥ date_to → 400 VALIDATION_ERROR. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Volitelné tělo `unit` (public_id/slug jednotky, MU-9a) → blok jen té jednotky (jen u nemovitosti v režimu „celek + jednotky\"); vynecháno = blok celku. Neexistující/nepublikovaná/nebookovatelná jednotka nebo objekt bez samostatných jednotek → 404 UNIT_NOT_FOUND (NIKDY tichý blok celku). Objekt rezervovatelný jen po jednotkách bez `unit` → 422 UNIT_REQUIRED. Není MCP tool.","tags":["calendar"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date_from":{"type":"string","description":"První blokovaná noc (YYYY-MM-DD, inkluzivně)"},"date_to":{"type":"string","description":"Den odjezdu (YYYY-MM-DD, exkluzivně) = [from, to)"},"unit":{"type":"string","minLength":1,"description":"Volitelná jednotka (public_id NEBO slug) — blok jen pro tuto jednotku (multi-unit, MU-9a). Vynecháno = blok celé nemovitosti (celek). Přijímá se jen u nemovitosti v režimu „celek + jednotky\"."},"note":{"type":"string","maxLength":190,"description":"Volitelná poznámka (údržba, obsazeno majitelem…)"}},"required":["date_from","date_to"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Kalendářní blokace nemovitosti (bez interního id). Interval [date_from, date_to) — date_to je den odjezdu. `source` určuje, zda ji lze ručně smazat (jen manual).","properties":{"block_id":{"type":"string","description":"Stabilní veřejné ID (blk_xxx)"},"date_from":{"type":"string","format":"date","description":"První blokovaná noc (inkluzivně)"},"date_to":{"type":"string","format":"date","description":"Den odjezdu (exkluzivně) = [from, to)"},"source":{"type":"string","enum":["manual","ical","booking"],"description":"manual=ruční vlastníkem (lze smazat), ical=externí kalendář, booking=z rezervace"},"note":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"unit":{"type":"object","description":"Jednotka, které se blok týká (multi-unit, MU-9a). PŘÍTOMNO jen u blokace konkrétní jednotky; u blokace celé nemovitosti (celku) se klíč VYNECHÁVÁ.","properties":{"unit_id":{"type":"string","description":"Stabilní veřejné ID jednotky (unit_xxx)"},"name":{"type":"string","description":"Název jednotky"}},"required":["unit_id","name"]}},"required":["block_id","date_from","date_to","source"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník/jednotka neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND / UNIT_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Objekt se rezervuje/blokuje jen po jednotkách — chybí `unit` (UNIT_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"list_calendar_blocks","summary":"Seznam kalendářních blokací nemovitosti","description":"Vrátí všechny blokace nemovitosti (manual i ical/booking) chronologicky, se `source` (aby bylo poznat, které lze ručně smazat). Není MCP tool.","tags":["calendar"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"property_id":{"type":"string"},"count":{"type":"integer"},"blocks":{"type":"array","items":{"type":"object","description":"Kalendářní blokace nemovitosti (bez interního id). Interval [date_from, date_to) — date_to je den odjezdu. `source` určuje, zda ji lze ručně smazat (jen manual).","properties":{"block_id":{"type":"string","description":"Stabilní veřejné ID (blk_xxx)"},"date_from":{"type":"string","format":"date","description":"První blokovaná noc (inkluzivně)"},"date_to":{"type":"string","format":"date","description":"Den odjezdu (exkluzivně) = [from, to)"},"source":{"type":"string","enum":["manual","ical","booking"],"description":"manual=ruční vlastníkem (lze smazat), ical=externí kalendář, booking=z rezervace"},"note":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"unit":{"type":"object","description":"Jednotka, které se blok týká (multi-unit, MU-9a). PŘÍTOMNO jen u blokace konkrétní jednotky; u blokace celé nemovitosti (celku) se klíč VYNECHÁVÁ.","properties":{"unit_id":{"type":"string","description":"Stabilní veřejné ID jednotky (unit_xxx)"},"name":{"type":"string","description":"Název jednotky"}},"required":["unit_id","name"]}},"required":["block_id","date_from","date_to","source"]}}},"required":["property_id","count","blocks"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/calendar-blocks/{blockId}":{"delete":{"operationId":"remove_calendar_block","summary":"Odeber ruční kalendářní blokaci","description":"Smaže JEN ruční blokaci (source=manual) — termín se tím znovu uvolní pro dostupnost. Blokaci z externího zdroje (ical/booking) nelze smazat → 409 BLOCK_NOT_MANUAL (zůstane). Neexistující/cizí blokace → 404 BLOCK_NOT_FOUND. Není MCP tool.","tags":["calendar"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"blockId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id blokace (blk_xxx)"}],"responses":{"200":{"description":"Odebráno","content":{"application/json":{"schema":{"type":"object","properties":{"block_id":{"type":"string"},"removed":{"type":"boolean"},"source":{"type":"string","enum":["manual"]},"date_from":{"type":"string","format":"date"},"date_to":{"type":"string","format":"date"}},"required":["block_id","removed"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Blokace/nemovitost/vlastník neexistuje (BLOCK_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"409":{"description":"Blokace není manuální — nelze ručně smazat (BLOCK_NOT_MANUAL)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/ical-sources":{"post":{"operationId":"create_ical_source","summary":"Zaregistruj externí iCal feed","description":"Zaregistruje iCal feed URL (Booking/Airbnb/Google) pod nemovitostí (1:N). Neimportuje hned — import spustí zvlášť POST …/sync. Neplatná URL / neznámé pole → 400 VALIDATION_ERROR. Cizí/neexistující nemovitost → 404 PROPERTY_NOT_FOUND. Volitelné tělo `unit` (public_id/slug jednotky, MU-10a) → feed importuje bloky jen té jednotky (jen u nemovitosti v režimu „celek + jednotky\"); vynecháno = feed celku. Neexistující/nepublikovaná/nebookovatelná jednotka nebo objekt bez samostatných jednotek → 404 UNIT_NOT_FOUND (NIKDY tichý feed celku, jinak by „Pokoj 1\" shodil celý objekt). Objekt rezervovatelný jen po jednotkách bez `unit` → 422 UNIT_REQUIRED. Není MCP tool.","tags":["ical"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"feed_url":{"type":"string","minLength":1,"maxLength":1024,"description":"URL iCal feedu (Booking/Airbnb/Google export)"},"label":{"type":"string","minLength":1,"maxLength":120,"description":"Volitelný štítek zdroje (Booking/Airbnb…)"},"unit":{"type":"string","minLength":1,"description":"Volitelná jednotka (public_id NEBO slug) — feed importuje bloky jen pro tuto jednotku (multi-unit, MU-10a). Vynecháno = feed celé nemovitosti (celek). Přijímá se jen u nemovitosti v režimu „celek + jednotky\"."}},"required":["feed_url"],"additionalProperties":false}}}},"responses":{"201":{"description":"Zaregistrováno","content":{"application/json":{"schema":{"type":"object","description":"Zaregistrovaný externí iCal feed nemovitosti (1:N per property). Sync stáhne feed a upsertne VEVENTy jako ical bloky → ovlivní dostupnost. `last_status` = výsledek posledního pokusu o sync.","properties":{"ical_source_id":{"type":"string","description":"Stabilní veřejné ID (ics_xxx)"},"feed_url":{"type":"string","description":"URL iCal feedu (Booking/Airbnb/Google export)"},"label":{"type":"string","nullable":true,"description":"Volitelný štítek zdroje (Booking/Airbnb…)"},"active":{"type":"boolean","description":"Deaktivovaný (false): jeho ical bloky byly odstraněny, dál neblokuje"},"last_synced_at":{"type":"string","format":"date-time","nullable":true,"description":"Čas posledního ÚSPĚŠNÉHO syncu (null = dosud nesyncováno)"},"last_status":{"type":"string","nullable":true,"description":"Výsledek posledního pokusu: ok / ICAL_FETCH_FAILED / ICAL_PARSE_FAILED"},"created_at":{"type":"string","format":"date-time"},"unit":{"type":"object","description":"Jednotka, které se feed týká (multi-unit, MU-10a). PŘÍTOMNO jen u feedu konkrétní jednotky (jeho importované bloky shodí JEN tu jednotku); u feedu celé nemovitosti (celku) se klíč VYNECHÁVÁ.","properties":{"unit_id":{"type":"string","description":"Stabilní veřejné ID jednotky (unit_xxx)"},"name":{"type":"string","description":"Název jednotky"}},"required":["unit_id","name"]}},"required":["ical_source_id","feed_url","active"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník/jednotka neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND / UNIT_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Objekt se rezervuje/blokuje jen po jednotkách — chybí `unit` (UNIT_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"list_ical_sources","summary":"Seznam zaregistrovaných iCal feedů","description":"Vrátí feedy nemovitosti (vč. deaktivovaných) se stavem posledního syncu (last_synced_at / last_status). Není MCP tool.","tags":["ical"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"property_id":{"type":"string"},"count":{"type":"integer"},"ical_sources":{"type":"array","items":{"type":"object","description":"Zaregistrovaný externí iCal feed nemovitosti (1:N per property). Sync stáhne feed a upsertne VEVENTy jako ical bloky → ovlivní dostupnost. `last_status` = výsledek posledního pokusu o sync.","properties":{"ical_source_id":{"type":"string","description":"Stabilní veřejné ID (ics_xxx)"},"feed_url":{"type":"string","description":"URL iCal feedu (Booking/Airbnb/Google export)"},"label":{"type":"string","nullable":true,"description":"Volitelný štítek zdroje (Booking/Airbnb…)"},"active":{"type":"boolean","description":"Deaktivovaný (false): jeho ical bloky byly odstraněny, dál neblokuje"},"last_synced_at":{"type":"string","format":"date-time","nullable":true,"description":"Čas posledního ÚSPĚŠNÉHO syncu (null = dosud nesyncováno)"},"last_status":{"type":"string","nullable":true,"description":"Výsledek posledního pokusu: ok / ICAL_FETCH_FAILED / ICAL_PARSE_FAILED"},"created_at":{"type":"string","format":"date-time"},"unit":{"type":"object","description":"Jednotka, které se feed týká (multi-unit, MU-10a). PŘÍTOMNO jen u feedu konkrétní jednotky (jeho importované bloky shodí JEN tu jednotku); u feedu celé nemovitosti (celku) se klíč VYNECHÁVÁ.","properties":{"unit_id":{"type":"string","description":"Stabilní veřejné ID jednotky (unit_xxx)"},"name":{"type":"string","description":"Název jednotky"}},"required":["unit_id","name"]}},"required":["ical_source_id","feed_url","active"]}}},"required":["property_id","count","ical_sources"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Nemovitost/vlastník neexistuje (PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/ical-sources/{sourceId}/deactivate":{"post":{"operationId":"deactivate_ical_source","summary":"Deaktivuj iCal feed (active=0 + odstraň jeho bloky)","description":"Deaktivuje feed (active=0) a ODSTRANÍ jeho ical bloky — termíny se tím zase uvolní (deaktivovaný feed nesmí dál blokovat). Manual/booking bloky beze změny. Idempotentní. Cizí/neexistující feed → 404 ICAL_SOURCE_NOT_FOUND. Není MCP tool.","tags":["ical"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"sourceId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id feedu (ics_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"allOf":[{"type":"object","description":"Zaregistrovaný externí iCal feed nemovitosti (1:N per property). Sync stáhne feed a upsertne VEVENTy jako ical bloky → ovlivní dostupnost. `last_status` = výsledek posledního pokusu o sync.","properties":{"ical_source_id":{"type":"string","description":"Stabilní veřejné ID (ics_xxx)"},"feed_url":{"type":"string","description":"URL iCal feedu (Booking/Airbnb/Google export)"},"label":{"type":"string","nullable":true,"description":"Volitelný štítek zdroje (Booking/Airbnb…)"},"active":{"type":"boolean","description":"Deaktivovaný (false): jeho ical bloky byly odstraněny, dál neblokuje"},"last_synced_at":{"type":"string","format":"date-time","nullable":true,"description":"Čas posledního ÚSPĚŠNÉHO syncu (null = dosud nesyncováno)"},"last_status":{"type":"string","nullable":true,"description":"Výsledek posledního pokusu: ok / ICAL_FETCH_FAILED / ICAL_PARSE_FAILED"},"created_at":{"type":"string","format":"date-time"},"unit":{"type":"object","description":"Jednotka, které se feed týká (multi-unit, MU-10a). PŘÍTOMNO jen u feedu konkrétní jednotky (jeho importované bloky shodí JEN tu jednotku); u feedu celé nemovitosti (celku) se klíč VYNECHÁVÁ.","properties":{"unit_id":{"type":"string","description":"Stabilní veřejné ID jednotky (unit_xxx)"},"name":{"type":"string","description":"Název jednotky"}},"required":["unit_id","name"]}},"required":["ical_source_id","feed_url","active"]},{"type":"object","properties":{"removed_blocks":{"type":"integer","description":"Počet odstraněných ical bloků"}}}]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Feed/nemovitost/vlastník neexistuje (ICAL_SOURCE_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/properties/{propertyId}/ical-sources/{sourceId}/sync":{"post":{"operationId":"sync_ical_source","summary":"Spusť one-shot import z iCal feedu","description":"Stáhne feed, naparsuje VEVENTy a upsertne je jako ical bloky navázané na feed → reálně ovlivní dostupnost (get_quote/create_hold na obsazený termín → 409 DATES_UNAVAILABLE). Idempotentní po (feed, UID): opakovaný sync beze změny nevytvoří duplikát; VEVENT, který z feedu zmizel, se smaže (storno v OTA uvolní termín). Nedostupný feed → 502 ICAL_FETCH_FAILED; nevalidní tělo → 422 ICAL_PARSE_FAILED (v obou last_status zaznamenán, žádné 5xx crash / tichý prázdný import). Cizí/neexistující feed → 404 ICAL_SOURCE_NOT_FOUND. Není MCP tool.","tags":["ical"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"propertyId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id nemovitosti (prop_xxx)"},{"name":"sourceId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id feedu (ics_xxx)"}],"responses":{"200":{"description":"Import proběhl","content":{"application/json":{"schema":{"type":"object","description":"Souhrn one-shot syncu iCal feedu. Idempotentní po (feed, UID) — opakovaný sync beze změny vrátí samé unchanged, 0 created/updated/removed.","properties":{"ical_source_id":{"type":"string"},"last_synced_at":{"type":"string","format":"date-time","nullable":true},"last_status":{"type":"string","description":"ok při úspěchu"},"created":{"type":"integer","description":"Nové bloky (nový VEVENT UID)"},"updated":{"type":"integer","description":"Bloky s posunutým termínem (stejné UID, jiné datum)"},"removed":{"type":"integer","description":"Bloky smazané (VEVENT zmizel z feedu = storno v OTA)"},"unchanged":{"type":"integer","description":"Beze změny"},"total":{"type":"integer","description":"Počet VEVENTů ve feedu po syncu"}},"required":["ical_source_id","created","updated","removed","total"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Feed/nemovitost/vlastník neexistuje (ICAL_SOURCE_NOT_FOUND / PROPERTY_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Stažené tělo není validní iCalendar (ICAL_PARSE_FAILED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"502":{"description":"Feed nedostupný / HTTP chyba (ICAL_FETCH_FAILED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/bookings/{bookingPub}/messages":{"post":{"operationId":"post_host_message","summary":"Host pošle zprávu do vlákna rezervace","description":"Host přidá zprávu do vlákna rezervace (server nastaví author=host — attribuce plyne z autentizační cesty, NE z těla; `author` v těle je odmítnut). Vyžaduje platnou host-session (magic-link) k této rezervaci → jinak 401 AUTH_REQUIRED (nic se nezapíše). Prázdný/přeplněný `body` (1–4000) → 400 VALIDATION_ERROR. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":4000,"description":"Text zprávy (1–4000 znaků). Autor se NEbere z těla — plyne z autentizační cesty."}},"required":["body"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Zpráva ve vlákně u rezervace (bez interního id). `author` plyne z autentizační cesty (host přes booking.public_id, owner přes owner-scope) — NIKDY z těla requestu. `read_at` = kdy protistrana zprávu reálně přečetla (null = nepřečteno).","properties":{"message_id":{"type":"string","description":"Stabilní veřejné ID (msg_xxx)"},"author":{"type":"string","enum":["host","owner"],"description":"Autor zprávy (z autentizační cesty, ne z těla)"},"body":{"type":"string","description":"Text zprávy (1–4000 znaků)"},"read_at":{"type":"string","format":"date-time","nullable":true,"description":"Kdy protistrana zprávu přečetla (null = nepřečteno)"},"created_at":{"type":"string","format":"date-time"}},"required":["message_id","author","body","created_at"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/cizí host-session (AUTH_REQUIRED) — přihlaste se magic-linkem k této rezervaci (I16c)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace neexistuje (BOOKING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}},"get":{"operationId":"list_host_messages","summary":"Vlákno rezervace (host)","description":"Vrátí celé vlákno rezervace chronologicky (zprávy hosta i vlastníka). Vyžaduje platnou host-session (magic-link) k této rezervaci → jinak 401 AUTH_REQUIRED. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Vlákno rezervace chronologicky (zprávy obou stran).","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"count":{"type":"integer"},"messages":{"type":"array","items":{"type":"object","description":"Zpráva ve vlákně u rezervace (bez interního id). `author` plyne z autentizační cesty (host přes booking.public_id, owner přes owner-scope) — NIKDY z těla requestu. `read_at` = kdy protistrana zprávu reálně přečetla (null = nepřečteno).","properties":{"message_id":{"type":"string","description":"Stabilní veřejné ID (msg_xxx)"},"author":{"type":"string","enum":["host","owner"],"description":"Autor zprávy (z autentizační cesty, ne z těla)"},"body":{"type":"string","description":"Text zprávy (1–4000 znaků)"},"read_at":{"type":"string","format":"date-time","nullable":true,"description":"Kdy protistrana zprávu přečetla (null = nepřečteno)"},"created_at":{"type":"string","format":"date-time"}},"required":["message_id","author","body","created_at"]}}},"required":["booking_id","count","messages"]}}}},"401":{"description":"Chybí/neplatná/cizí host-session (AUTH_REQUIRED) — přihlaste se magic-linkem k této rezervaci (I16c)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace neexistuje (BOOKING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/api/bookings/{bookingPub}/messages/read":{"post":{"operationId":"mark_host_read","summary":"Host označí zprávy vlastníka za přečtené","description":"Nastaví reálný read_at na dosud nepřečtené zprávy PROTISTRANY (author=owner). Idempotentní — už přečtené se nepřepíší. Neexistující rezervace → 404 BOOKING_NOT_FOUND. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Výsledek označení zpráv protistrany za přečtené (idempotentní — jen dosud nepřečtené).","properties":{"booking_id":{"type":"string"},"marked_read":{"type":"integer","description":"Počet zpráv, kterým se v tomto volání nastavil read_at"}},"required":["booking_id","marked_read"]}}}},"401":{"description":"Chybí/neplatná/cizí host-session (AUTH_REQUIRED) — přihlaste se magic-linkem k této rezervaci (I16c)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace neexistuje (BOOKING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/api/bookings/{bookingPub}/messages/unread-count":{"get":{"operationId":"host_unread_count","summary":"Počet nepřečtených zpráv vlastníka (host)","description":"Vrátí `unread` = počet dosud nepřečtených zpráv PROTISTRANY (author=owner, read_at IS NULL) — reálný COUNT, ne cache. Prázdné vlákno → `{ unread: 0 }`. Vyžaduje platnou host-session (magic-link) k této rezervaci → jinak 401 AUTH_REQUIRED. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Počet dosud nepřečtených zpráv PROTISTRANY (read-model I7c) — reálný COUNT nad `message`.read_at.","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"unread":{"type":"integer","description":"Počet zpráv protistrany s read_at IS NULL (host čte zprávy vlastníka a naopak)"}},"required":["booking_id","unread"]}}}},"401":{"description":"Chybí/neplatná/cizí host-session (AUTH_REQUIRED) — přihlaste se magic-linkem k této rezervaci (I16c)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace neexistuje (BOOKING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/api/owners/{ownerId}/bookings/{bookingPub}/messages":{"post":{"operationId":"post_owner_message","summary":"Vlastník pošle zprávu do vlákna rezervace","description":"Vlastník přidá zprávu do vlákna své rezervace (server nastaví author=owner — attribuce z autentizační cesty, NE z těla). Prázdný/přeplněný `body` (1–4000) → 400. Cizí/neexistující rezervace → 404 BOOKING_NOT_FOUND. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":4000,"description":"Text zprávy (1–4000 znaků). Autor se NEbere z těla — plyne z autentizační cesty."}},"required":["body"],"additionalProperties":false}}}},"responses":{"201":{"description":"Vytvořeno","content":{"application/json":{"schema":{"type":"object","description":"Zpráva ve vlákně u rezervace (bez interního id). `author` plyne z autentizační cesty (host přes booking.public_id, owner přes owner-scope) — NIKDY z těla requestu. `read_at` = kdy protistrana zprávu reálně přečetla (null = nepřečteno).","properties":{"message_id":{"type":"string","description":"Stabilní veřejné ID (msg_xxx)"},"author":{"type":"string","enum":["host","owner"],"description":"Autor zprávy (z autentizační cesty, ne z těla)"},"body":{"type":"string","description":"Text zprávy (1–4000 znaků)"},"read_at":{"type":"string","format":"date-time","nullable":true,"description":"Kdy protistrana zprávu přečetla (null = nepřečteno)"},"created_at":{"type":"string","format":"date-time"}},"required":["message_id","author","body","created_at"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace/vlastník neexistuje (BOOKING_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]},"get":{"operationId":"list_owner_messages","summary":"Vlákno rezervace (vlastník)","description":"Vrátí totéž vlákno rezervace chronologicky (owner-scoped). Cizí/neexistující rezervace → 404 BOOKING_NOT_FOUND. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Vlákno rezervace chronologicky (zprávy obou stran).","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"count":{"type":"integer"},"messages":{"type":"array","items":{"type":"object","description":"Zpráva ve vlákně u rezervace (bez interního id). `author` plyne z autentizační cesty (host přes booking.public_id, owner přes owner-scope) — NIKDY z těla requestu. `read_at` = kdy protistrana zprávu reálně přečetla (null = nepřečteno).","properties":{"message_id":{"type":"string","description":"Stabilní veřejné ID (msg_xxx)"},"author":{"type":"string","enum":["host","owner"],"description":"Autor zprávy (z autentizační cesty, ne z těla)"},"body":{"type":"string","description":"Text zprávy (1–4000 znaků)"},"read_at":{"type":"string","format":"date-time","nullable":true,"description":"Kdy protistrana zprávu přečetla (null = nepřečteno)"},"created_at":{"type":"string","format":"date-time"}},"required":["message_id","author","body","created_at"]}}},"required":["booking_id","count","messages"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace/vlastník neexistuje (BOOKING_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/bookings/{bookingPub}/messages/read":{"post":{"operationId":"mark_owner_read","summary":"Vlastník označí zprávy hosta za přečtené","description":"Nastaví reálný read_at na dosud nepřečtené zprávy PROTISTRANY (author=host). Idempotentní. Cizí/neexistující rezervace → 404 BOOKING_NOT_FOUND. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Výsledek označení zpráv protistrany za přečtené (idempotentní — jen dosud nepřečtené).","properties":{"booking_id":{"type":"string"},"marked_read":{"type":"integer","description":"Počet zpráv, kterým se v tomto volání nastavil read_at"}},"required":["booking_id","marked_read"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace/vlastník neexistuje (BOOKING_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/bookings/{bookingPub}/messages/unread-count":{"get":{"operationId":"owner_unread_count","summary":"Počet nepřečtených zpráv hosta (vlastník)","description":"Vrátí `unread` = počet dosud nepřečtených zpráv PROTISTRANY (author=host, read_at IS NULL) — reálný COUNT. Owner-scope: cizí/neexistující rezervace → 404 BOOKING_NOT_FOUND (bez leaku počtu), neexistující vlastník → 404 OWNER_NOT_FOUND. Není MCP tool.","tags":["messaging"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Počet dosud nepřečtených zpráv PROTISTRANY (read-model I7c) — reálný COUNT nad `message`.read_at.","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"unread":{"type":"integer","description":"Počet zpráv protistrany s read_at IS NULL (host čte zprávy vlastníka a naopak)"}},"required":["booking_id","unread"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace/vlastník neexistuje (BOOKING_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/owners/{ownerId}/messages/unread-count":{"get":{"operationId":"owner_global_unread_count","summary":"Owner-globální počet nepřečtených zpráv hosta (rollup přes všechny bookingy)","description":"Vrátí `unread` = součet dosud nepřečtených zpráv hosta (author=host, read_at IS NULL) přes VŠECHNY bookingy vlastníka — jeden reálný agregační COUNT(*) přes owner-scope join booking→property (žádný N+1, žádná cache). Badge do owner dashboardu. Vlastník bez bookingů/zpráv → `{ unread: 0 }`. Neexistující vlastník → 404 OWNER_NOT_FOUND (bez pole `unread`). Cizí bookingy se do součtu NEpočítají (owner-scope izolace). Není MCP tool (agenti nechatují).","tags":["messaging"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Owner-globální rollup nepřečtených zpráv hosta napříč VŠEMI bookingy vlastníka (read-model I7d) — jeden reálný agregační COUNT(*), badge do owner dashboardu.","properties":{"owner_id":{"type":"string","description":"public_id vlastníka (own_xxx)"},"unread":{"type":"integer","description":"Součet zpráv author=host s read_at IS NULL přes všechny bookingy vlastníka (0 pokud žádné)"}},"required":["owner_id","unread"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Vlastník neexistuje (OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/bookings/{bookingPub}/guests":{"post":{"operationId":"submit_checkin_guests","summary":"Host odešle online check-in (evidence osob)","description":"Host odešle CELÝ check-in list osob najednou (zákonná evidence, § 3g). Nový POST idempotentně NAHRADÍ dosavadní sadu (host smí opravit před příjezdem) — buď celá sada, nebo nic (tx atomická). `is_child` server VYPOČTE z data narození vs. datum příjezdu (NEbere z těla); `is_foreigner=true` vyžaduje `citizenship`+`document_number`. Check-in jen po potvrzení rezervace (CONFIRMED/COMPLETED) — jinak 409 CHECKIN_NOT_ALLOWED. Cizinec bez dokladu → 422 FOREIGNER_FIELDS_REQUIRED. Prázdný seznam / budoucí datum narození / neznámé pole → 400. Neexistující rezervace → 404. Není MCP tool.","tags":["checkin"],"parameters":[{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"guests":{"type":"array","items":{"type":"object","properties":{"first_name":{"type":"string","minLength":1,"maxLength":100,"description":"Jméno"},"last_name":{"type":"string","minLength":1,"maxLength":100,"description":"Příjmení"},"birth_date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Datum narození (YYYY-MM-DD) — z něj se počítá is_child k datu příjezdu"},"address":{"type":"string","minLength":1,"maxLength":500,"description":"Adresa trvalého pobytu (u cizince adresa v zahraničí)"},"is_foreigner":{"type":"boolean","description":"true = cizinec (vyžaduje citizenship + document_number)"},"citizenship":{"type":"string","minLength":1,"maxLength":80,"description":"Státní příslušnost — povinné u cizince (u CZ hosta se ignoruje)"},"document_number":{"type":"string","minLength":1,"maxLength":60,"description":"Číslo cestovního dokladu — povinné u cizince"},"visa_number":{"type":"string","minLength":1,"maxLength":60,"description":"Číslo víza — volitelné i u cizince"}},"required":["first_name","last_name","birth_date","address","is_foreigner"],"additionalProperties":false},"minItems":1,"maxItems":30,"description":"Seznam osob (celá sada — nový POST nahradí dosavadní)."}},"required":["guests"],"additionalProperties":false}}}},"responses":{"201":{"description":"Uloženo","content":{"application/json":{"schema":{"type":"object","description":"Evidence osob u rezervace (dle pořadí odeslání).","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"count":{"type":"integer"},"guests":{"type":"array","items":{"type":"object","description":"Osoba v evidenci hostů (online check-in). `is_child` i `is_foreigner` jsou UKLÁDANÉ VYPOČTENÉ hodnoty — `is_child` z data narození vs. datum příjezdu, NE z těla requestu. Cizinecká pole (citizenship/document_number/visa_number) jsou u CZ hosta null.","properties":{"guest_id":{"type":"string","description":"Stabilní veřejné ID osoby (guest_xxx)"},"first_name":{"type":"string"},"last_name":{"type":"string"},"birth_date":{"type":"string","format":"date","description":"Datum narození (YYYY-MM-DD)"},"address":{"type":"string","description":"Adresa trvalého pobytu"},"is_foreigner":{"type":"boolean","description":"true = cizinec (má vyplněná cizinecká pole)"},"is_child":{"type":"boolean","description":"Vypočteno: osoba <18 k datu příjezdu (pro výjimku poplatku z pobytu)"},"citizenship":{"type":"string","nullable":true,"description":"Státní příslušnost (null u CZ hosta)"},"document_number":{"type":"string","nullable":true,"description":"Číslo cestovního dokladu (null u CZ hosta)"},"visa_number":{"type":"string","nullable":true,"description":"Číslo víza (null, není-li)"},"created_at":{"type":"string","format":"date-time"}},"required":["guest_id","first_name","last_name","birth_date","address","is_foreigner","is_child","created_at"]}}},"required":["booking_id","count","guests"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR / INVALID_DATES)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace neexistuje (BOOKING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"409":{"description":"Rezervace ještě není potvrzená (CHECKIN_NOT_ALLOWED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Cizinec bez povinných polí (FOREIGNER_FIELDS_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}},"get":{"operationId":"list_checkin_guests","summary":"Evidence osob u rezervace (host)","description":"Vrátí evidenci osob u rezervace (dle pořadí odeslání). Neexistující rezervace → 404 BOOKING_NOT_FOUND. Není MCP tool.","tags":["checkin"],"parameters":[{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Evidence osob u rezervace (dle pořadí odeslání).","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"count":{"type":"integer"},"guests":{"type":"array","items":{"type":"object","description":"Osoba v evidenci hostů (online check-in). `is_child` i `is_foreigner` jsou UKLÁDANÉ VYPOČTENÉ hodnoty — `is_child` z data narození vs. datum příjezdu, NE z těla requestu. Cizinecká pole (citizenship/document_number/visa_number) jsou u CZ hosta null.","properties":{"guest_id":{"type":"string","description":"Stabilní veřejné ID osoby (guest_xxx)"},"first_name":{"type":"string"},"last_name":{"type":"string"},"birth_date":{"type":"string","format":"date","description":"Datum narození (YYYY-MM-DD)"},"address":{"type":"string","description":"Adresa trvalého pobytu"},"is_foreigner":{"type":"boolean","description":"true = cizinec (má vyplněná cizinecká pole)"},"is_child":{"type":"boolean","description":"Vypočteno: osoba <18 k datu příjezdu (pro výjimku poplatku z pobytu)"},"citizenship":{"type":"string","nullable":true,"description":"Státní příslušnost (null u CZ hosta)"},"document_number":{"type":"string","nullable":true,"description":"Číslo cestovního dokladu (null u CZ hosta)"},"visa_number":{"type":"string","nullable":true,"description":"Číslo víza (null, není-li)"},"created_at":{"type":"string","format":"date-time"}},"required":["guest_id","first_name","last_name","birth_date","address","is_foreigner","is_child","created_at"]}}},"required":["booking_id","count","guests"]}}}},"404":{"description":"Rezervace neexistuje (BOOKING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/api/owners/{ownerId}/bookings/{bookingPub}/guests":{"get":{"operationId":"list_checkin_guests_owner","summary":"Evidence osob u rezervace (vlastník)","description":"Vrátí tutéž evidenci osob (owner-scoped) — vlastník vidí check-in ke své rezervaci. Cizí/neexistující rezervace → 404 BOOKING_NOT_FOUND. Není MCP tool.","tags":["checkin"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Evidence osob u rezervace (dle pořadí odeslání).","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"count":{"type":"integer"},"guests":{"type":"array","items":{"type":"object","description":"Osoba v evidenci hostů (online check-in). `is_child` i `is_foreigner` jsou UKLÁDANÉ VYPOČTENÉ hodnoty — `is_child` z data narození vs. datum příjezdu, NE z těla requestu. Cizinecká pole (citizenship/document_number/visa_number) jsou u CZ hosta null.","properties":{"guest_id":{"type":"string","description":"Stabilní veřejné ID osoby (guest_xxx)"},"first_name":{"type":"string"},"last_name":{"type":"string"},"birth_date":{"type":"string","format":"date","description":"Datum narození (YYYY-MM-DD)"},"address":{"type":"string","description":"Adresa trvalého pobytu"},"is_foreigner":{"type":"boolean","description":"true = cizinec (má vyplněná cizinecká pole)"},"is_child":{"type":"boolean","description":"Vypočteno: osoba <18 k datu příjezdu (pro výjimku poplatku z pobytu)"},"citizenship":{"type":"string","nullable":true,"description":"Státní příslušnost (null u CZ hosta)"},"document_number":{"type":"string","nullable":true,"description":"Číslo cestovního dokladu (null u CZ hosta)"},"visa_number":{"type":"string","nullable":true,"description":"Číslo víza (null, není-li)"},"created_at":{"type":"string","format":"date-time"}},"required":["guest_id","first_name","last_name","birth_date","address","is_foreigner","is_child","created_at"]}}},"required":["booking_id","count","guests"]}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace/vlastník neexistuje (BOOKING_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/api/bookings/{bookingPub}/payment":{"get":{"operationId":"get_booking_payment","summary":"Platební instrukce rezervace (direct: celý total / deposit: záloha + SPAYD)","description":"Vrátí platební instrukce rezervace + hotový SPD/SPAYD řetězec pro QR platbu (jen data — PNG render je klientská věc): CZ IBAN vlastníka (mod-97) a stabilní variabilní symbol. `mode=direct` (přímá platba host → vlastník): SPAYD na `amount_czk` = celý booking total. `mode=deposit` (režim B záloha % + doplatek): SPAYD na `deposit_czk` = záloha placená předem (`deposit_percent`/`balance_czk`/`total_czk` popisují rozpad; doplatek `balance_czk` je informativní, párování/druhé QR přijde s I5b-3). deposit-property bez nastaveného `deposit_percent` → 422 DEPOSIT_PERCENT_MISSING (deterministicky, ne tiché % / direct fallback). Vlastník bez vyplněného účtu → 422 ACCOUNT_MISSING (nikdy fake IBAN). Neexistující rezervace → 404 BOOKING_NOT_FOUND. Není MCP tool (agenti neplatí).","tags":["payments"],"parameters":[{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","description":"Platební instrukce rezervace. `mode=direct` (přímá platba host → vlastník) → `amount_czk` = celý booking total. `mode=deposit` (režim B záloha % + doplatek) → SPAYD/QR je na `deposit_czk` (záloha placená předem), pole `deposit_percent`/`deposit_czk`/`balance_czk`/`total_czk` popisují rozpad (`deposit_czk + balance_czk === total_czk`; balance = informativní doplatek na místě, řeší I5b-3). `spayd` = standardní SPD/SPAYD řetězec pro QR platbu (jen data; PNG render je klientská věc), `account_iban` = platný CZ IBAN vlastníka, `variable_symbol` = stabilní VS rezervace.","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"mode":{"type":"string","enum":["direct","deposit"],"description":"Platební režim: direct = celý total, deposit = QR na zálohu"},"amount_czk":{"type":"integer","description":"JEN mode=direct: částka k úhradě v celých Kč (== booking total)"},"deposit_percent":{"type":"integer","description":"JEN mode=deposit: owner-nastavené % zálohy (1–100)"},"deposit_czk":{"type":"integer","description":"JEN mode=deposit: částka zálohy placené předem (== SPAYD AM); round(total × deposit_percent/100)"},"balance_czk":{"type":"integer","description":"JEN mode=deposit: informativní doplatek na místě (total − deposit; párování/druhé QR = pozdější osa)"},"total_czk":{"type":"integer","description":"JEN mode=deposit: celkový booking total (== zmrazený quote total; deposit_czk + balance_czk)"},"deposit_paid":{"type":"boolean","description":"JEN mode=deposit: přijetí zálohy REÁLNĚ potvrzeno vlastníkem (existuje payment_match řádek; I5b-3). false = dosud nepotvrzeno."},"matched_amount_czk":{"type":["integer","null"],"description":"JEN mode=deposit: reálně zapsaná potvrzená částka zálohy (== deposit_czk); null když nepotvrzeno"},"matched_at":{"type":["string","null"],"format":"date-time","description":"JEN mode=deposit: čas potvrzení přijetí zálohy vlastníkem (ISO); null když nepotvrzeno"},"currency":{"type":"string","example":"CZK"},"account_iban":{"type":"string","description":"Platný CZ IBAN vlastníka (mod-97), pole ACC v SPAYD"},"account_human":{"type":"string","description":"Lidsky čitelné CZ číslo účtu vlastníka (předčíslí-číslo/kód)"},"variable_symbol":{"type":"string","description":"Stabilní variabilní symbol platby (pole X-VS v SPAYD)"},"spayd":{"type":"string","description":"SPD*1.0*ACC:…*AM:…*CC:CZK*X-VS:…*MSG:… (AM = amount_czk u direct / deposit_czk u deposit; vstup pro QR generátor klienta)"}},"required":["booking_id","mode","currency","account_iban","account_human","variable_symbol","spayd"]}}}},"404":{"description":"Rezervace neexistuje (BOOKING_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"Vlastník nemá vyplněný účet (ACCOUNT_MISSING) nebo deposit-property nemá nastavené deposit_percent (DEPOSIT_PERCENT_MISSING)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/api/owners/{ownerId}/bookings/{bookingPub}/deposit/confirm":{"post":{"operationId":"confirm_deposit_received","summary":"Vlastník potvrdí přijetí zálohy (režim B, ruční)","description":"Vlastník ručně potvrdí, že záloha (režim B) dorazila — bez bank-API (spec „bez opt-inu potvrzuje přijetí zálohy ručně\"). Zapíše payment_match na REÁLNĚ přepočtenou částku zálohy (round(booking total × deposit_percent/100)) s VS = booking.id; částka se NEbere z těla (jen volitelná `note`). Poté `GET …/payment` vrací `deposit_paid=true`. IDEMPOTENTNÍ: druhé potvrzení téže zálohy vrátí tentýž řádek (200, bez duplikace); první → 201. NEMĚNÍ stav rezervace. direct-property → 422 DEPOSIT_NOT_APPLICABLE; deposit bez nastaveného deposit_percent → 422 DEPOSIT_PERCENT_MISSING; rezervace v nevhodném stavu (HOLD/PENDING_OWNER/CANCELLED_*) → 409 DEPOSIT_NOT_CONFIRMABLE; cizí/neexistující rezervace/vlastník → 404. Není MCP tool (agenti neplatí).","tags":["payments"],"parameters":[{"name":"ownerId","in":"path","required":true,"schema":{"type":"string"},"description":"public_id vlastníka (own_xxx)"},{"name":"bookingPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id rezervace (bkg_xxx)"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":255,"description":"Volitelná poznámka vlastníka k potvrzení (např. datum přijetí na účet)."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Již potvrzeno dříve — existující payment_match (idempotence)","content":{"application/json":{"schema":{"type":"object","description":"Potvrzené přijetí zálohy (režim B, ruční — bez bank-API). `amount_czk` je REÁLNĚ přepočtená částka zálohy (round(booking total × deposit_percent/100)), NE hodnota z těla requestu. `variable_symbol` = booking.id. Idempotentní: druhé potvrzení téže zálohy vrátí tentýž řádek (bez duplikace). NEMĚNÍ stav rezervace.","properties":{"match_id":{"type":"string","description":"Stabilní veřejné ID záznamu (pay_xxx)"},"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"kind":{"type":"string","enum":["deposit"],"description":"Druh platby — zatím jen záloha (deposit)"},"amount_czk":{"type":"integer","description":"Reálně přepočtená částka zálohy v celých Kč (== deposit_czk)"},"variable_symbol":{"type":"string","description":"Variabilní symbol platby (= booking.id)"},"source":{"type":"string","enum":["manual"],"description":"Zdroj potvrzení — ruční vlastníkem (Fio auto-párování = pozdější osa)"},"note":{"type":["string","null"],"description":"Volitelná poznámka vlastníka"},"matched_at":{"type":"string","format":"date-time","description":"Čas potvrzení přijetí zálohy (ISO)"}},"required":["match_id","booking_id","kind","amount_czk","variable_symbol","source","matched_at"]}}}},"201":{"description":"Přijetí zálohy potvrzeno (nový payment_match)","content":{"application/json":{"schema":{"type":"object","description":"Potvrzené přijetí zálohy (režim B, ruční — bez bank-API). `amount_czk` je REÁLNĚ přepočtená částka zálohy (round(booking total × deposit_percent/100)), NE hodnota z těla requestu. `variable_symbol` = booking.id. Idempotentní: druhé potvrzení téže zálohy vrátí tentýž řádek (bez duplikace). NEMĚNÍ stav rezervace.","properties":{"match_id":{"type":"string","description":"Stabilní veřejné ID záznamu (pay_xxx)"},"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"kind":{"type":"string","enum":["deposit"],"description":"Druh platby — zatím jen záloha (deposit)"},"amount_czk":{"type":"integer","description":"Reálně přepočtená částka zálohy v celých Kč (== deposit_czk)"},"variable_symbol":{"type":"string","description":"Variabilní symbol platby (= booking.id)"},"source":{"type":"string","enum":["manual"],"description":"Zdroj potvrzení — ruční vlastníkem (Fio auto-párování = pozdější osa)"},"note":{"type":["string","null"],"description":"Volitelná poznámka vlastníka"},"matched_at":{"type":"string","format":"date-time","description":"Čas potvrzení přijetí zálohy (ISO)"}},"required":["match_id","booking_id","kind","amount_czk","variable_symbol","source","matched_at"]}}}},"400":{"description":"Chyba vstupu (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/neplatná/prošlá owner-session (OWNER_AUTH_REQUIRED) — přihlaste se jako vlastník magic-linkem (I18b). Handler neběží, nic se nezapíše.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"403":{"description":"Platná owner-session, ale nepatří tomuto vlastníkovi (OWNER_FORBIDDEN) — leak-free (neprozradí (ne)existenci ownera/property). Znalost owner public_id sama nestačí (I18b).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Rezervace/vlastník neexistuje (BOOKING_NOT_FOUND / OWNER_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"409":{"description":"Rezervace není ve stavu, kdy lze potvrdit zálohu (DEPOSIT_NOT_CONFIRMABLE)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"422":{"description":"direct-property (DEPOSIT_NOT_APPLICABLE) nebo chybí deposit_percent (DEPOSIT_PERCENT_MISSING)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}},"security":[{"OwnerSession":[]}]}},"/admin/photos/moderation":{"get":{"operationId":"admin_list_moderation_queue","summary":"Fronta fotek k moderaci (admin)","description":"Vrátí fotky čekající na verdikt (`moderation_status IN pending|review`), NEJSTARŠÍ PRVNÍ, s kontextem (property.public_id + title, owner.public_id). Odblokovává foto osu — nahraná fotka startuje pending a `resolvePhotoForServe` servíruje jen approved. Vyžaduje admin token (`X-Admin-Token` nebo `Authorization: Bearer`). Není MCP tool (admin není agentní povrch).","tags":["admin"],"security":[{"AdminToken":[]}],"responses":{"200":{"description":"Fronta","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"photos":{"type":"array","items":{"type":"object","description":"Fotka čekající na moderaci + kontext pro admina (které nemovitosti/vlastníka se týká).","properties":{"photo_id":{"type":"string","description":"Stabilní veřejné ID (pho_xxx)"},"url":{"type":"string","description":"URL fotky"},"sort_order":{"type":"integer","description":"Pořadí ve veřejné galerii"},"moderation_status":{"type":"string","enum":["pending","approved","rejected","review"],"description":"Stav moderace: pending (nově přidaná, čeká na vision I14b) / approved (veřejně viditelná) / rejected / review (hraniční, admin fronta)"},"moderation_reason":{"type":["string","null"],"description":"Důvod zamítnutí / hraničnosti (naplní I14b vision; teď null)"},"content_type":{"type":["string","null"],"enum":["image/jpeg","image/png","image/webp",null],"description":"I14c: mime binárně nahrané fotky z magic-byte sniffu (null = URL/legacy fotka)"},"byte_size":{"type":["integer","null"],"description":"I14c: velikost uložených bajtů (null = URL/legacy fotka)"},"created_at":{"type":"string","format":"date-time"},"property":{"type":"object","properties":{"property_id":{"type":"string","description":"public_id nemovitosti (prop_xxx)"},"title":{"type":"string","description":"Název nemovitosti (property.name)"}},"required":["property_id","title"]},"owner":{"type":"object","properties":{"owner_id":{"type":"string","description":"public_id vlastníka (own_xxx)"}},"required":["owner_id"]}},"required":["photo_id","url","sort_order","moderation_status","property","owner"]}}},"required":["count","photos"]}}}},"401":{"description":"Chybí/nesouhlasí admin token (ADMIN_AUTH_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"503":{"description":"Admin rozhraní není nakonfigurováno — ADMIN_TOKEN chybí (ADMIN_DISABLED, fail-closed)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/admin/photos/{photoPub}/moderate":{"post":{"operationId":"admin_moderate_photo","summary":"Zapiš verdikt fotky (admin)","description":"Zapíše REÁLNÝ admin verdikt: `approved` → fotka poteče veřejně přes `resolvePhotoForServe`; `rejected` → nadále blokována (+ povinný `reason`). Přechod povolen JEN z pending|review; terminální stav (approved/rejected) → 409 MODERATION_ALREADY_DECIDED (žádný tichý druhý zápis); neznámá fotka → 404 PHOTO_NOT_FOUND. Verdikt je LIDSKÉ rozhodnutí (doplněk k I14b vision, ne simulace AI). Vyžaduje admin token. Není MCP tool.","tags":["admin"],"security":[{"AdminToken":[]}],"parameters":[{"name":"photoPub","in":"path","required":true,"schema":{"type":"string"},"description":"public_id fotky (pho_xxx)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"verdict":{"type":"string","enum":["approved","rejected"],"description":"approved / rejected"},"reason":{"type":"string","description":"Důvod zamítnutí (u rejected POVINNÝ; u approved ignorován → uloží se NULL)"}},"required":["verdict"]}}}},"responses":{"200":{"description":"Verdikt zapsán","content":{"application/json":{"schema":{"type":"object","description":"Fotka nemovitosti (bez interního id) s per-foto stavem AI moderace (I14a). Owner vidí všechny se stavem; veřejné povrchy jen approved.","properties":{"photo_id":{"type":"string","description":"Stabilní veřejné ID (pho_xxx)"},"url":{"type":"string","description":"URL fotky"},"sort_order":{"type":"integer","description":"Pořadí ve veřejné galerii"},"moderation_status":{"type":"string","enum":["pending","approved","rejected","review"],"description":"Stav moderace: pending (nově přidaná, čeká na vision I14b) / approved (veřejně viditelná) / rejected / review (hraniční, admin fronta)"},"moderation_reason":{"type":["string","null"],"description":"Důvod zamítnutí / hraničnosti (naplní I14b vision; teď null)"},"content_type":{"type":["string","null"],"enum":["image/jpeg","image/png","image/webp",null],"description":"I14c: mime binárně nahrané fotky z magic-byte sniffu (null = URL/legacy fotka)"},"byte_size":{"type":["integer","null"],"description":"I14c: velikost uložených bajtů (null = URL/legacy fotka)"},"created_at":{"type":"string","format":"date-time"}},"required":["photo_id","url","sort_order","moderation_status"]}}}},"400":{"description":"Chyba vstupu — např. rejected bez reason (VALIDATION_ERROR)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/nesouhlasí admin token (ADMIN_AUTH_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"404":{"description":"Fotka neexistuje (PHOTO_NOT_FOUND)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"409":{"description":"Fotka už má finální verdikt (MODERATION_ALREADY_DECIDED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"503":{"description":"Admin rozhraní není nakonfigurováno — ADMIN_TOKEN chybí (ADMIN_DISABLED, fail-closed)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/admin/bookings":{"get":{"operationId":"admin_list_bookings","summary":"Přehled rezervací (admin)","description":"Read-only list rezervací z REÁLNÉHO DB dotazu (JOIN property + owner), NEJNOVĚJŠÍ PRVNÍ (created_at DESC). Volitelný filtr `?status=<ENUM>` (HOLD/PENDING_OWNER/CONFIRMED/COMPLETED/CANCELLED_EXPIRED/CANCELLED_GUEST/CANCELLED_OWNER; neznámá hodnota → 400 INVALID_STATUS; bez filtru → všechny). Volitelný `?limit` (default 50, strop 200). Prázdný stav → 200 + prázdný list (ne 404). DTO NEexponuje interní secrety (*_token/idempotency_key) ani check-in PII hostů. Vyžaduje admin token (`X-Admin-Token` nebo `Authorization: Bearer`). Není MCP tool (admin není agentní povrch).","tags":["admin"],"security":[{"AdminToken":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["HOLD","PENDING_OWNER","CONFIRMED","COMPLETED","CANCELLED_EXPIRED","CANCELLED_GUEST","CANCELLED_OWNER"]},"description":"Filtr na stav rezervace (bez = všechny). Mimo ENUM → 400 INVALID_STATUS."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Max počet vrácených rezervací (default 50, strop 200)."}],"responses":{"200":{"description":"Přehled rezervací (nejnovější první)","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"filter":{"type":"object","properties":{"status":{"type":["string","null"]}}},"limit":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"bookings":{"type":"array","items":{"type":"object","description":"Booking-level summary rezervace pro admina (JOIN property + owner). Read-only. NEobsahuje interní secrety (checkout_token/owner_token/idempotency_key) ani check-in PII hostů (booking_guest) — to je pozdější detail endpoint.","properties":{"booking_id":{"type":"string","description":"public_id rezervace (bkg_xxx)"},"status":{"type":"string","enum":["HOLD","PENDING_OWNER","CONFIRMED","COMPLETED","CANCELLED_EXPIRED","CANCELLED_GUEST","CANCELLED_OWNER"],"description":"Stav rezervace (booking ENUM)"},"property":{"type":"object","properties":{"property_id":{"type":"string","description":"public_id nemovitosti (prop_xxx)"},"title":{"type":"string","description":"Název nemovitosti (property.name)"}},"required":["property_id","title"]},"owner":{"type":"object","properties":{"owner_id":{"type":"string","description":"public_id vlastníka (own_xxx)"}},"required":["owner_id"]},"date_from":{"type":"string","format":"date","description":"Datum příjezdu"},"date_to":{"type":"string","format":"date","description":"Datum odjezdu (exkluzivně)"},"nights":{"type":"integer"},"guests":{"type":"object","properties":{"adults":{"type":"integer"},"children":{"type":"integer"}},"required":["adults","children"]},"total_czk":{"type":"integer","description":"Zmrazený total rezervace (Kč)"},"currency":{"type":"string","example":"CZK"},"guest_name":{"type":"string","description":"Jméno hosta z rezervace (kontakt; ne check-in evidence)"},"guest_email":{"type":"string","format":"email","description":"E-mail hosta z rezervace"},"created_by_ai":{"type":"boolean","description":"Rezervace vznikla přes agenta (MCP/AI)"},"agent_client":{"type":["string","null"],"description":"User-Agent / MCP klient (null u ne-agentní)"},"created_at":{"type":"string","format":"date-time"},"owner_deadline":{"type":["string","null"],"format":"date-time","description":"Do kdy má vlastník potvrdit (null mimo PENDING_OWNER)"},"confirmed_at":{"type":["string","null"],"format":"date-time"},"cancelled_at":{"type":["string","null"],"format":"date-time"}},"required":["booking_id","status","property","owner","date_from","date_to","nights","guests","total_czk","currency","created_at"]}}},"required":["count","bookings"]}}}},"400":{"description":"Neplatná hodnota filtru status (INVALID_STATUS)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/nesouhlasí admin token (ADMIN_AUTH_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"503":{"description":"Admin rozhraní není nakonfigurováno — ADMIN_TOKEN chybí (ADMIN_DISABLED, fail-closed)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/admin/properties":{"get":{"operationId":"admin_list_properties","summary":"Přehled nemovitostí (admin)","description":"Read-only list nemovitostí z REÁLNÉHO DB dotazu (JOIN owner + correlated COUNT approved fotek / aktivních rezervací), NEJNOVĚJŠÍ PRVNÍ (created_at DESC). Volitelný filtr publikačního stavu `?status=draft|published` (I2c publish model `property.status`; neznámá hodnota → 400 INVALID_STATUS; bez filtru → všechny). Volitelný `?limit` (default 50, strop 200). Prázdný stav → 200 + prázdný list (ne 404). DTO NEexponuje owner secrety/kontakty (jen owner.public_id) ani interní tokeny. Vyžaduje admin token (`X-Admin-Token` nebo `Authorization: Bearer`). Není MCP tool (admin není agentní povrch).","tags":["admin"],"security":[{"AdminToken":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["draft","published"]},"description":"Filtr na publikační stav (bez = všechny). Mimo ENUM → 400 INVALID_STATUS."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Max počet vrácených nemovitostí (default 50, strop 200)."}],"responses":{"200":{"description":"Přehled nemovitostí (nejnovější první)","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"filter":{"type":"object","properties":{"status":{"type":["string","null"]}}},"limit":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"properties":{"type":"array","items":{"type":"object","description":"Per-nemovitost summary pro admina (JOIN owner + agregáty). Read-only. NEobsahuje owner secrety/kontakty (jen owner.public_id — owner detail je pozdější slice) ani interní tokeny (ical_export_token/…).","properties":{"property_id":{"type":"string","description":"public_id nemovitosti (prop_xxx)"},"slug":{"type":"string","description":"slug pro property page URL /p/<slug>"},"name":{"type":"string","description":"Název nemovitosti (property.name)"},"type":{"type":"string","enum":["chata","chalupa","apartman","penzion"],"description":"Typ objektu"},"region":{"type":"string","description":"Region/oblast (Beskydy, Krkonoše…)"},"capacity":{"type":"integer","description":"Maximální počet hostů"},"bedrooms":{"type":"integer","description":"Počet ložnic"},"status":{"type":"string","enum":["draft","published"],"description":"Publikační stav (I2c publish lifecycle): draft = dosud nepublikovaná; published = live na veřejných povrchech."},"base_price_czk":{"type":["integer","null"],"description":"Základní cena/noc (Kč). null = draft/dosud neoceněno (ne fabrikovaná 0)."},"payment_mode":{"type":"string","enum":["direct","deposit"],"description":"Platební režim"},"cancellation_policy":{"type":"string","enum":["flexible","moderate","strict"],"description":"Storno šablona"},"approved_photo_count":{"type":"integer","description":"Počet APPROVED fotek z property_photo (jen approved; ne legacy photos JSON)."},"active_bookings_count":{"type":"integer","description":"Počet aktivních rezervací (HOLD/PENDING_OWNER/CONFIRMED; dokončené/zrušené se nepočítají)."},"owner":{"type":"object","properties":{"owner_id":{"type":"string","description":"public_id vlastníka (own_xxx) — bez kontaktů/secretů"}},"required":["owner_id"]},"created_at":{"type":"string","format":"date-time"}},"required":["property_id","slug","name","type","region","capacity","bedrooms","status","payment_mode","cancellation_policy","approved_photo_count","active_bookings_count","owner","created_at"]}}},"required":["count","properties"]}}}},"400":{"description":"Neplatná hodnota filtru status (INVALID_STATUS)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/nesouhlasí admin token (ADMIN_AUTH_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"503":{"description":"Admin rozhraní není nakonfigurováno — ADMIN_TOKEN chybí (ADMIN_DISABLED, fail-closed)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/admin/owners":{"get":{"operationId":"admin_list_owners","summary":"Přehled vlastníků (admin)","description":"Read-only list vlastníků z REÁLNÉHO DB dotazu (correlated COUNT nemovitostí = property_count), NEJNOVĚJŠÍ PRVNÍ (created_at DESC). Volitelný filtr datovka ověření `?verified=true|false` (owner.verified_owner; neznámá hodnota → 400 INVALID_STATUS; bez filtru → všichni). Volitelný `?limit` (default 50, strop 200). Prázdný stav → 200 + prázdný list (ne 404). DTO nese kontakt (e-mail/telefon — vlastníci jsou předmětem přehledu), ale NEexponuje bank_account / verification_meta / interní id. Vyžaduje admin token (`X-Admin-Token` nebo `Authorization: Bearer`). Není MCP tool (admin není agentní povrch).","tags":["admin"],"security":[{"AdminToken":[]}],"parameters":[{"name":"verified","in":"query","required":false,"schema":{"type":"boolean","enum":["true","false"]},"description":"Filtr na datovka ověření (bez = všichni). Mimo {true,false} → 400 INVALID_STATUS."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Max počet vrácených vlastníků (default 50, strop 200)."}],"responses":{"200":{"description":"Přehled vlastníků (nejnovější první)","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer"},"filter":{"type":"object","properties":{"verified":{"type":["boolean","null"]}}},"limit":{"type":"integer"},"generated_at":{"type":"string","format":"date-time"},"owners":{"type":"array","items":{"type":"object","description":"Per-vlastník summary pro admina (owner + correlated COUNT nemovitostí). Read-only. Kontakt (e-mail/telefon) JE (vlastníci jsou předmětem přehledu, operátor pilotu je potřebuje). NEobsahuje bank_account (citlivá platební instrukce — pozdější owner-detail), verification_meta (interní datovka JSON) ani owner internal id.","properties":{"owner_id":{"type":"string","description":"public_id vlastníka (own_xxx)"},"name":{"type":"string","description":"Jméno / název vlastníka (owner.name)"},"email":{"type":"string","format":"email","description":"Kontaktní e-mail vlastníka"},"phone":{"type":["string","null"],"description":"Kontaktní telefon (null pokud neuveden)"},"verified_owner":{"type":"boolean","description":"Datovka ověření — badge důvěry pro agenty (owner.verified_owner)."},"property_count":{"type":"integer","description":"Počet nemovitostí spravovaných vlastníkem (correlated COUNT z property; ne hardcoded)."},"created_at":{"type":"string","format":"date-time"}},"required":["owner_id","name","email","verified_owner","property_count","created_at"]}}},"required":["count","owners"]}}}},"400":{"description":"Neplatná hodnota filtru verified (INVALID_STATUS)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"401":{"description":"Chybí/nesouhlasí admin token (ADMIN_AUTH_REQUIRED)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}},"503":{"description":"Admin rozhraní není nakonfigurováno — ADMIN_TOKEN chybí (ADMIN_DISABLED, fail-closed)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}}}}}}},"/auth/owner/request":{"post":{"operationId":"owner_auth_request","summary":"Vyžádat přihlašovací magic-link vlastníka","description":"Pošle přihlašovací magic-link na REGISTROVANÝ owner e-mail. ANTI-ENUMERACE: odpověď je VŽDY stejná neutrální 200 („Pokud je e-mail registrovaný, poslali jsme odkaz.\") — neregistrovaný e-mail nevyvolá žádný e-mail ani zápis, nelze rozlišit od registrovaného. Raw token jde JEN do e-mailu (v DB pouze sha256 hash, 15min TTL, single-use). Není MCP tool.","tags":["owner-auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"E-mail vlastníka (normalizuje se trim+lowercase)"}},"required":["email"]}}}},"responses":{"200":{"description":"Neutrální potvrzení (nezávisle na existenci vlastníka)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"string"}},"required":["ok","message"]}}}}}}},"/auth/owner/verify":{"get":{"operationId":"owner_auth_verify","summary":"Ověřit magic-link a získat owner-session","description":"Ověří raw token z e-mailu. Úspěch → nastaví podepsanou `Set-Cookie: pb_owner` (HttpOnly, SameSite=Lax, Secure za HTTPS) a vrátí HTML „přihlášen\". Token je single-use + TTL vynucené atomicky v DB → 2. verify / expirovaný / neznámý token → 400 HTML (bez leaku proč). Identita v cookie vzniká VÝHRADNĚ z reálného ověření (HMAC podpis own_id doménově odděleným klíčem — host pb_host cookie sem neprojde). Není MCP tool.","tags":["owner-auth"],"parameters":[{"name":"t","in":"query","required":true,"schema":{"type":"string"},"description":"Raw magic-link token (64 hex z e-mailu)"}],"responses":{"200":{"description":"Přihlášeno — Set-Cookie pb_owner + HTML potvrzení","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Neplatný / použitý / expirovaný token — HTML, žádná cookie","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/auth/owner/whoami":{"get":{"operationId":"owner_auth_whoami","summary":"Aktuální owner identita z pb_owner cookie","description":"Vrátí `{ authenticated, owner? }` odvozené VÝHRADNĚ z reálného HMAC ověření `pb_owner` cookie + DB řádku vlastníka. Bez/neplatná/manipulovaná/expirovaná cookie → `{ authenticated:false }`. Cross-audience: host `pb_host` cookie sem NEprojde (oddělený podpisový klíč). §14-testovatelný konzument primitivu. Není MCP tool.","tags":["owner-auth"],"responses":{"200":{"description":"Stav owner-session","content":{"application/json":{"schema":{"type":"object","properties":{"authenticated":{"type":"boolean"},"owner":{"type":"object","properties":{"owner_id":{"type":"string","description":"public_id vlastníka (own_xxx)"},"email":{"type":"string","format":"email"}},"required":["owner_id","email"]}},"required":["authenticated"]}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Deterministický kód chyby (QUOTE_EXPIRED, DATES_UNAVAILABLE, …)"},"message":{"type":"string"},"details":{}},"required":["code","message"]}}}},"securitySchemes":{"AdminToken":{"type":"apiKey","in":"header","name":"X-Admin-Token","description":"Interní admin shared-secret (I17a). Alternativně Authorization: Bearer <token>."},"OwnerSession":{"type":"apiKey","in":"cookie","name":"pb_owner","description":"Podepsaná owner-session cookie (pb_owner) z magic-link přihlášení vlastníka (I18a). Property-CRUD router (I18b), nested pricing/availability routery — surcharges/occupancy-pricing/los-discounts/calendar-blocks/ical-sources (I18c-1) — i nested PII/regulační routery — photos/tourist-tax/tourist-tax-report/guest-book/ubyport (I18c-2) — i owner-scope billing usage / messaging vlákno+rollup / check-in evidence / potvrzení zálohy (I18c-3) — ji vyžadují a musí patřit vlastníkovi v cestě (:ownerId). Host cesty (/api/bookings/{bookingPub}/…) ji NEmají — patří host-session."}}}}