{"openapi":"3.1.0","info":{"title":"Stay n Host API","version":"1.0.0","description":"The Stay n Host REST API (v1). Resource-oriented, versioned, session-gated. The same contract feeds the web app and future native/partner clients. The tenant is always the signed session claim — never a request parameter."},"tags":[{"name":"properties","description":"Property resource (create/read/update/archive)."},{"name":"listing-types","description":"Listing-type taxonomy resource (create/read/update/archive)."},{"name":"listings","description":"Listing (sellable unit) resource (create/read/update/archive/availability)."}],"paths":{"/api/v1/agents/rules":{"get":{"operationId":"listAgentRules","summary":"Every configured automation, workspace defaults first.","tags":["agents"],"responses":{"200":{"description":"Every configured automation, workspace defaults first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRuleList"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertAgentRule","summary":"Configure one automation. Insert-or-update on (kind, property).","tags":["agents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["guest.booking-confirmed","guest.lock-code-pre-checkin","guest.post-checkout","guest.unpaid-quote-reminder","reception.daily-arrivals","reception.instant-arrival","ops.daily-report","guest.ai-autopilot"]},"propertyIds":{"minItems":1,"maxItems":200,"type":"array","items":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"enabled":{"type":"boolean"},"channels":{"minItems":1,"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}},"sendAtLocal":{"anyOf":[{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},{"type":"null"}]},"leadMinutes":{"anyOf":[{"type":"integer","minimum":0,"maximum":1440},{"type":"null"}]},"recipients":{"maxItems":20,"type":"array","items":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"variants":{"anyOf":[{"minItems":1,"type":"array","items":{"type":"string","enum":["minimal","detailed"]}},{"type":"null"}]},"conditions":{"$ref":"#/components/schemas/AgentConditions"}},"required":["kind","propertyIds","enabled","channels"],"additionalProperties":false}}}},"responses":{"200":{"description":"Configure one automation. Insert-or-update on (kind, property).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRuleUpserted"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agents/catalog":{"get":{"operationId":"readAgentAuthoringCatalog","summary":"The triggers, audiences and starter packs an automation can be composed from.","tags":["agents"],"responses":{"200":{"description":"The triggers, audiences and starter packs an automation can be composed from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentAuthoringCatalog"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agents/authored":{"post":{"operationId":"createAuthoredAgentRule","summary":"Write a new automation: pick a trigger, an audience, and one or more messages.","tags":["agents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120},"triggerKey":{"type":"string","enum":["booking-confirmed","before-check-in","during-stay","before-check-out","after-check-out"]},"audience":{"type":"string","enum":["guest","fixed-recipients"]},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"enabled":{"type":"boolean"},"channels":{"minItems":1,"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}},"recipients":{"maxItems":20,"type":"array","items":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"conditions":{"$ref":"#/components/schemas/AgentConditions"},"messages":{"minItems":1,"maxItems":12,"type":"array","items":{"type":"object","properties":{"offsetMinutes":{"type":"integer","minimum":0,"maximum":43200},"channels":{"minItems":1,"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}},"enabled":{"type":"boolean"},"conditions":{"$ref":"#/components/schemas/AgentConditions"},"templateId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1,"maxLength":120},"body":{"type":"string","minLength":1,"maxLength":4000}},"required":["offsetMinutes","channels"],"additionalProperties":false}}},"required":["title","triggerKey","audience","channels","messages"],"additionalProperties":false}}}},"responses":{"201":{"description":"Write a new automation: pick a trigger, an audience, and one or more messages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentAuthoredRuleCreated"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agents/authored/{id}":{"patch":{"operationId":"updateAuthoredAgentRule","summary":"Edit one authored automation. Trigger and audience are fixed at creation.","tags":["agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120},"enabled":{"type":"boolean"},"channels":{"minItems":1,"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}},"recipients":{"maxItems":20,"type":"array","items":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"conditions":{"$ref":"#/components/schemas/AgentConditions"},"messages":{"minItems":1,"maxItems":12,"type":"array","items":{"type":"object","properties":{"offsetMinutes":{"type":"integer","minimum":0,"maximum":43200},"channels":{"minItems":1,"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}},"enabled":{"type":"boolean"},"conditions":{"$ref":"#/components/schemas/AgentConditions"},"templateId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1,"maxLength":120},"body":{"type":"string","minLength":1,"maxLength":4000}},"required":["offsetMinutes","channels"],"additionalProperties":false}}},"additionalProperties":false}}}},"responses":{"200":{"description":"Edit one authored automation. Trigger and audience are fixed at creation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentAuthoredRuleId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteAuthoredAgentRule","summary":"Retire one authored automation. Soft, so its run history stays readable.","tags":["agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Retire one authored automation. Soft, so its run history stays readable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentAuthoredRuleId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agents/packs":{"post":{"operationId":"installAgentStarterPack","summary":"Install a starter pack. Every automation it writes arrives DISABLED.","tags":["agents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"packKey":{"type":"string","minLength":1,"maxLength":64}},"required":["packKey"],"additionalProperties":false}}}},"responses":{"201":{"description":"Install a starter pack. Every automation it writes arrives DISABLED.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentStarterPackInstalled"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agents/runs":{"get":{"operationId":"listAgentRuns","summary":"Run history — what fired, when and to whom. Newest first.","tags":["agents"],"parameters":[{"in":"query","name":"ruleId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Run history — what fired, when and to whom. Newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunList"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agents/runs/{id}/resend":{"post":{"operationId":"resendAgentRun","summary":"Send one delivered run again. The worker re-renders it for the same booking from today's facts; never the door code.","tags":["agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Send one delivered run again. The worker re-renders it for the same booking from today's facts; never the door code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResend"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agents/authored/{id}/test":{"post":{"operationId":"testSendAuthoredRule","summary":"Email the automation's messages, as previewed against the sample stay, to the caller's own address. Never a guest, never the door code.","tags":["agents"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Email the automation's messages, as previewed against the sample stay, to the caller's own address. Never a guest, never the door code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthoredRuleTestSend"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/approvals":{"get":{"operationId":"listApprovalTasks","summary":"The tenant human-approval queue. Pending first, oldest first.","tags":["approvals"],"parameters":[{"in":"query","name":"status","schema":{"type":"string","enum":["pending","approved","rejected","cancelled","all"]}}],"responses":{"200":{"description":"The tenant human-approval queue. Pending first, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalTaskList"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/approvals/{id}/decide":{"post":{"operationId":"decideApprovalTask","summary":"Approve or reject a pending task. Human-gated; the decider may not be the requester.","tags":["approvals"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","reject"]},"note":{"type":"string","maxLength":500}},"required":["decision"],"additionalProperties":false}}}},"responses":{"200":{"description":"Approve or reject a pending task. Human-gated; the decider may not be the requester.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalDecision"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/approval-policy":{"get":{"operationId":"getApprovalPolicy","summary":"Which flows in this workspace park an approval step before taking effect.","tags":["approval-policy"],"responses":{"200":{"description":"Which flows in this workspace park an approval step before taking effect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalPolicy"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setApprovalPolicy","summary":"Turn the approval gate on quotation links on or off.","tags":["approval-policy"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"quoteShareApprovalRequired":{"type":"boolean"}},"required":["quoteShareApprovalRequired"],"additionalProperties":false}}}},"responses":{"200":{"description":"Turn the approval gate on quotation links on or off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalPolicy"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/notifications":{"get":{"operationId":"listNotifications","summary":"List the asking seat's notifications, newest first, with a keyset cursor.","tags":["notifications"],"parameters":[{"in":"query","name":"filter","schema":{"type":"string","enum":["all","unread"]}},{"in":"query","name":"category","schema":{"type":"string","enum":["bookings","guests","housekeeping","finance","channels","system"]}},{"in":"query","name":"cursor","schema":{"description":"Opaque keyset cursor from a previous page.","type":"string","maxLength":100},"description":"Opaque keyset cursor from a previous page."},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"List the asking seat's notifications, newest first, with a keyset cursor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationListResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/docs-assistant/ask":{"post":{"operationId":"askDocs","summary":"Answer an operator question from the public help centre, with citations.","tags":["docs-assistant"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskDocsBody"}}}},"responses":{"200":{"description":"Answer an operator question from the public help centre, with citations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskDocsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/notifications/unread-count":{"get":{"operationId":"getUnreadNotificationCount","summary":"The badge count — unread rows whose severity the seat has configured to count.","tags":["notifications"],"responses":{"200":{"description":"The badge count — unread rows whose severity the seat has configured to count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnreadCountResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/notifications/{id}/read":{"post":{"operationId":"markNotificationRead","summary":"Mark one of the asking seat's notifications read (idempotent).","tags":["notifications"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Mark one of the asking seat's notifications read (idempotent).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkNotificationReadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/notifications/read-all":{"post":{"operationId":"markAllNotificationsRead","summary":"Mark read up to an instant the client actually displayed (never unseen arrivals).","tags":["notifications"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkAllNotificationsReadBody"}}}},"responses":{"200":{"description":"Mark read up to an instant the client actually displayed (never unseen arrivals).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkAllNotificationsReadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/notifications/preferences":{"get":{"operationId":"getNotificationPreferences","summary":"The effective config plus both raw layers (seat override / workspace default).","tags":["notifications"],"responses":{"200":{"description":"The effective config plus both raw layers (seat override / workspace default).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setNotificationPreferences","summary":"Upsert the seat override (notification:view) or the workspace default (notification:configure).","tags":["notifications"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetNotificationPreferenceBody"}}}},"responses":{"200":{"description":"Upsert the seat override (notification:view) or the workspace default (notification:configure).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetNotificationPreferenceResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties":{"get":{"operationId":"listProperties","summary":"List the tenant's properties (keyset-paginated).","tags":["properties"],"parameters":[{"in":"query","name":"includeArchived","schema":{"description":"Include soft-deleted (archived) properties.","example":false,"type":"boolean"},"description":"Include soft-deleted (archived) properties."},{"in":"query","name":"cursor","schema":{"description":"Keyset cursor — the last id of the previous page.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Keyset cursor — the last id of the previous page."},{"in":"query","name":"search","schema":{"description":"Free-text search across every property: name or code. Matched as a literal substring, case-insensitively.","type":"string","minLength":1,"maxLength":100},"description":"Free-text search across every property: name or code. Matched as a literal substring, case-insensitively."},{"in":"query","name":"limit","schema":{"description":"Page size (server-clamped to [1, 100]; default 50).","example":50,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"description":"Page size (server-clamped to [1, 100]; default 50)."}],"responses":{"200":{"description":"List the tenant's properties (keyset-paginated).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPropertiesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createProperty","summary":"Create a property (id is server-minted).","tags":["properties"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePropertyBody"}}}},"responses":{"201":{"description":"Create a property (id is server-minted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/assignable-managers":{"get":{"operationId":"listAssignableManagers","summary":"List the tenant's active memberships assignable as a property manager.","tags":["properties"],"responses":{"200":{"description":"List the tenant's active memberships assignable as a property manager.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignableManagersResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/quick-add":{"post":{"operationId":"quickAddProperty","summary":"Add a property, a unit type, its units and their nightly rate in one step.","tags":["properties"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickAddPropertyBody"}}}},"responses":{"201":{"description":"Add a property, a unit type, its units and their nightly rate in one step.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickAddPropertyResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}":{"get":{"operationId":"getProperty","summary":"Get a single property by id.","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Get a single property by id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"editProperty","summary":"Patch a property (partial update; code is editable — re-validated + uniqueness-checked).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditPropertyBody"}}}},"responses":{"200":{"description":"Patch a property (partial update; code is editable — re-validated + uniqueness-checked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"archiveProperty","summary":"Archive (soft-delete) a property; returns the archived view.","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Archive (soft-delete) a property; returns the archived view.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/restore":{"post":{"operationId":"restoreProperty","summary":"Restore (un-archive) a soft-deleted property; returns the live view.","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Restore (un-archive) a soft-deleted property; returns the live view.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/permanent":{"delete":{"operationId":"deletePropertyPermanent","summary":"Permanently (hard) delete a property + its owned media; returns the removed id.","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Permanently (hard) delete a property + its owned media; returns the removed id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/photos":{"get":{"operationId":"listPropertyPhotos","summary":"List a property's photos (with short-lived presigned GET urls).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"responses":{"200":{"description":"List a property's photos (with short-lived presigned GET urls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPropertyPhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"requestPhotoUpload","summary":"Request a presigned PUT for a new property photo (id + key are server-minted).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestPhotoUploadBody"}}}},"responses":{"201":{"description":"Request a presigned PUT for a new property photo (id + key are server-minted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/photos/{photoId}":{"post":{"operationId":"confirmPhotoUpload","summary":"Confirm a pending photo upload (HEADs the object → ready).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmPhotoUploadBody"}}}},"responses":{"200":{"description":"Confirm a pending photo upload (HEADs the object → ready).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"reorderPhoto","summary":"Set-lead or reorder a property photo (position write; lead = MIN position).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderPhotoBody"}}}},"responses":{"200":{"description":"Set-lead or reorder a property photo (position write; lead = MIN position).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPropertyPhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removePhoto","summary":"Remove a property photo (delete the object + soft-delete the row).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"responses":{"200":{"description":"Remove a property photo (delete the object + soft-delete the row).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPropertyPhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/whatsapp-connection":{"get":{"operationId":"getWhatsAppConnection","summary":"The tenant's WhatsApp connection; credentials masked to presence + last4.","tags":["whatsapp-connection"],"responses":{"200":{"description":"The tenant's WhatsApp connection; credentials masked to presence + last4.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppConnectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setWhatsAppConnection","summary":"Create or update the tenant's WhatsApp connection; omitted credentials are kept.","tags":["whatsapp-connection"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetWhatsAppConnectionBody"}}}},"responses":{"200":{"description":"Create or update the tenant's WhatsApp connection; omitted credentials are kept.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppConnectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"disconnectWhatsApp","summary":"Disconnect WhatsApp for this tenant (frees the number for re-use).","tags":["whatsapp-connection"],"responses":{"200":{"description":"Disconnect WhatsApp for this tenant (frees the number for re-use).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppConnectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/content":{"get":{"operationId":"getPropertyContent","summary":"Read a property's content & policies facet.","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"responses":{"200":{"description":"Read a property's content & policies facet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyContentView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setPropertyContent","summary":"Replace a property's content & policies card (whole-object; null clears).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPropertyContentBody"}}}},"responses":{"200":{"description":"Replace a property's content & policies card (whole-object; null clears).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyContentView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/content":{"get":{"operationId":"getListingContent","summary":"Read a listing's content facet (guest-facing description).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"responses":{"200":{"description":"Read a listing's content facet (guest-facing description).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingContentView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setListingContent","summary":"Replace a listing's content card (whole-object; null clears).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetListingContentBody"}}}},"responses":{"200":{"description":"Replace a listing's content card (whole-object; null clears).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingContentView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/refund-policy":{"get":{"operationId":"getPropertyRefundPolicy","summary":"Read a property's cancellation & refund policy.","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"responses":{"200":{"description":"Read a property's cancellation & refund policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyRefundPolicyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setPropertyRefundPolicy","summary":"Replace a property's cancellation & refund policy (whole-object; the ladder is replaced whole).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPropertyRefundPolicyBody"}}}},"responses":{"200":{"description":"Replace a property's cancellation & refund policy (whole-object; the ladder is replaced whole).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyRefundPolicyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/quotation":{"get":{"operationId":"getPropertyQuotation","summary":"Read a property's quotation boilerplate (terms & footer).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"responses":{"200":{"description":"Read a property's quotation boilerplate (terms & footer).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyQuotationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setPropertyQuotation","summary":"Replace a property's quotation boilerplate (whole-object; null clears).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPropertyQuotationBody"}}}},"responses":{"200":{"description":"Replace a property's quotation boilerplate (whole-object; null clears).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyQuotationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/cleaning-rules":{"get":{"operationId":"getPropertyCleaningRules","summary":"Read a property's cleaning rules (stayover and deep clean; 0441).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"responses":{"200":{"description":"Read a property's cleaning rules (stayover and deep clean; 0441).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningRulesView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setPropertyCleaningRules","summary":"Replace a property's cleaning rules (whole-object; null switches a rule off).","tags":["properties"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id (UUID)."},"required":true,"description":"The parent property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCleaningRulesBody"}}}},"responses":{"200":{"description":"Replace a property's cleaning rules (whole-object; null switches a rule off).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningRulesView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types":{"get":{"operationId":"listListingTypes","summary":"List the tenant's listing types (keyset-paginated).","tags":["listing-types"],"parameters":[{"in":"query","name":"includeArchived","schema":{"description":"Include soft-deleted (archived) listing_types.","example":false,"type":"boolean"},"description":"Include soft-deleted (archived) listing_types."},{"in":"query","name":"cursor","schema":{"description":"Keyset cursor — the last id of the previous page.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Keyset cursor — the last id of the previous page."},{"in":"query","name":"limit","schema":{"description":"Page size (server-clamped to [1, 100]; default 50).","example":50,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"description":"Page size (server-clamped to [1, 100]; default 50)."},{"in":"query","name":"propertyId","schema":{"description":"Narrow to a property's reachable types (its own + legacy tenant-wide). Omit for the full tenant list.","example":"22222222-2222-4222-8222-222222222222","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Narrow to a property's reachable types (its own + legacy tenant-wide). Omit for the full tenant list."}],"responses":{"200":{"description":"List the tenant's listing types (keyset-paginated).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingTypesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createListingType","summary":"Create a listing type (id is server-minted).","tags":["listing-types"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateListingTypeBody"}}}},"responses":{"201":{"description":"Create a listing type (id is server-minted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTypeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types/{id}":{"get":{"operationId":"getListingType","summary":"Get a single listing type by id.","tags":["listing-types"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_type id (UUID).","example":"22222222-2222-4222-8222-222222222222"},"required":true,"description":"The listing_type id (UUID)."}],"responses":{"200":{"description":"Get a single listing type by id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTypeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"editListingType","summary":"Patch a listing type (partial update; key is immutable).","tags":["listing-types"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_type id (UUID).","example":"22222222-2222-4222-8222-222222222222"},"required":true,"description":"The listing_type id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditListingTypeBody"}}}},"responses":{"200":{"description":"Patch a listing type (partial update; key is immutable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTypeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"archiveListingType","summary":"Archive (soft-delete) a listing type; returns the archived view.","tags":["listing-types"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_type id (UUID).","example":"22222222-2222-4222-8222-222222222222"},"required":true,"description":"The listing_type id (UUID)."}],"responses":{"200":{"description":"Archive (soft-delete) a listing type; returns the archived view.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTypeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types/{id}/capacity":{"get":{"operationId":"getListingTypeCapacity","summary":"C9 — the capacity + stay-defaults card behind the OTA room type.","tags":["listing-types"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_type id (UUID).","example":"22222222-2222-4222-8222-222222222222"},"required":true,"description":"The listing_type id (UUID)."}],"responses":{"200":{"description":"C9 — the capacity + stay-defaults card behind the OTA room type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTypeCapacityView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setListingTypeCapacity","summary":"C9 — set the capacity + stay defaults (validated; reaches the OTA on re-sync/sweep).","tags":["listing-types"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_type id (UUID).","example":"22222222-2222-4222-8222-222222222222"},"required":true,"description":"The listing_type id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetListingTypeCapacityBody"}}}},"responses":{"200":{"description":"C9 — set the capacity + stay defaults (validated; reaches the OTA on re-sync/sweep).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTypeCapacityView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types/{id}/restore":{"post":{"operationId":"restoreListingType","summary":"Restore (un-archive) a soft-deleted listing type; returns the live view.","tags":["listing-types"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_type id (UUID).","example":"22222222-2222-4222-8222-222222222222"},"required":true,"description":"The listing_type id (UUID)."}],"responses":{"200":{"description":"Restore (un-archive) a soft-deleted listing type; returns the live view.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingTypeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings":{"get":{"operationId":"listListings","summary":"List the tenant's listings (keyset-paginated; property/type filters).","tags":["listings"],"parameters":[{"in":"query","name":"includeArchived","schema":{"description":"Include soft-deleted (archived) listings.","example":false,"type":"boolean"},"description":"Include soft-deleted (archived) listings."},{"in":"query","name":"propertyId","schema":{"description":"Filter to listings under this property.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Filter to listings under this property."},{"in":"query","name":"listingTypeId","schema":{"description":"Filter to listings of this type.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Filter to listings of this type."},{"in":"query","name":"cursor","schema":{"description":"Keyset cursor — the last id of the previous page.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Keyset cursor — the last id of the previous page."},{"in":"query","name":"limit","schema":{"description":"Page size (server-clamped to [1, 100]; default 50).","example":50,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"description":"Page size (server-clamped to [1, 100]; default 50)."},{"in":"query","name":"search","schema":{"description":"Free-text search (case-insensitive) across the listing code + its property name/code + type name.","example":"Marina","type":"string","maxLength":200},"description":"Free-text search (case-insensitive) across the listing code + its property name/code + type name."},{"in":"query","name":"minBedrooms","schema":{"description":"Only listings with AT LEAST this many bedrooms (0/absent = any).","example":2,"type":"integer","minimum":0,"maximum":50},"description":"Only listings with AT LEAST this many bedrooms (0/absent = any)."},{"in":"query","name":"minBeds","schema":{"description":"Only listings with AT LEAST this many beds (0/absent = any).","type":"integer","minimum":0,"maximum":50},"description":"Only listings with AT LEAST this many beds (0/absent = any)."},{"in":"query","name":"minBathrooms","schema":{"description":"Only listings with AT LEAST this many bathrooms (0/absent = any).","type":"integer","minimum":0,"maximum":50},"description":"Only listings with AT LEAST this many bathrooms (0/absent = any)."},{"in":"query","name":"amenities","schema":{"description":"CSV of canonical amenity keys the listing must have ALL of (e.g. `wifi,pool`; blank = any).","example":"wifi,pool","type":"string","maxLength":500},"description":"CSV of canonical amenity keys the listing must have ALL of (e.g. `wifi,pool`; blank = any)."}],"responses":{"200":{"description":"List the tenant's listings (keyset-paginated; property/type filters).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createListing","summary":"Create a listing (id is server-minted).","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateListingBody"}}}},"responses":{"201":{"description":"Create a listing (id is server-minted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/availability":{"get":{"operationId":"listingAvailability","summary":"Type-first availability for a stay window (per-listing-type free-counts).","tags":["listings"],"parameters":[{"in":"query","name":"checkIn","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Stay check-in date (YYYY-MM-DD).","example":"2026-07-01"},"required":true,"description":"Stay check-in date (YYYY-MM-DD)."},{"in":"query","name":"checkOut","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Stay check-out date (YYYY-MM-DD; exclusive — checkout night free).","example":"2026-07-04"},"required":true,"description":"Stay check-out date (YYYY-MM-DD; exclusive — checkout night free)."},{"in":"query","name":"propertyId","schema":{"description":"Optional: scope availability to a single property.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Optional: scope availability to a single property."}],"responses":{"200":{"description":"Type-first availability for a stay window (per-listing-type free-counts).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingAvailabilityResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}":{"get":{"operationId":"getListing","summary":"Get a single listing by id.","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"responses":{"200":{"description":"Get a single listing by id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"editListing","summary":"Patch a listing (partial update; listing_code is editable — uniqueness-checked).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditListingBody"}}}},"responses":{"200":{"description":"Patch a listing (partial update; listing_code is editable — uniqueness-checked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"archiveListing","summary":"Archive (soft-delete) a listing; returns the archived view.","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"responses":{"200":{"description":"Archive (soft-delete) a listing; returns the archived view.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/occupancy":{"get":{"operationId":"getListingOccupancy","summary":"The unit occupancy overrides + the type defaults + the resolved values.","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"responses":{"200":{"description":"The unit occupancy overrides + the type defaults + the resolved values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingOccupancyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setListingOccupancy","summary":"Replace the unit occupancy overrides (null = inherit from the listing type).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetListingOccupancyBody"}}}},"responses":{"200":{"description":"Replace the unit occupancy overrides (null = inherit from the listing type).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingOccupancyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/restore":{"post":{"operationId":"restoreListing","summary":"Restore (un-archive) a soft-deleted listing; returns the live view.","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"responses":{"200":{"description":"Restore (un-archive) a soft-deleted listing; returns the live view.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/permanent":{"delete":{"operationId":"deleteListingPermanent","summary":"Permanently (hard) delete a listing + its owned media; returns the removed id.","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"responses":{"200":{"description":"Permanently (hard) delete a listing + its owned media; returns the removed id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/ical-token":{"post":{"operationId":"rotateIcalToken","summary":"Rotate the listing's iCal feed URL (the previous URL 404s immediately).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id (UUID).","example":"33333333-3333-4333-8333-333333333333"},"required":true,"description":"The listing id (UUID)."}],"responses":{"200":{"description":"Rotate the listing's iCal feed URL (the previous URL 404s immediately).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateIcalTokenResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/photos":{"get":{"operationId":"listListingPhotos","summary":"List a listing's photos (with short-lived presigned GET urls).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."}],"responses":{"200":{"description":"List a listing's photos (with short-lived presigned GET urls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingPhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"requestListingPhotoUpload","summary":"Request a presigned PUT for a new listing photo (id + key are server-minted).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestListingPhotoUploadBody"}}}},"responses":{"201":{"description":"Request a presigned PUT for a new listing photo (id + key are server-minted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestListingPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/photos/{photoId}":{"post":{"operationId":"confirmListingPhotoUpload","summary":"Confirm a pending photo upload (HEADs the object → ready).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmListingPhotoUploadBody"}}}},"responses":{"200":{"description":"Confirm a pending photo upload (HEADs the object → ready).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmListingPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"reorderListingPhoto","summary":"Set-lead or reorder a listing photo (position write; lead = MIN position).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderListingPhotoBody"}}}},"responses":{"200":{"description":"Set-lead or reorder a listing photo (position write; lead = MIN position).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingPhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeListingPhoto","summary":"Remove a listing photo (delete the object + soft-delete the row).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"responses":{"200":{"description":"Remove a listing photo (delete the object + soft-delete the row).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingPhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/photo-derivatives":{"post":{"operationId":"backfillPhotoDerivatives","summary":"Generate the missing resized copies (thumb/card/full) for photos that have none. Bounded per call; repeat until `remaining` is 0.","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackfillPhotoDerivativesBody"}}}},"responses":{"200":{"description":"Generate the missing resized copies (thumb/card/full) for photos that have none. Bounded per call; repeat until `remaining` is 0.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackfillPhotoDerivativesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/photo-derivatives/reconcile":{"post":{"operationId":"reconcilePhotoDerivatives","summary":"Check that every recorded derivative is really in the store, and narrow the record where it is not. Bounded per call; repeat while `nextCursor` is non-null.","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcilePhotoDerivativesBody"}}}},"responses":{"200":{"description":"Check that every recorded derivative is really in the store, and narrow the record where it is not. Bounded per call; repeat while `nextCursor` is non-null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcilePhotoDerivativesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/photos/{photoId}/category":{"patch":{"operationId":"setListingPhotoCategory","summary":"Move a listing photo into a gallery category (null = uncategorized).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetListingPhotoCategoryBody"}}}},"responses":{"200":{"description":"Move a listing photo into a gallery category (null = uncategorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingPhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-photo-categories":{"get":{"operationId":"listListingPhotoCategories","summary":"List the tenant's registered custom listing-photo categories.","tags":["listings"],"responses":{"200":{"description":"List the tenant's registered custom listing-photo categories.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingPhotoCategoriesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"registerListingPhotoCategory","summary":"Register a custom listing-photo category (the key is derived from the label).","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterListingPhotoCategoryBody"}}}},"responses":{"201":{"description":"Register a custom listing-photo category (the key is derived from the label).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingPhotoCategoryListItem"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-photo-categories/{categoryKey}":{"delete":{"operationId":"removeListingPhotoCategory","summary":"Remove a custom listing-photo category (photos in it fall back to uncategorized).","tags":["listings"],"parameters":[{"in":"path","name":"categoryKey","schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","description":"A gallery bucket key — a built-in (`living_room`) or one of the tenant's registered custom keys.","example":"main_hero_shots"},"required":true,"description":"A gallery bucket key — a built-in (`living_room`) or one of the tenant's registered custom keys."}],"responses":{"200":{"description":"Remove a custom listing-photo category (photos in it fall back to uncategorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingPhotoCategoriesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types/{id}/photos":{"get":{"operationId":"listListingTypePhotos","summary":"List a listing type's photos (with short-lived presigned GET urls).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing-type id (UUID)."},"required":true,"description":"The parent listing-type id (UUID)."}],"responses":{"200":{"description":"List a listing type's photos (with short-lived presigned GET urls).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingTypePhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"requestListingTypePhotoUpload","summary":"Request a presigned PUT for a new listing-type photo (id + key are server-minted).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing-type id (UUID)."},"required":true,"description":"The parent listing-type id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestListingTypePhotoUploadBody"}}}},"responses":{"201":{"description":"Request a presigned PUT for a new listing-type photo (id + key are server-minted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestListingTypePhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types/{id}/photos/{photoId}":{"post":{"operationId":"confirmListingTypePhotoUpload","summary":"Confirm a pending photo upload (HEADs the object → ready).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing-type id (UUID)."},"required":true,"description":"The parent listing-type id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmListingTypePhotoUploadBody"}}}},"responses":{"200":{"description":"Confirm a pending photo upload (HEADs the object → ready).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmListingTypePhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"reorderListingTypePhoto","summary":"Set-lead or reorder a listing-type photo (position write; lead = MIN position).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing-type id (UUID)."},"required":true,"description":"The parent listing-type id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderListingTypePhotoBody"}}}},"responses":{"200":{"description":"Set-lead or reorder a listing-type photo (position write; lead = MIN position).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingTypePhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeListingTypePhoto","summary":"Remove a listing-type photo (delete the object + soft-delete the row).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing-type id (UUID)."},"required":true,"description":"The parent listing-type id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"responses":{"200":{"description":"Remove a listing-type photo (delete the object + soft-delete the row).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingTypePhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types/{id}/photos/push":{"post":{"operationId":"pushListingTypePhotos","summary":"Replace every unit of this type's photos with the type's set.","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing-type id (UUID)."},"required":true,"description":"The parent listing-type id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushListingTypePhotosBody"}}}},"responses":{"200":{"description":"Replace every unit of this type's photos with the type's set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushListingTypePhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-types/{id}/photos/{photoId}/category":{"patch":{"operationId":"setListingTypePhotoCategory","summary":"Move a listing-type photo into a gallery category (null = uncategorized).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing-type id (UUID)."},"required":true,"description":"The parent listing-type id (UUID)."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id (UUID)."},"required":true,"description":"The photo id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetListingTypePhotoCategoryBody"}}}},"responses":{"200":{"description":"Move a listing-type photo into a gallery category (null = uncategorized).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingTypePhotosResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/channel-links":{"get":{"operationId":"listListingChannelLinks","summary":"List a listing's external channel links (ordered).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."}],"responses":{"200":{"description":"List a listing's external channel links (ordered).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingChannelLinksResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setListingChannelLinks","summary":"Replace a listing’s external channel links with the given set (idempotent).","tags":["listings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent listing id (UUID)."},"required":true,"description":"The parent listing id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetListingChannelLinksBody"}}}},"responses":{"200":{"description":"Replace a listing’s external channel links with the given set (idempotent).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListListingChannelLinksResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries":{"get":{"operationId":"listInquiries","summary":"List booking-funnel inquiries (newest first) with their active 2h holds.","tags":["bookings"],"parameters":[{"in":"query","name":"status","schema":{"description":"Optional funnel-status filter.","type":"string","minLength":1,"maxLength":60},"description":"Optional funnel-status filter."},{"in":"query","name":"statuses","schema":{"description":"Comma-separated funnel statuses to restrict the page to (applied before the limit).","type":"string","minLength":1,"maxLength":400},"description":"Comma-separated funnel statuses to restrict the page to (applied before the limit)."},{"in":"query","name":"cursor","schema":{"description":"Keyset cursor — the last id of the previous page.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Keyset cursor — the last id of the previous page."},{"in":"query","name":"search","schema":{"description":"Free-text search across the whole funnel: reference code, guest name, property, listing type, or any unit’s listing code. Matched as a literal substring, case-insensitively.","type":"string","minLength":1,"maxLength":100},"description":"Free-text search across the whole funnel: reference code, guest name, property, listing type, or any unit’s listing code. Matched as a literal substring, case-insensitively."},{"in":"query","name":"limit","schema":{"description":"Page size (default 50, max 100).","type":"integer","minimum":1,"maximum":100},"description":"Page size (default 50, max 100)."}],"responses":{"200":{"description":"List booking-funnel inquiries (newest first) with their active 2h holds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInquiriesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createInquiry","summary":"Record a new stay inquiry (funnel step 1).","tags":["bookings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInquiryBody"}}}},"responses":{"201":{"description":"Record a new stay inquiry (funnel step 1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InquiryView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}":{"get":{"operationId":"getInquiry","summary":"Read one inquiry with its guest contact, quote breakdown, and active hold (0022).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Read one inquiry with its guest contact, quote breakdown, and active hold (0022).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetInquiryResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateInquiry","summary":"Edit an inquiry's stay window, party, unit selection, source and note. Revokes any live public quotation link.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateInquiryBody"}}}},"responses":{"200":{"description":"Edit an inquiry's stay window, party, unit selection, source and note. Revokes any live public quotation link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InquiryView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings). This operation returns: `inquiry_not_editable` when the inquiry is terminal, or has payment proof pending verification; `concurrent_update` when another edit or transition moved the row first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/quote":{"post":{"operationId":"quoteInquiry","summary":"Quote the stay (one manual whole-stay amount; funnel step 2).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteInquiryBody"}}}},"responses":{"200":{"description":"Quote the stay (one manual whole-stay amount; funnel step 2).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InquiryView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings). This operation returns: `inquiry_not_available` when the requested listing (or every listing of the requested type) is taken for at least one night of the stay — the attempt is recorded as an availability re-check and NO quote is written.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/promo-codes":{"post":{"operationId":"listInquiryPromoCodes","summary":"The ACTIVE direct-booking-site promo campaigns an operator may apply while quoting.","tags":["bookings"],"responses":{"200":{"description":"The ACTIVE direct-booking-site promo campaigns an operator may apply while quoting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInquiryPromoCodesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/quote-preview":{"post":{"operationId":"previewQuote","summary":"Preview the SUGGEST-only quote for stay legs (Σ per-night override ?? base rate).","tags":["bookings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotePreviewBody"}}}},"responses":{"200":{"description":"Preview the SUGGEST-only quote for stay legs (Σ per-night override ?? base rate).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotePreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/request-payment":{"post":{"operationId":"requestPayment","summary":"Mark the 100% advance as requested (funnel step 3).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Mark the 100% advance as requested (funnel step 3).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InquiryView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/reject":{"post":{"operationId":"rejectInquiry","summary":"Reject an inquiry by policy — the operator side-exit (→ rejected_by_policy).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Reject an inquiry by policy — the operator side-exit (→ rejected_by_policy).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InquiryView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/cancel-lock":{"post":{"operationId":"cancelLockedInquiry","summary":"Cancel a LOCKED inquiry: reject the claimed payment and release the held nights (→ rejected_by_policy).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Cancel a LOCKED inquiry: reject the claimed payment and release the held nights (→ rejected_by_policy).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelLockedInquiryResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/decline":{"post":{"operationId":"declineInquiry","summary":"Record a guest decline — the guest side-exit (→ cancelled_by_guest).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Record a guest decline — the guest side-exit (→ cancelled_by_guest).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InquiryView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/payment-proof":{"post":{"operationId":"submitPaymentProof","summary":"Record the payment proof and start the 2h listing lock (funnel step 4).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitPaymentProofBody"}}}},"responses":{"200":{"description":"Record the payment proof and start the 2h listing lock (funnel step 4).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InquiryView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/convert":{"post":{"operationId":"convertInquiryToBooking","summary":"Verify the payment + convert the locked inquiry into a confirmed booking (item #4).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertInquiryBody"}}}},"responses":{"201":{"description":"Verify the payment + convert the locked inquiry into a confirmed booking (item #4).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/complimentary":{"post":{"operationId":"confirmComplimentaryStay","summary":"Confirm a zero-total (complimentary) quote into a booking — no payment, no journal.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmComplimentaryBody"}}}},"responses":{"201":{"description":"Confirm a zero-total (complimentary) quote into a booking — no payment, no journal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings":{"get":{"operationId":"listBookings","summary":"List confirmed bookings (newest first) with guest + the verified-paid sum.","tags":["bookings"],"parameters":[{"in":"query","name":"status","schema":{"description":"Optional status filter.","type":"string","minLength":1,"maxLength":60},"description":"Optional status filter."},{"in":"query","name":"partition","schema":{"description":"One half of the book: `working` (upcoming + in-house, what /bookings shows) or `past` (ended or never happened, what /past-stays shows). Absent: every status.","type":"string","enum":["working","past"]},"description":"One half of the book: `working` (upcoming + in-house, what /bookings shows) or `past` (ended or never happened, what /past-stays shows). Absent: every status."},{"in":"query","name":"cursor","schema":{"description":"The `nextCursor` of the previous page: the id of its last row.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"The `nextCursor` of the previous page: the id of its last row."},{"in":"query","name":"search","schema":{"description":"Free-text search across the whole partition: reference code, booker name, or any apartment’s code, property name or channel reservation id. Matched as a literal substring, case-insensitively.","type":"string","minLength":1,"maxLength":100},"description":"Free-text search across the whole partition: reference code, booker name, or any apartment’s code, property name or channel reservation id. Matched as a literal substring, case-insensitively."},{"in":"query","name":"limit","schema":{"description":"Page size (default 50, max 100).","type":"integer","minimum":1,"maximum":100},"description":"Page size (default 50, max 100)."},{"in":"query","name":"view","schema":{"description":"A /today preset scoping every page of the list: `checkins-today` (arrival due today, not yet checked in), `in-house` (checked in, not checked out), `outstanding` (an unpaid balance on an upcoming or in-house stay), `overdue-checkouts` (checked in, check-out day passed), `overdue-checkins` (check-in day passed, never checked in).","type":"string","enum":["checkins-today","in-house","outstanding","overdue-checkouts","overdue-checkins"]},"description":"A /today preset scoping every page of the list: `checkins-today` (arrival due today, not yet checked in), `in-house` (checked in, not checked out), `outstanding` (an unpaid balance on an upcoming or in-house stay), `overdue-checkouts` (checked in, check-out day passed), `overdue-checkins` (check-in day passed, never checked in)."},{"in":"query","name":"today","schema":{"description":"The tenant-local date (YYYY-MM-DD) a `view` is evaluated on. Pass the date the first page was read on so every page stays in one set; absent, the tenant’s own clock decides.","example":"2026-07-10","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"description":"The tenant-local date (YYYY-MM-DD) a `view` is evaluated on. Pass the date the first page was read on so every page stays in one set; absent, the tenant’s own clock decides."}],"responses":{"200":{"description":"List confirmed bookings (newest first) with guest + the verified-paid sum.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBookingsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createDirectBooking","summary":"Create a source-trusted direct/imported booking (already-confirmed + already-paid).","tags":["bookings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDirectBookingBody"}}}},"responses":{"201":{"description":"Create a source-trusted direct/imported booking (already-confirmed + already-paid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/booking-groups":{"post":{"operationId":"createBookingGroup","summary":"Create a multi-listing group booking (one guest + one settled payment across ≥2 units).","tags":["bookings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGroupBookingBody"}}}},"responses":{"201":{"description":"Create a multi-listing group booking (one guest + one settled payment across ≥2 units).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupBookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}":{"get":{"operationId":"getBooking","summary":"Read one confirmed booking (the detail / lifecycle page).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"Read one confirmed booking (the detail / lifecycle page).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingDetailView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateBooking","summary":"Edit a confirmed booking's stay/unit/party/total (nights re-committed; pre-check-in only).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBookingBody"}}}},"responses":{"200":{"description":"Edit a confirmed booking's stay/unit/party/total (nights re-committed; pre-check-in only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/check-in":{"post":{"operationId":"checkInBooking","summary":"Check the guest in (mark arrived → checked_in).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckInBookingBody"}}}},"responses":{"200":{"description":"Check the guest in (mark arrived → checked_in).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/check-out":{"post":{"operationId":"checkOutBooking","summary":"Check the guest out (mark departed → checked_out).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckOutBookingBody"}}}},"responses":{"200":{"description":"Check the guest out (mark departed → checked_out).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/condition":{"get":{"operationId":"readBookingCondition","summary":"The stay's condition record: its media, both gate states, and the linked turnover evidence.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"The stay's condition record: its media, both gate states, and the linked turnover evidence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingConditionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/condition/media":{"post":{"operationId":"requestConditionMediaUpload","summary":"Mint a presigned PUT for one condition photo/video (two-phase; server-minted key).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestConditionMediaUploadBody"}}}},"responses":{"201":{"description":"Mint a presigned PUT for one condition photo/video (two-phase; server-minted key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestConditionMediaUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/condition/media/{mediaId}/confirm":{"post":{"operationId":"confirmConditionMediaUpload","summary":"HEAD-prove the uploaded object and flip pending → ready (only ready satisfies a gate).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."},{"in":"path","name":"mediaId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The condition-media id."},"required":true,"description":"The condition-media id."}],"responses":{"200":{"description":"HEAD-prove the uploaded object and flip pending → ready (only ready satisfies a gate).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmConditionMediaUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/condition/media/{mediaId}/view-url":{"get":{"operationId":"mintConditionMediaViewUrl","summary":"Mint a short-lived presigned GET for one ready item (C3 operational evidence).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."},{"in":"path","name":"mediaId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The condition-media id."},"required":true,"description":"The condition-media id."},{"in":"query","name":"download","schema":{"description":"Set to \"1\" to mint an attachment (download) URL instead of inline.","type":"string","enum":["1"]},"description":"Set to \"1\" to mint an attachment (download) URL instead of inline."}],"responses":{"200":{"description":"Mint a short-lived presigned GET for one ready item (C3 operational evidence).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintConditionMediaViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/condition/inherited/{photoId}/view-url":{"get":{"operationId":"mintInheritedHandoverViewUrl","summary":"Mint a short-lived presigned GET for one inherited handover photo.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inherited cleaning-photo id."},"required":true,"description":"The inherited cleaning-photo id."},{"in":"query","name":"download","schema":{"description":"Set to \"1\" to mint an attachment (download) URL instead of inline.","type":"string","enum":["1"]},"description":"Set to \"1\" to mint an attachment (download) URL instead of inline."}],"responses":{"200":{"description":"Mint a short-lived presigned GET for one inherited handover photo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintInheritedHandoverViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/condition/media/{mediaId}":{"patch":{"operationId":"annotateConditionMedia","summary":"Re-caption one item, or point it at a damage report on the same booking.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."},{"in":"path","name":"mediaId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The condition-media id."},"required":true,"description":"The condition-media id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnotateConditionMediaBody"}}}},"responses":{"200":{"description":"Re-caption one item, or point it at a damage report on the same booking.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnotateConditionMediaResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeConditionMedia","summary":"Remove one piece of condition evidence (soft delete; can re-close a gate).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."},{"in":"path","name":"mediaId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The condition-media id."},"required":true,"description":"The condition-media id."}],"responses":{"200":{"description":"Remove one piece of condition evidence (soft delete; can re-close a gate).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveConditionMediaResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/condition/damage":{"post":{"operationId":"openBookingDamageReport","summary":"Record a damage note on the stay (no inspection round required; posts no money). Accepts inspection:damage OR booking:check_out.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenBookingDamageBody"}}}},"responses":{"201":{"description":"Record a damage note on the stay (no inspection round required; posts no money). Accepts inspection:damage OR booking:check_out.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DamageReportView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/no-show":{"post":{"operationId":"markNoShowBooking","summary":"Mark a no-show (guest never arrived → no_show).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"Mark a no-show (guest never arrived → no_show).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/cancel":{"post":{"operationId":"cancelBooking","summary":"Cancel a pre-check-in booking (frees the booked nights; reason required).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBookingBody"}}}},"responses":{"200":{"description":"Cancel a pre-check-in booking (frees the booked nights; reason required).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBookingResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/refunds":{"post":{"operationId":"requestRefund","summary":"Request a refund on a cancelled/no-show booking (maker; ≤ verified − committed).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestRefundBody"}}}},"responses":{"201":{"description":"Request a refund on a cancelled/no-show booking (maker; ≤ verified − committed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listRefunds","summary":"The booking's refunds (oldest-first) + the paid/committed capacity numbers.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"The booking's refunds (oldest-first) + the paid/committed capacity numbers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRefundsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/refunds/{id}/decision":{"post":{"operationId":"decideRefund","summary":"Pay or reject a requested refund (checker; human-gated).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The refund id."},"required":true,"description":"The refund id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideRefundBody"}}}},"responses":{"200":{"description":"Pay or reject a requested refund (checker; human-gated).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/history":{"get":{"operationId":"getBookingHistory","summary":"The booking's full event timeline (funnel → confirm → edits), oldest-first.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"The booking's full event timeline (funnel → confirm → edits), oldest-first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingHistoryResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/version":{"get":{"operationId":"getBookingVersion","summary":"The booking record's freshness token: the newest audit row in its story.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"The booking record's freshness token: the newest audit row in its story.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingVersionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/guest-cash":{"post":{"operationId":"recordGuestCash","summary":"Record guest cash against a booking (mints the RCP receipt; parks for a 2nd approver when the tenant switch is on).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordGuestCashBody"}}}},"responses":{"201":{"description":"Record guest cash against a booking (mints the RCP receipt; parks for a 2nd approver when the tenant switch is on).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCashPaymentView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payments/{id}/guest-cash-approval":{"post":{"operationId":"approveGuestCash","summary":"Approve a parked guest-cash payment (account_manager; posts the balanced inflow journal).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The payment id."},"required":true,"description":"The payment id."}],"responses":{"200":{"description":"Approve a parked guest-cash payment (account_manager; posts the balanced inflow journal).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveGuestCashResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/guest-cash":{"get":{"operationId":"guestCashReport","summary":"The guest-cash receipt report (RCP receipts) over a date window — filterable by property, recorder, or status.","tags":["payments"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"recordedBy","schema":{"description":"Filter by the recorder membership.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Filter by the recorder membership."},{"in":"query","name":"status","schema":{"type":"string","enum":["verified","pending_verification"]}}],"responses":{"200":{"description":"The guest-cash receipt report (RCP receipts) over a date window — filterable by property, recorder, or status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCashReportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payment-attachments/upload":{"post":{"operationId":"requestPaymentAttachmentUpload","summary":"Mint a presigned PUT for a payment screenshot (guest proof / operator receipt).","tags":["payment-attachments"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentAttachmentUploadBody"}}}},"responses":{"201":{"description":"Mint a presigned PUT for a payment screenshot (guest proof / operator receipt).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentAttachmentUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payment-attachments":{"post":{"operationId":"attachPaymentScreenshot","summary":"Bind an uploaded screenshot to an existing payment (kind + object key → a ready row).","tags":["payment-attachments"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachPaymentScreenshotBody"}}}},"responses":{"201":{"description":"Bind an uploaded screenshot to an existing payment (kind + object key → a ready row).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachPaymentScreenshotResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payments/{id}/split-transfers":{"post":{"operationId":"splitPaymentIntoTransfers","summary":"Re-cut one proof_received payment into one payment per screenshot, with operator-stated amounts.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The payment id."},"required":true,"description":"The payment id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitPaymentTransfersBody"}}}},"responses":{"200":{"description":"Re-cut one proof_received payment into one payment per screenshot, with operator-stated amounts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitPaymentTransfersResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payments/stranded":{"get":{"operationId":"listStrandedPayments","summary":"Transfers left proof_received on an already-converted inquiry — read-only, with the agreed split each repair would restore.","tags":["payments"],"responses":{"200":{"description":"Transfers left proof_received on an already-converted inquiry — read-only, with the agreed split each repair would restore.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StrandedPaymentsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payments/{id}/repair-stranded":{"post":{"operationId":"repairStrandedPayment","summary":"Verify one stranded transfer onto its booking: post the missing inflow journal, allocate it, and restore the inquiry’s agreed advance.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The payment id."},"required":true,"description":"The payment id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepairStrandedPaymentBody"}}}},"responses":{"200":{"description":"Verify one stranded transfer onto its booking: post the missing inflow journal, allocate it, and restore the inquiry’s agreed advance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepairStrandedPaymentResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payment-attachments/{id}/view-url":{"get":{"operationId":"mintPaymentAttachmentViewUrl","summary":"A 300s signed GET for one READY payment screenshot.","tags":["payment-attachments"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The payment-attachment id."},"required":true,"description":"The payment-attachment id."}],"responses":{"200":{"description":"A 300s signed GET for one READY payment screenshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentAttachmentViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/payments":{"get":{"operationId":"listBookingPayments","summary":"Every payment of a booking, newest first, each with its ready screenshots (Payment tab).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"Every payment of a booking, newest first, each with its ready screenshots (Payment tab).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsWithAttachmentsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/payments":{"get":{"operationId":"listInquiryPayments","summary":"Every payment of an inquiry, newest first, each with its ready screenshots (Payment tab).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Every payment of an inquiry, newest first, each with its ready screenshots (Payment tab).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsWithAttachmentsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/verifications":{"get":{"operationId":"listVerifications","summary":"List every ID verification (statuses, masked numbers, doc progress) — the queue.","tags":["bookings"],"responses":{"200":{"description":"List every ID verification (statuses, masked numbers, doc progress) — the queue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListVerificationsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/verifications/{verificationId}":{"get":{"operationId":"getVerificationDetail","summary":"Read one verification: state, booking context (Related), and the audit trail.","tags":["bookings"],"parameters":[{"in":"path","name":"verificationId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The verification id (UUID)."},"required":true,"description":"The verification id (UUID)."}],"responses":{"200":{"description":"Read one verification: state, booking context (Related), and the audit trail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/verifications/{verificationId}/share":{"post":{"operationId":"createVerificationShare","summary":"Mint (or return) the guest ID-upload link for this verification.","tags":["bookings"],"parameters":[{"in":"path","name":"verificationId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The verification id (UUID)."},"required":true,"description":"The verification id (UUID)."}],"responses":{"201":{"description":"Mint (or return) the guest ID-upload link for this verification.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationShareResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bank-accounts":{"get":{"operationId":"listBankAccounts","summary":"Every live bank account, with the properties assigned to each.","tags":["bank-accounts"],"responses":{"200":{"description":"Every live bank account, with the properties assigned to each.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountListResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createBankAccount","summary":"Create a bank account.","tags":["bank-accounts"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBankAccountBody"}}}},"responses":{"201":{"description":"Create a bank account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bank-accounts/{id}":{"patch":{"operationId":"updateBankAccount","summary":"Rename or correct a bank account. Every property assigned to it prints the new text.","tags":["bank-accounts"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBankAccountBody"}}}},"responses":{"200":{"description":"Rename or correct a bank account. Every property assigned to it prints the new text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"archiveBankAccount","summary":"Archive a bank account. Refused while any property is still assigned to it.","tags":["bank-accounts"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Archive a bank account. Refused while any property is still assigned to it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveBankAccountResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bank-accounts/{id}/properties":{"post":{"operationId":"setBankAccountProperties","summary":"Replace the full set of properties this account serves.","tags":["bank-accounts"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetBankAccountPropertiesBody"}}}},"responses":{"200":{"description":"Replace the full set of properties this account serves.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAccountView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification":{"get":{"operationId":"getVerification","summary":"Read the booking's ID-verification state (masked number; document envelopes).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"responses":{"200":{"description":"Read the booking's ID-verification state (masked number; document envelopes).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVerificationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/request":{"post":{"operationId":"requestVerification","summary":"Ask the guest for ID documents (mints the verification; parks the booking behind the gate).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestVerificationBody"}}}},"responses":{"201":{"description":"Ask the guest for ID documents (mints the verification; parks the booking behind the gate).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/requirement":{"post":{"operationId":"setVerificationDocRequirement","summary":"Mark the doc requirement: passport (foreigner) or MRC (couple address mismatch).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDocRequirementBody"}}}},"responses":{"200":{"description":"Mark the doc requirement: passport (foreigner) or MRC (couple address mismatch).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/details":{"post":{"operationId":"recordVerificationDetails","summary":"Record the identity number + kind (write-only: responses carry the masked form).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordVerificationDetailsBody"}}}},"responses":{"200":{"description":"Record the identity number + kind (write-only: responses carry the masked form).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/documents":{"post":{"operationId":"requestVerificationDocUpload","summary":"Request a presigned PUT for one ID document (id + object key server-minted).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestVerificationDocUploadBody"}}}},"responses":{"201":{"description":"Request a presigned PUT for one ID document (id + object key server-minted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestVerificationDocUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/documents/{documentId}":{"post":{"operationId":"confirmVerificationDocUpload","summary":"Confirm an ID-document upload (HEAD-proved; fires docs-received on the first).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."},{"in":"path","name":"documentId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The verification document id (UUID)."},"required":true,"description":"The verification document id (UUID)."}],"responses":{"200":{"description":"Confirm an ID-document upload (HEAD-proved; fires docs-received on the first).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmVerificationDocUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/documents/{documentId}/view-url":{"post":{"operationId":"mintVerificationDocViewUrl","summary":"Mint a short-lived presigned GET for one ID image (C4; every mint audited).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."},{"in":"path","name":"documentId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The verification document id (UUID)."},"required":true,"description":"The verification document id (UUID)."}],"responses":{"200":{"description":"Mint a short-lived presigned GET for one ID image (C4; every mint audited).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintVerificationDocViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/approve":{"post":{"operationId":"approveVerification","summary":"Approve the docs (→ verified; unblocks the lock-code half of the dual gate).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationDecisionBody"}}}},"responses":{"200":{"description":"Approve the docs (→ verified; unblocks the lock-code half of the dual gate).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/reject":{"post":{"operationId":"rejectVerification","summary":"Reject the docs (terminal; blocks the lock-code path).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationDecisionBody"}}}},"responses":{"200":{"description":"Reject the docs (terminal; blocks the lock-code path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/revoke":{"post":{"operationId":"revokeVerification","summary":"Revoke a verified ID (human-only; reason mandatory; surfaces in the 12AM report).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeVerificationBody"}}}},"responses":{"200":{"description":"Revoke a verified ID (human-only; reason mandatory; surfaces in the 12AM report).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/delete":{"post":{"operationId":"deleteVerification","summary":"Soft-delete a per-guest ID check (a mistaken or duplicate add).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteVerificationBody"}}}},"responses":{"200":{"description":"Soft-delete a per-guest ID check (a mistaken or duplicate add).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteVerificationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/waive":{"post":{"operationId":"waiveBookingVerification","summary":"Waive ID verification — advance a parked booking to ready without a verified check.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaiveBookingVerificationBody"}}}},"responses":{"200":{"description":"Waive ID verification — advance a parked booking to ready without a verified check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaiveVerificationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/waive-guest":{"post":{"operationId":"waiveGuestVerification","summary":"Skip ONE guest’s ID check (→ waived); the booking readies when all are verified-or-waived.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaiveVerificationBody"}}}},"responses":{"200":{"description":"Skip ONE guest’s ID check (→ waived); the booking readies when all are verified-or-waived.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/verification/carry-forward":{"post":{"operationId":"carryForwardVerification","summary":"Carry a PRIOR verified check for the same guest onto this stay (→ verified; the door code releases).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id (UUID)."},"required":true,"description":"The booking id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CarryForwardVerificationBody"}}}},"responses":{"200":{"description":"Carry a PRIOR verified check for the same guest onto this stay (→ verified; the door code releases).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/calendar":{"get":{"operationId":"getCalendar","summary":"Read the master calendar window: stays, live 2h holds, blocks, prep spans.","tags":["calendar"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Window start date (inclusive), YYYY-MM-DD."},"required":true,"description":"Window start date (inclusive), YYYY-MM-DD."},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Window end date (EXCLUSIVE), YYYY-MM-DD."},"required":true,"description":"Window end date (EXCLUSIVE), YYYY-MM-DD."},{"in":"query","name":"propertyId","schema":{"description":"Scope the calendar to one property.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Scope the calendar to one property."}],"responses":{"200":{"description":"Read the master calendar window: stays, live 2h holds, blocks, prep spans.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-blocks":{"post":{"operationId":"createListingBlock","summary":"Withdraw a span of nights from sale (maintenance / owner use / renovation).","tags":["calendar"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateListingBlockBody"}}}},"responses":{"201":{"description":"Withdraw a span of nights from sale (maintenance / owner use / renovation).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBlockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listing-blocks/{id}":{"patch":{"operationId":"updateListingBlock","summary":"Move/relabel an availability block (the block's listing is immutable).","tags":["calendar"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_block id (UUID)."},"required":true,"description":"The listing_block id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateListingBlockBody"}}}},"responses":{"200":{"description":"Move/relabel an availability block (the block's listing is immutable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBlockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeListingBlock","summary":"Remove an availability block (soft-delete; the span returns to sale).","tags":["calendar"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_block id (UUID)."},"required":true,"description":"The listing_block id (UUID)."}],"responses":{"200":{"description":"Remove an availability block (soft-delete; the span returns to sale).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBlockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks":{"get":{"operationId":"listCleaningTasks","summary":"The cleaning queue (dispatchers: all tasks; cleaners: own tasks only).","tags":["housekeeping"],"responses":{"200":{"description":"The cleaning queue (dispatchers: all tasks; cleaners: own tasks only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCleaningTasksResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"assignCleaning","summary":"Dispatch a cleaner to a dirty unit (§1.6 dirty → cleaning_assigned; M8 urgent detect).","tags":["housekeeping"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignCleaningBody"}}}},"responses":{"201":{"description":"Dispatch a cleaner to a dirty unit (§1.6 dirty → cleaning_assigned; M8 urgent detect).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/scheduled":{"post":{"operationId":"scheduleCleaning","summary":"Plan a cleaning from the calendar (unassigned, carries the drawn window).","tags":["housekeeping"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleCleaningBody"}}}},"responses":{"201":{"description":"Plan a cleaning from the calendar (unassigned, carries the drawn window).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/start":{"post":{"operationId":"startCleaning","summary":"The cleaner starts the job (§1.6 cleaning_assigned → cleaning_in_progress).","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningStepBody"}}}},"responses":{"200":{"description":"The cleaner starts the job (§1.6 cleaning_assigned → cleaning_in_progress).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/complete":{"post":{"operationId":"completeCleaning","summary":"Mark cleaned (§1.6 cleaning_in_progress → inspection_pending; enqueues inspection). With markReady, or when the workspace does not require inspection, the round is cleared and the unit is ready.","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteCleaningBody"}}}},"responses":{"200":{"description":"Mark cleaned (§1.6 cleaning_in_progress → inspection_pending; enqueues inspection). With markReady, or when the workspace does not require inspection, the round is cleared and the unit is ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/reassign":{"post":{"operationId":"reassignCleaning","summary":"Hand the job to a new cleaner (M4 — the prior row closes; the chain continues).","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReassignCleaningBody"}}}},"responses":{"200":{"description":"Hand the job to a new cleaner (M4 — the prior row closes; the chain continues).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/plan-assignee":{"post":{"operationId":"assignPlannedCleaning","summary":"Name the cleaner on a PLANNED cleaning (FU-B). The plan stays a plan; nothing goes live.","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignPlannedCleaningBody"}}}},"responses":{"200":{"description":"Name the cleaner on a PLANNED cleaning (FU-B). The plan stays a plan; nothing goes live.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/dispatch":{"post":{"operationId":"dispatchPlannedCleaning","summary":"Dispatch a named PLAN to its cleaner, under dispatch's rules (the unit must be dirty).","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."}],"responses":{"200":{"description":"Dispatch a named PLAN to its cleaner, under dispatch's rules (the unit must be dirty).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/abort":{"post":{"operationId":"abortCleaning","summary":"Abort a no-show clean (M4 — the row closes aborted; readiness reverts to dirty).","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbortCleaningBody"}}}},"responses":{"200":{"description":"Abort a no-show clean (M4 — the row closes aborted; readiness reverts to dirty).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleaningTaskView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/photos":{"post":{"operationId":"requestCleaningPhotoUpload","summary":"Mint a presigned PUT for one before/after photo (two-phase; server-minted key).","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestCleaningPhotoUploadBody"}}}},"responses":{"201":{"description":"Mint a presigned PUT for one before/after photo (two-phase; server-minted key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestCleaningPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/photos/{photoId}/confirm":{"post":{"operationId":"confirmCleaningPhotoUpload","summary":"HEAD-prove the uploaded photo and flip pending → ready.","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"HEAD-prove the uploaded photo and flip pending → ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmCleaningPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/photos/{photoId}/view-url":{"get":{"operationId":"mintCleaningPhotoViewUrl","summary":"Mint a short-lived presigned GET for one ready photo (C3 operational evidence).","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."},{"in":"query","name":"download","schema":{"description":"Set to \"1\" to mint an attachment (download) URL instead of inline.","type":"string","enum":["1"]},"description":"Set to \"1\" to mint an attachment (download) URL instead of inline."}],"responses":{"200":{"description":"Mint a short-lived presigned GET for one ready photo (C3 operational evidence).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintCleaningPhotoViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/cleaning-tasks/{id}/photos/{photoId}":{"delete":{"operationId":"removeCleaningPhoto","summary":"Remove one piece of cleaning evidence (soft delete).","tags":["housekeeping"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaning-task id."},"required":true,"description":"The cleaning-task id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"Remove one piece of cleaning evidence (soft delete).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePhotoResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections":{"get":{"operationId":"listInspections","summary":"The inspection queue (open rounds first).","tags":["inspections"],"responses":{"200":{"description":"The inspection queue (open rounds first).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInspectionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/clear":{"post":{"operationId":"clearInspection","summary":"Pass the checkout (§1.6a pending → clear; listing → ready — a HUMAN verdict).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InspectionNotesBody"}}}},"responses":{"200":{"description":"Pass the checkout (§1.6a pending → clear; listing → ready — a HUMAN verdict).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InspectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/record":{"post":{"operationId":"recordInspectionFinding","summary":"Record a finding: damage / missing item (opens a damage report) or extra cleaning.","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordInspectionFindingBody"}}}},"responses":{"200":{"description":"Record a finding: damage / missing item (opens a damage report) or extra cleaning.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordInspectionFindingResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/escalate":{"post":{"operationId":"escalateInspection","summary":"Escalate to the damage/claim machine (§1.6a → escalated; stamps linked reports).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InspectionNotesBody"}}}},"responses":{"200":{"description":"Escalate to the damage/claim machine (§1.6a → escalated; stamps linked reports).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InspectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/resolve":{"post":{"operationId":"resolveInspection","summary":"Close the damage NO-CHARGE (§1.9 capture; listing maintenance_required → ready).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InspectionNotesBody"}}}},"responses":{"200":{"description":"Close the damage NO-CHARGE (§1.9 capture; listing maintenance_required → ready).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InspectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-reports/{id}/photos":{"post":{"operationId":"requestDamagePhotoUpload","summary":"Mint a presigned PUT for one damage photo/video (two-phase; server-minted key).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The damage-report id."},"required":true,"description":"The damage-report id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestDamagePhotoUploadBody"}}}},"responses":{"201":{"description":"Mint a presigned PUT for one damage photo/video (two-phase; server-minted key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestDamagePhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-reports/{id}/photos/{photoId}/confirm":{"post":{"operationId":"confirmDamagePhotoUpload","summary":"HEAD-prove the uploaded damage evidence and flip pending → ready.","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The damage-report id."},"required":true,"description":"The damage-report id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"HEAD-prove the uploaded damage evidence and flip pending → ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmDamagePhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-reports/{id}/photos/{photoId}/view-url":{"get":{"operationId":"mintDamagePhotoViewUrl","summary":"Mint a short-lived presigned GET for one ready damage evidence item (C3).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The damage-report id."},"required":true,"description":"The damage-report id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."},{"in":"query","name":"download","schema":{"description":"Set to \"1\" to mint an attachment (download) URL instead of inline.","type":"string","enum":["1"]},"description":"Set to \"1\" to mint an attachment (download) URL instead of inline."}],"responses":{"200":{"description":"Mint a short-lived presigned GET for one ready damage evidence item (C3).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintDamagePhotoViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-reports/{id}/photos/{photoId}":{"delete":{"operationId":"removeDamagePhoto","summary":"Remove one piece of damage evidence (soft delete).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The damage-report id."},"required":true,"description":"The damage-report id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"Remove one piece of damage evidence (soft delete).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePhotoResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/photos":{"post":{"operationId":"requestInspectionPhotoUpload","summary":"Mint a presigned PUT for one inspection photo/video (two-phase; server-minted key).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestInspectionPhotoUploadBody"}}}},"responses":{"201":{"description":"Mint a presigned PUT for one inspection photo/video (two-phase; server-minted key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestInspectionPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/photos/{photoId}/confirm":{"post":{"operationId":"confirmInspectionPhotoUpload","summary":"HEAD-prove the uploaded inspection evidence and flip pending → ready.","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"HEAD-prove the uploaded inspection evidence and flip pending → ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmInspectionPhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/photos/{photoId}/view-url":{"get":{"operationId":"mintInspectionPhotoViewUrl","summary":"Mint a short-lived presigned GET for one ready inspection evidence item (C3).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."},{"in":"query","name":"download","schema":{"description":"Set to \"1\" to mint an attachment (download) URL instead of inline.","type":"string","enum":["1"]},"description":"Set to \"1\" to mint an attachment (download) URL instead of inline."}],"responses":{"200":{"description":"Mint a short-lived presigned GET for one ready inspection evidence item (C3).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintInspectionPhotoViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inspections/{id}/photos/{photoId}":{"delete":{"operationId":"removeInspectionPhoto","summary":"Remove one piece of inspection evidence (soft delete).","tags":["inspections"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inspection id."},"required":true,"description":"The inspection id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"Remove one piece of inspection evidence (soft delete).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePhotoResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets":{"get":{"operationId":"listMaintenanceTickets","summary":"The maintenance board: every ticket in scope, or only your own reports without resolve.","tags":["maintenance"],"parameters":[{"in":"query","name":"status","schema":{"description":"Comma-separated statuses (open, in_progress, on_hold, resolved, cancelled).","type":"string","minLength":1,"maxLength":100},"description":"Comma-separated statuses (open, in_progress, on_hold, resolved, cancelled)."},{"in":"query","name":"priority","schema":{"type":"string","enum":["low","normal","high","urgent"]}},{"in":"query","name":"assignee","schema":{"description":"A membership id, `anyone` (nobody assigned) or `me`.","anyOf":[{"type":"string","const":"anyone"},{"type":"string","const":"me"},{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}]},"description":"A membership id, `anyone` (nobody assigned) or `me`."},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"The maintenance board: every ticket in scope, or only your own reports without resolve.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceBoard"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"reportMaintenanceTicket","summary":"Report an issue on a property or one of its units.","tags":["maintenance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportMaintenanceTicketBody"}}}},"responses":{"201":{"description":"Report an issue on a property or one of its units.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceTicketView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets/{id}":{"get":{"operationId":"getMaintenanceTicket","summary":"One ticket with its photos and, for a resolve holder, what it may link to.","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."}],"responses":{"200":{"description":"One ticket with its photos and, for a resolve holder, what it may link to.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceTicketDetail"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateMaintenanceTicket","summary":"Change a ticket: status, priority, assignee, wording, or its expense and stay links.","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMaintenanceTicketBody"}}}},"responses":{"200":{"description":"Change a ticket: status, priority, assignee, wording, or its expense and stay links.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceTicketView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets/{id}/resolve":{"post":{"operationId":"resolveMaintenanceTicket","summary":"Resolve a ticket with a note; the last open ticket on a unit makes it ready again.","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveMaintenanceTicketBody"}}}},"responses":{"200":{"description":"Resolve a ticket with a note; the last open ticket on a unit makes it ready again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveMaintenanceTicketResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets/{id}/reopen":{"post":{"operationId":"reopenMaintenanceTicket","summary":"Reopen a resolved ticket (its resolution is cleared).","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."}],"responses":{"200":{"description":"Reopen a resolved ticket (its resolution is cleared).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceTicketView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets/{id}/photos":{"post":{"operationId":"requestMaintenancePhotoUpload","summary":"Mint a presigned PUT for one ticket photo/video (two-phase; server-minted key).","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestMaintenancePhotoUploadBody"}}}},"responses":{"201":{"description":"Mint a presigned PUT for one ticket photo/video (two-phase; server-minted key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestMaintenancePhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets/{id}/photos/{photoId}/confirm":{"post":{"operationId":"confirmMaintenancePhotoUpload","summary":"HEAD-prove the uploaded ticket evidence and flip pending to ready.","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"HEAD-prove the uploaded ticket evidence and flip pending to ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmMaintenancePhotoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets/{id}/photos/{photoId}/view-url":{"get":{"operationId":"mintMaintenancePhotoViewUrl","summary":"Mint a short-lived presigned GET for one ready ticket photo.","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."},{"in":"query","name":"download","schema":{"description":"Set to \"1\" to mint an attachment (download) URL instead of inline.","type":"string","enum":["1"]},"description":"Set to \"1\" to mint an attachment (download) URL instead of inline."}],"responses":{"200":{"description":"Mint a short-lived presigned GET for one ready ticket photo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintMaintenancePhotoViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/maintenance/tickets/{id}/photos/{photoId}":{"delete":{"operationId":"removeMaintenancePhoto","summary":"Remove a ticket photo (soft delete): your own, or any with maintenance:resolve.","tags":["maintenance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The ticket id."},"required":true,"description":"The ticket id."},{"in":"path","name":"photoId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The photo id."},"required":true,"description":"The photo id."}],"responses":{"200":{"description":"Remove a ticket photo (soft delete): your own, or any with maintenance:resolve.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovePhotoResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/lock-codes":{"get":{"operationId":"getListingLockCodes","summary":"The listing’s two static-code statuses (masked preview only, never a value).","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id."},"required":true,"description":"The listing id."}],"responses":{"200":{"description":"The listing’s two static-code statuses (masked preview only, never a value).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingLockCodesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setListingLockCode","summary":"Set/replace one static code (guest or cleaner) physically set on the lock.","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id."},"required":true,"description":"The listing id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetListingLockCodeBody"}}}},"responses":{"200":{"description":"Set/replace one static code (guest or cleaner) physically set on the lock.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingLockCodesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/lock-codes":{"get":{"operationId":"getBookingLockCodes","summary":"The booking’s per-audience gate status + relay lifecycle (never a value).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"The booking’s per-audience gate status + relay lifecycle (never a value).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingLockCodesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/lock-codes/reveal":{"post":{"operationId":"revealLockCode","summary":"Reveal a code to the POC (dual-gated; audited). The raw code is in THIS response only.","tags":["lock-code-relays"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LockCodeAudienceBody"}}}},"responses":{"200":{"description":"Reveal a code to the POC (dual-gated; audited). The raw code is in THIS response only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevealLockCodeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/lock-codes/hand-to-guest":{"post":{"operationId":"handLockCodeToGuest","summary":"Record the human POC→guest hand-off (§1.5 handed_to_guest; the AI never does this).","tags":["lock-code-relays"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LockCodeAudienceBody"}}}},"responses":{"200":{"description":"Record the human POC→guest hand-off (§1.5 handed_to_guest; the AI never does this).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HandLockCodeToGuestResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/lock-code-relays/ready":{"get":{"operationId":"listReadyLockCodeRelays","summary":"The armed relays awaiting the POC (the /today “codes ready to relay” card).","tags":["lock-code-relays"],"responses":{"200":{"description":"The armed relays awaiting the POC (the /today “codes ready to relay” card).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListReadyRelaysResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/lock-connections":{"get":{"operationId":"listLockConnections","summary":"The connected TTLock and Nuki accounts, with their health (never a token).","tags":["lock-codes"],"responses":{"200":{"description":"The connected TTLock and Nuki accounts, with their health (never a token).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LockConnectionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"connectLockVendor","summary":"Connect a smart-lock account. The credentials are used once; only sealed tokens are kept.","tags":["lock-codes"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectLockVendorBody"}}}},"responses":{"201":{"description":"Connect a smart-lock account. The credentials are used once; only sealed tokens are kept.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LockConnectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/lock-connections/{id}":{"delete":{"operationId":"disconnectLockVendor","summary":"Disconnect a smart-lock account that has no lock mapped to a listing.","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The lock connection id."},"required":true,"description":"The lock connection id."}],"responses":{"200":{"description":"Disconnect a smart-lock account that has no lock mapped to a listing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisconnectLockVendorResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/lock-connections/{id}/reconnect":{"post":{"operationId":"reconnectLockVendor","summary":"Replace a connected account’s credentials in place; its mapped locks and codes stay.","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The lock connection id."},"required":true,"description":"The lock connection id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconnectLockVendorBody"}}}},"responses":{"200":{"description":"Replace a connected account’s credentials in place; its mapped locks and codes stay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LockConnectionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/lock-connections/{id}/locks":{"get":{"operationId":"listVendorLocks","summary":"The locks on a connected account, read live from the vendor, with battery.","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The lock connection id."},"required":true,"description":"The lock connection id."}],"responses":{"200":{"description":"The locks on a connected account, read live from the vendor, with battery.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorLocksResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/smart-lock":{"get":{"operationId":"getListingSmartLock","summary":"The listing lock mode and the smart locks mapped to it.","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id."},"required":true,"description":"The listing id."}],"responses":{"200":{"description":"The listing lock mode and the smart locks mapped to it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSmartLockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"mapListingLock","summary":"Map a vendor lock to the listing (unit door or front door) and switch it to integrated.","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id."},"required":true,"description":"The listing id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapListingLockBody"}}}},"responses":{"200":{"description":"Map a vendor lock to the listing (unit door or front door) and switch it to integrated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSmartLockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/listings/{id}/smart-lock/{role}":{"delete":{"operationId":"unmapListingLock","summary":"Unmap the listing lock in one role; with none left the listing returns to static codes.","tags":["lock-codes"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id."},"required":true,"description":"The listing id."},{"in":"path","name":"role","schema":{"type":"string","enum":["unit","front_door"],"description":"Which door: the unit or a shared front door."},"required":true,"description":"Which door: the unit or a shared front door."}],"responses":{"200":{"description":"Unmap the listing lock in one role; with none left the listing returns to static codes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingSmartLockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests":{"get":{"operationId":"listGuests","summary":"List the tenant’s guests with derived stays / lifetime value / latest ID status.","tags":["guests"],"parameters":[{"in":"query","name":"search","schema":{"description":"Free-text search across every guest: name, phone, WhatsApp or email. Matched as a literal substring, case-insensitively.","type":"string","minLength":1,"maxLength":100},"description":"Free-text search across every guest: name, phone, WhatsApp or email. Matched as a literal substring, case-insensitively."},{"in":"query","name":"limit","schema":{"description":"Page size (default 200, max 500).","type":"integer","minimum":1,"maximum":500},"description":"Page size (default 200, max 500)."},{"in":"query","name":"cursor","schema":{"description":"Keyset cursor: the id of the last guest of the previous page.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Keyset cursor: the id of the last guest of the previous page."},{"in":"query","name":"segment","schema":{"description":"A server-side segment. `new_30_days`: guests created in the last 30 days of the workspace's calendar (today and the 29 before it).","type":"string","enum":["new_30_days"]},"description":"A server-side segment. `new_30_days`: guests created in the last 30 days of the workspace's calendar (today and the 29 before it)."}],"responses":{"200":{"description":"List the tenant’s guests with derived stays / lifetime value / latest ID status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListGuestsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createGuest","summary":"Create a guest profile (the new-guest wizard). The id is server-minted.","tags":["guests"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGuestBody"}}}},"responses":{"201":{"description":"Create a guest profile (the new-guest wizard). The id is server-minted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests/duplicates":{"get":{"operationId":"findGuestDuplicates","summary":"Candidate duplicate guest sets — live guests sharing a normalized phone / WhatsApp / email.","tags":["guests"],"responses":{"200":{"description":"Candidate duplicate guest sets — live guests sharing a normalized phone / WhatsApp / email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestDuplicatesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests/match":{"get":{"operationId":"matchGuestsByPhone","summary":"Live guests whose phone/WhatsApp matches either number being typed into the booking funnel — warns before a duplicate guest is created, and carries the blacklist state the funnel blocks on. Both query numbers are searched against both stored columns.","tags":["guests"],"parameters":[{"in":"query","name":"phone","schema":{"description":"The phone being typed (display form; normalized server-side).","type":"string","maxLength":40},"description":"The phone being typed (display form; normalized server-side)."},{"in":"query","name":"whatsapp","schema":{"description":"The WhatsApp number being typed (display form; normalized server-side).","type":"string","maxLength":40},"description":"The WhatsApp number being typed (display form; normalized server-side)."}],"responses":{"200":{"description":"Live guests whose phone/WhatsApp matches either number being typed into the booking funnel — warns before a duplicate guest is created, and carries the blacklist state the funnel blocks on. Both query numbers are searched against both stored columns.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestMatchResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests/{id}/merge":{"post":{"operationId":"mergeGuest","summary":"Merge a duplicate guest INTO this one — reassign its records, then tombstone the duplicate.","tags":["guests"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"required":true,"description":"The guest id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeGuestBody"}}}},"responses":{"200":{"description":"Merge a duplicate guest INTO this one — reassign its records, then tombstone the duplicate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeGuestResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests/{id}":{"get":{"operationId":"getGuest","summary":"A guest profile: contact, aggregates, relationship flags + stay history.","tags":["guests"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"required":true,"description":"The guest id."}],"responses":{"200":{"description":"A guest profile: contact, aggregates, relationship flags + stay history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateGuest","summary":"Edit a guest’s contact details + acquisition source.","tags":["guests"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"required":true,"description":"The guest id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGuestBody"}}}},"responses":{"200":{"description":"Edit a guest’s contact details + acquisition source.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests/{id}/note":{"post":{"operationId":"setGuestNote","summary":"Set the operator's running note on a guest (blank clears it).","tags":["guests"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"required":true,"description":"The guest id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetGuestNoteBody"}}}},"responses":{"200":{"description":"Set the operator's running note on a guest (blank clears it).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests/{id}/flags":{"post":{"operationId":"setGuestFlag","summary":"Toggle one advisory tag (vip / watchlist / long-stay).","tags":["guests"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"required":true,"description":"The guest id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetGuestFlagBody"}}}},"responses":{"200":{"description":"Toggle one advisory tag (vip / watchlist / long-stay).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guests/{id}/blacklist":{"post":{"operationId":"setGuestBlacklist","summary":"Set/clear the blacklist (a stated reason is required to blacklist).","tags":["guests"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"required":true,"description":"The guest id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetGuestBlacklistBody"}}}},"responses":{"200":{"description":"Set/clear the blacklist (a stated reason is required to blacklist).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reviews":{"get":{"operationId":"listReviews","summary":"The tenant’s guest reviews + the KPI band (avg rating, response rate, distribution).","tags":["reviews"],"responses":{"200":{"description":"The tenant’s guest reviews + the KPI band (avg rating, response rate, distribution).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListReviewsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"requestReview","summary":"Request a review for a booking on a platform (queue or send). The id is server-minted.","tags":["reviews"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestReviewBody"}}}},"responses":{"201":{"description":"Request a review for a booking on a platform (queue or send). The id is server-minted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reviews/{id}/record":{"post":{"operationId":"recordReview","summary":"Record a received rating (1–5) on an open review.","tags":["reviews"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The review id."},"required":true,"description":"The review id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordReviewBody"}}}},"responses":{"200":{"description":"Record a received rating (1–5) on an open review.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reviews/{id}/skip":{"post":{"operationId":"skipReview","summary":"Skip a review (an issue / no ask) — a terminal non-review.","tags":["reviews"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The review id."},"required":true,"description":"The review id."}],"responses":{"200":{"description":"Skip a review (an issue / no ask) — a terminal non-review.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reviews/{id}/reply":{"post":{"operationId":"replyReview","summary":"C8 — publish the host’s ONE public reply to an OTA-synced review.","tags":["reviews"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The review id."},"required":true,"description":"The review id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyReviewBody"}}}},"responses":{"200":{"description":"C8 — publish the host’s ONE public reply to an OTA-synced review.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reviews/{id}/host-review":{"post":{"operationId":"hostReview","summary":"C8 — submit the Airbnb-only host→guest review (three 1–5 scores, recommend, text).","tags":["reviews"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The review id."},"required":true,"description":"The review id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostReviewBody"}}}},"responses":{"200":{"description":"C8 — submit the Airbnb-only host→guest review (three 1–5 scores, recommend, text).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/extensions":{"get":{"operationId":"listExtensions","summary":"The tenant’s stay extensions + the KPI band (active requests, approved, extra revenue).","tags":["extensions"],"responses":{"200":{"description":"The tenant’s stay extensions + the KPI band (active requests, approved, extra revenue).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListExtensionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"requestExtension","summary":"Request a stay extension (add nights to a booking) — the maker proposal. The id is server-minted.","tags":["extensions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestExtensionBody"}}}},"responses":{"201":{"description":"Request a stay extension (add nights to a booking) — the maker proposal. The id is server-minted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtensionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/extensions/options":{"get":{"operationId":"extensionOptions","summary":"Can this stay be extended in place, and if not, which other units are free for those nights?","tags":["extensions"],"parameters":[{"in":"query","name":"bookingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"newCheckOut","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"Can this stay be extended in place, and if not, which other units are free for those nights?","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtensionOptionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/extensions/{id}/approve":{"post":{"operationId":"approveExtension","summary":"Approve a requested extension — commits the new nights + moves check-out + posts the inflow (SoD).","tags":["extensions"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The stay-extension id."},"required":true,"description":"The stay-extension id."}],"responses":{"200":{"description":"Approve a requested extension — commits the new nights + moves check-out + posts the inflow (SoD).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtensionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/extensions/{id}/decline":{"post":{"operationId":"declineExtension","summary":"Decline a requested extension — a terminal no-op on inventory + money (SoD).","tags":["extensions"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The stay-extension id."},"required":true,"description":"The stay-extension id."}],"responses":{"200":{"description":"Decline a requested extension — a terminal no-op on inventory + money (SoD).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtensionView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/status":{"get":{"operationId":"listChannelManagerStatus","summary":"Per-property channel-sync status: mode, provisioning coverage, last error.","tags":["channel-manager"],"responses":{"200":{"description":"Per-property channel-sync status: mode, provisioning coverage, last error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListChannelStatusResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/live-status":{"get":{"operationId":"checkChannelManagerLiveStatus","summary":"Verify our channel mappings against the provider's live property list: which mapped containers still exist, which are provably gone, and which the provider has switched off. Read-only — it reports, it never repairs.","tags":["channel-manager"],"responses":{"200":{"description":"Verify our channel mappings against the provider's live property list: which mapped containers still exist, which are provably gone, and which the provider has switched off. Read-only — it reports, it never repairs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelLiveStatusResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/messaging-app":{"post":{"operationId":"enableChannelMessagingApp","summary":"Install the provider's Messages & Reviews app on this property's containers, which is what un-gates guest messages and reviews (without it those APIs answer 403). Idempotent. The inverse is DELETE on the same path.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Install the provider's Messages & Reviews app on this property's containers, which is what un-gates guest messages and reviews (without it those APIs answer 403). Idempotent. The inverse is DELETE on the same path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableMessagingAppResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"disableChannelMessagingApp","summary":"Remove the provider's Messages & Reviews app from this property's containers, turning guest messages and reviews back off. Idempotent; only ever removes OUR app, never a neighbouring integration holding the same slot.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Remove the provider's Messages & Reviews app from this property's containers, turning guest messages and reviews back off. Idempotent; only ever removes OUR app, never a neighbouring integration holding the same slot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableMessagingAppResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/enable":{"post":{"operationId":"enableChannelSync","summary":"Provision this property at the channel-manager provider (unit mode: every active listing; pool mode: the property with a room type per unit type). Idempotent — already-mapped units are skipped.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Provision this property at the channel-manager provider (unit mode: every active listing; pool mode: the property with a room type per unit type). Idempotent — already-mapped units are skipped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableChannelSyncResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/google-readiness":{"get":{"operationId":"getGoogleReadiness","summary":"Is this property ready for Google Vacation Rentals? The provider's pre-activation checklist, checked before the four-week wait.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Is this property ready for Google Vacation Rentals? The provider's pre-activation checklist, checked before the four-week wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleReadinessResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/connect-session":{"post":{"operationId":"createHostedConnectSession","summary":"Mint the short-lived hosted connect/mapping session (the host runs the OTA OAuth + listing mapping there).","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostedConnectSessionBody"}}}},"responses":{"200":{"description":"Mint the short-lived hosted connect/mapping session (the host runs the OTA OAuth + listing mapping there).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostedConnectSessionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/disable":{"post":{"operationId":"disableChannelSync","summary":"Tear down the provider-side property (unmap) and retire the sync mappings.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Tear down the provider-side property (unmap) and retire the sync mappings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableChannelSyncResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/extras":{"get":{"operationId":"getChannelExtras","summary":"OTA review scores and the current hold-back per provider-side property.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"OTA review scores and the current hold-back per provider-side property.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelExtrasResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/holdback":{"patch":{"operationId":"setChannelHoldback","summary":"Keep N units off the channel via an availability-offset rule (0/null removes).","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelHoldbackBody"}}}},"responses":{"200":{"description":"Keep N units off the channel via an availability-offset rule (0/null removes).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelHoldbackResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/distribution-currency":{"patch":{"operationId":"setDistributionCurrency","summary":"Declare which currency an OTA lists this property in (null = inherit). Not a price.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDistributionCurrencyBody"}}}},"responses":{"200":{"description":"Declare which currency an OTA lists this property in (null = inherit). Not a price.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDistributionCurrencyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/units/{listingId}/channels":{"get":{"operationId":"listUnitChannels","summary":"The unit's live OTA channels (empty when not channel-synced).","tags":["listings"],"parameters":[{"in":"path","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"The unit's live OTA channels (empty when not channel-synced).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnitChannelsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/units/{listingId}/booking-policy":{"get":{"operationId":"getUnitBookingPolicy","summary":"The unit's OTA booking policy — instant, well-reviewed-only, or request-to-book.","tags":["listings"],"parameters":[{"in":"path","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"The unit's OTA booking policy — instant, well-reviewed-only, or request-to-book.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnitBookingPolicyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/units/{listingId}/availability":{"post":{"operationId":"setSpanAvailability","summary":"Open/close a night span on channels — all (stop-sell) or a subset (targeted rules).","tags":["channel-manager"],"parameters":[{"in":"path","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSpanAvailabilityBody"}}}},"responses":{"200":{"description":"Open/close a night span on channels — all (stop-sell) or a subset (targeted rules).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSpanAvailabilityResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/units/{listingId}/sync":{"post":{"operationId":"syncChannelUnit","summary":"Queue a full re-push of one unit to the channel (worker flushes within a tick).","tags":["channel-manager"],"parameters":[{"in":"path","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Queue a full re-push of one unit to the channel (worker flushes within a tick).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncChannelUnitResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/sync-mode":{"post":{"operationId":"changeChannelSyncMode","summary":"Change a property’s sync shape (individual units ↔ pooled by type), tearing down and re-provisioning.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeSyncModeBody"}}}},"responses":{"200":{"description":"Change a property’s sync shape (individual units ↔ pooled by type), tearing down and re-provisioning.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeSyncModeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/units/{listingId}/map":{"post":{"operationId":"mapChannelUnit","summary":"Distribute one unit on the channel (provision it under the property’s existing setup).","tags":["channel-manager"],"parameters":[{"in":"path","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Distribute one unit on the channel (provision it under the property’s existing setup).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableChannelSyncResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/units/{listingId}/unmap":{"post":{"operationId":"unmapChannelUnit","summary":"Tear down one unit's channel setup (provider side + mappings).","tags":["channel-manager"],"parameters":[{"in":"path","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Tear down one unit's channel setup (provider side + mappings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableChannelSyncResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/properties/{id}/content":{"post":{"operationId":"pushChannelContent","summary":"Project photos, policy, facilities and taxes onto the provider-side property.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Project photos, policy, facilities and taxes onto the provider-side property.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushChannelContentResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/revisions":{"get":{"operationId":"listQuarantinedRevisions","summary":"Channel booking revisions awaiting a human (unmapped/altered-money/conflicts).","tags":["channel-manager"],"responses":{"200":{"description":"Channel booking revisions awaiting a human (unmapped/altered-money/conflicts).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListQuarantinedRevisionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/revisions/{id}/retry":{"post":{"operationId":"retryChannelRevision","summary":"Send a quarantined/failed revision back through the applier.","tags":["channel-manager"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Send a quarantined/failed revision back through the applier.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryRevisionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/channel-settings":{"get":{"operationId":"listChannelSettings","summary":"Every connectable channel with who collects its bookings and its markup.","tags":["channel-manager"],"responses":{"200":{"description":"Every connectable channel with who collects its bookings and its markup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListChannelSettingsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/channel-markups":{"get":{"operationId":"listChannelMarkups","summary":"Every connectable channel's markup, and the currencies the live rate plans sell in (the markup seat's own read).","tags":["channel-pricing"],"responses":{"200":{"description":"Every connectable channel's markup, and the currencies the live rate plans sell in (the markup seat's own read).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListChannelMarkupsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/channel-settings/{channel}/payment-collector":{"patch":{"operationId":"setChannelPaymentCollector","summary":"Who collects one OTA's bookings when a booking does not say (null = the channel default).","tags":["channel-manager"],"parameters":[{"in":"path","name":"channel","schema":{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo"]},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPaymentCollectorBody"}}}},"responses":{"200":{"description":"Who collects one OTA's bookings when a booking does not say (null = the channel default).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelSettingView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/channel-settings/{channel}/markup":{"patch":{"operationId":"setChannelMarkup","summary":"One channel's markup (percentage plus flat add), carried by its own child rate plan.","tags":["channel-pricing"],"parameters":[{"in":"path","name":"channel","schema":{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo","google"]},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelMarkupBody"}}}},"responses":{"200":{"description":"One channel's markup (percentage plus flat add), carried by its own child rate plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelMarkupResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/channel-prices":{"get":{"operationId":"previewChannelPrices","summary":"What each channel will see for one listing over the next 30 nights.","tags":["channel-pricing"],"parameters":[{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"What each channel will see for one listing over the next 30 nights.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelPricePreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/sync-now":{"post":{"operationId":"syncChannelsNow","summary":"Send queued availability, rate and stay-rule changes to the channels now.","tags":["channel-manager"],"responses":{"200":{"description":"Send queued availability, rate and stay-rule changes to the channels now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncChannelsNowResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/resend-all":{"post":{"operationId":"resendAllChannels","summary":"Queue the whole 500-day horizon for every connected property (the drift repair).","tags":["channel-manager"],"responses":{"200":{"description":"Queue the whole 500-day horizon for every connected property (the drift repair).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendAllChannelsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/hibernation":{"post":{"operationId":"setChannelHibernation","summary":"Pause selling on every channel (mappings kept) or wake exactly the paused properties.","tags":["channel-manager"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelHibernationBody"}}}},"responses":{"200":{"description":"Pause selling on every channel (mappings kept) or wake exactly the paused properties.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelHibernationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/base-rate":{"get":{"operationId":"getListingBaseRate","summary":"Read a listing’s base-rate hierarchy (unit / type / property) + the resolved rate.","tags":["pricing"],"parameters":[{"in":"query","name":"listingId","schema":{"description":"Read the FULL hierarchy for this listing (unit + type + property).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the FULL hierarchy for this listing (unit + type + property)."},{"in":"query","name":"listingTypeId","schema":{"description":"Read the type level (+ its property default). Exactly ONE id param.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the type level (+ its property default). Exactly ONE id param."},{"in":"query","name":"propertyId","schema":{"description":"Read the property default only. Exactly ONE id param.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the property default only. Exactly ONE id param."}],"responses":{"200":{"description":"Read a listing’s base-rate hierarchy (unit / type / property) + the resolved rate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingBaseRateView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setBaseRate","summary":"Set or clear one hierarchy level’s base nightly rate (minor units; tenant base currency).","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetBaseRateBody"}}}},"responses":{"200":{"description":"Set or clear one hierarchy level’s base nightly rate (minor units; tenant base currency).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetBaseRateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/fx-quote":{"get":{"operationId":"getFxQuote","summary":"The current FX rate for one currency pair, for the base-rate converter (read-only).","tags":["pricing"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^[A-Za-z]{3}$","description":"The currency the operator is converting FROM."},"required":true,"description":"The currency the operator is converting FROM."},{"in":"query","name":"to","schema":{"type":"string","pattern":"^[A-Za-z]{3}$","description":"The currency of the rate field being filled."},"required":true,"description":"The currency of the rate field being filled."}],"responses":{"200":{"description":"The current FX rate for one currency pair, for the base-rate converter (read-only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FxQuoteView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/weekend-adjust":{"post":{"operationId":"setWeekendAdjust","summary":"Set or clear one hierarchy level’s WEEKEND percentage (basis points; +2000 = 20% higher), applied to Friday/Saturday/Sunday nights over the base rate.","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetWeekendAdjustBody"}}}},"responses":{"200":{"description":"Set or clear one hierarchy level’s WEEKEND percentage (basis points; +2000 = 20% higher), applied to Friday/Saturday/Sunday nights over the base rate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetWeekendAdjustResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/date-rate":{"post":{"operationId":"setDateRate","summary":"Set or clear the per-DATE nightly override for one listing over [from, to) (minor units; tenant base currency).","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDateRateBody"}}}},"responses":{"200":{"description":"Set or clear the per-DATE nightly override for one listing over [from, to) (minor units; tenant base currency).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDateRateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/date-rate-adjust":{"post":{"operationId":"adjustDateRate","summary":"Raise or lower every night of [from, to) for one listing by a percentage (basis points), writing per-date overrides computed from what each night currently costs.","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdjustDateRateBody"}}}},"responses":{"200":{"description":"Raise or lower every night of [from, to) for one listing by a percentage (basis points), writing per-date overrides computed from what each night currently costs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdjustDateRateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/channel-date-rate-adjust":{"post":{"operationId":"adjustChannelDateRate","summary":"Raise or lower every night of [from, to) on ONE channel lane by a percentage, in the lane's own currency.","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdjustChannelDateRateBody"}}}},"responses":{"200":{"description":"Raise or lower every night of [from, to) on ONE channel lane by a percentage, in the lane's own currency.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdjustChannelDateRateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/channel-rate":{"get":{"operationId":"listChannelRates","summary":"A listing's per-channel pricing lanes (each in its OWN currency; 0148).","tags":["pricing"],"parameters":[{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"A listing's per-channel pricing lanes (each in its OWN currency; 0148).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListChannelRatesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setChannelRate","summary":"Set or clear one channel lane (nightly rate in the LANE currency; clear drops its date overrides).","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelRateBody"}}}},"responses":{"200":{"description":"Set or clear one channel lane (nightly rate in the LANE currency; clear drops its date overrides).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelRateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/pushed-rate":{"get":{"operationId":"getPushedRates","summary":"The RESOLVED nightly rate the channel is actually selling for one listing (listing grain only).","tags":["pricing"],"parameters":[{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"night","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"The RESOLVED nightly rate the channel is actually selling for one listing (listing grain only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushedRateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/channel-date-rate":{"post":{"operationId":"setChannelDateRate","summary":"Set or clear a lane's per-DATE override over [from, to) (inherits the lane currency).","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelDateRatesBody"}}}},"responses":{"200":{"description":"Set or clear a lane's per-DATE override over [from, to) (inherits the lane currency).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelDateRatesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/channel-rate-authority":{"post":{"operationId":"setChannelRateAuthority","summary":"Set who owns the nightly price on one mapped channel lane (lodgr, or an external pricing tool).","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelRateAuthorityBody"}}}},"responses":{"200":{"description":"Set who owns the nightly price on one mapped channel lane (lodgr, or an external pricing tool).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetChannelRateAuthorityResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pricing/date-restriction":{"get":{"operationId":"listDateRestrictions","summary":"The per-DATE stay-rule overrides for one listing over [from, to).","tags":["pricing"],"parameters":[{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"from","schema":{"type":"string"},"required":true},{"in":"query","name":"to","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"The per-DATE stay-rule overrides for one listing over [from, to).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDateRestrictionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setDateRestriction","summary":"Set or clear the per-DATE stay rules (min/max stay, closed-to-arrival/departure, stop-sell) for one listing over [from, to).","tags":["pricing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDateRestrictionBody"}}}},"responses":{"200":{"description":"Set or clear the per-DATE stay rules (min/max stay, closed-to-arrival/departure, stop-sell) for one listing over [from, to).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDateRestrictionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/price-rules":{"get":{"operationId":"listPriceRules","summary":"Every live price rule, the send-to-channels switch and the entry currency.","tags":["price-rules"],"responses":{"200":{"description":"Every live price rule, the send-to-channels switch and the entry currency.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRulesPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createPriceRule","summary":"Create a price rule (a saved rule applies at once; owner decision 2026-10-05).","tags":["price-rules"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRuleBody"}}}},"responses":{"201":{"description":"Create a price rule (a saved rule applies at once; owner decision 2026-10-05).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRuleView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/price-rules/{id}":{"patch":{"operationId":"updatePriceRule","summary":"Replace every field of one price rule (including switching it on or off).","tags":["price-rules"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRuleBody"}}}},"responses":{"200":{"description":"Replace every field of one price rule (including switching it on or off).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRuleView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removePriceRule","summary":"Remove a price rule (soft-delete; prices return to what the remaining rules give).","tags":["price-rules"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Remove a price rule (soft-delete; prices return to what the remaining rules give).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRuleRemoved"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/price-rules/preview":{"post":{"operationId":"previewPriceRules","summary":"The next N nights of one listing before and after rules, optionally with an unsaved draft rule. Writes nothing.","tags":["price-rules"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRulePreviewBody"}}}},"responses":{"200":{"description":"The next N nights of one listing before and after rules, optionally with an unsaved draft rule. Writes nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRulePreview"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/price-rules/limits":{"get":{"operationId":"listPriceRuleLimits","summary":"Every property and type with the floor and ceiling a rule may not push a night past.","tags":["price-rules"],"responses":{"200":{"description":"Every property and type with the floor and ceiling a rule may not push a night past.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRuleLimits"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setPriceRuleLimits","summary":"Set or clear the floor and ceiling of one property or type (minor units, tenant base currency).","tags":["price-rules"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPriceRuleLimitsBody"}}}},"responses":{"200":{"description":"Set or clear the floor and ceiling of one property or type (minor units, tenant base currency).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRuleLimitRow"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/issues":{"get":{"operationId":"listOpsIssues","summary":"The issues in one status (open by default), most pressing first, with every tab count.","tags":["issues"],"parameters":[{"in":"query","name":"status","schema":{"description":"Which tab to list; open when absent.","type":"string","enum":["open","fixed","dismissed","auto_resolved"]},"description":"Which tab to list; open when absent."}],"responses":{"200":{"description":"The issues in one status (open by default), most pressing first, with every tab count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsIssuesPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/issues/{id}/fixed":{"post":{"operationId":"markOpsIssueFixed","summary":"Mark an open issue fixed (it reopens if a scan finds it again).","tags":["issues"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Mark an open issue fixed (it reopens if a scan finds it again).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsIssueView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/issues/{id}/dismiss":{"post":{"operationId":"dismissOpsIssue","summary":"Dismiss an open issue (it stays dismissed on later scans).","tags":["issues"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Dismiss an open issue (it stays dismissed on later scans).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsIssueView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/issues/{id}/reopen":{"post":{"operationId":"reopenOpsIssue","summary":"Reopen a fixed, dismissed or auto-resolved issue.","tags":["issues"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Reopen a fixed, dismissed or auto-resolved issue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsIssueView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/issues/scan":{"post":{"operationId":"scanOpsIssues","summary":"Run the hourly scan now for this workspace, then return the open issues.","tags":["issues"],"responses":{"200":{"description":"Run the hourly scan now for this workspace, then return the open issues.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpsIssuesPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/folio":{"get":{"operationId":"getBookingFolio","summary":"The stay's folio: lines, totals, balance due, invoices and the guest's extra asks.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"The stay's folio: lines, totals, balance due, invoices and the guest's extra asks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Folio"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/folio/charges":{"post":{"operationId":"addFolioCharge","summary":"Put an amount the guest owes on the folio (a balance due; moves no money).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddFolioChargeBody"}}}},"responses":{"201":{"description":"Put an amount the guest owes on the folio (a balance due; moves no money).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolioChargeCreated"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/folio-charges/{id}/reverse":{"post":{"operationId":"reverseFolioCharge","summary":"Reverse a folio charge with a reason (append-only; refused while it is collected).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReverseFolioChargeBody"}}}},"responses":{"201":{"description":"Reverse a folio charge with a reason (append-only; refused while it is collected).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolioChargeCreated"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/folio-charges/{id}/collect":{"post":{"operationId":"collectFolioCharge","summary":"Record that the guest paid one folio charge, on the booking-charge rail.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectFolioChargeBody"}}}},"responses":{"201":{"description":"Record that the guest paid one folio charge, on the booking-charge rail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FolioChargeCollected"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/invoices":{"post":{"operationId":"issueGuestInvoice","summary":"Invoice the stay; if the charges changed since the last invoice, credit it and reissue.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"201":{"description":"Invoice the stay; if the charges changed since the last invoice, credit it and reissue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueGuestInvoiceResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-invoices/{id}/credit":{"post":{"operationId":"creditGuestInvoice","summary":"Cancel an invoice with a credit note for its full amount.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"201":{"description":"Cancel an invoice with a credit note for its full amount.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestInvoice"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-invoices/{id}/email":{"post":{"operationId":"emailGuestInvoice","summary":"Email an invoice or credit note to the guest (sent by the worker).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Email an invoice or credit note to the guest (sent by the worker).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestInvoiceEmailed"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/extra-requests":{"get":{"operationId":"listPendingExtraRequests","summary":"Guests' extra asks waiting on a person, oldest first.","tags":["bookings"],"responses":{"200":{"description":"Guests' extra asks waiting on a person, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingExtraRequests"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/extra-requests/{id}/decision":{"post":{"operationId":"decideExtraRequest","summary":"Confirm an extra (it lands on the folio as a balance due) or decline it with a reason.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideExtraRequestBody"}}}},"responses":{"200":{"description":"Confirm an extra (it lands on the folio as a balance due) or decline it with a reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtraRequestDecided"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/fees/upsells":{"get":{"operationId":"listUpsellSettings","summary":"How each optional extra is offered in the guest app.","tags":["fees"],"responses":{"200":{"description":"How each optional extra is offered in the guest app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsellSettingsList"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/fees/{id}/upsell":{"patch":{"operationId":"setUpsellSettings","summary":"Set how one optional extra is offered in the guest app.","tags":["fees"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsellSettingsBody"}}}},"responses":{"200":{"description":"Set how one optional extra is offered in the guest app.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsellSaved"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/fees/{id}/upsell/photo/upload-url":{"post":{"operationId":"requestUpsellPhotoUpload","summary":"Presign a PUT for an extra's photo (writes no row).","tags":["fees"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsellPhotoUploadBody"}}}},"responses":{"200":{"description":"Presign a PUT for an extra's photo (writes no row).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsellPhotoTicket"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/fees/{id}/upsell/photo":{"patch":{"operationId":"setUpsellPhoto","summary":"Bind an uploaded photo to an extra, or clear it with null.","tags":["fees"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetUpsellPhotoBody"}}}},"responses":{"200":{"description":"Bind an uploaded photo to an extra, or clear it with null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsellSaved"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/upsell-revenue":{"get":{"operationId":"readUpsellRevenue","summary":"Collected upsell sales for a date range: by month, category and item (paid only).","tags":["treasury"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"Collected upsell sales for a date range: by month, category and item (paid only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsellRevenue"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/amenities":{"get":{"operationId":"getAmenityHierarchy","summary":"Read the amenity hierarchy (unit / type / property) + the resolved set at a grain.","tags":["listings"],"parameters":[{"in":"query","name":"listingId","schema":{"description":"Read the FULL hierarchy for this listing (unit + type + property).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the FULL hierarchy for this listing (unit + type + property)."},{"in":"query","name":"listingTypeId","schema":{"description":"Read the type level (+ its property default). Exactly ONE id param.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the type level (+ its property default). Exactly ONE id param."},{"in":"query","name":"propertyId","schema":{"description":"Read the property default only. Exactly ONE id param.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the property default only. Exactly ONE id param."}],"responses":{"200":{"description":"Read the amenity hierarchy (unit / type / property) + the resolved set at a grain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AmenityHierarchyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setAmenities","summary":"Set one hierarchy level’s amenity set (an empty array clears that level).","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAmenitiesBody"}}}},"responses":{"200":{"description":"Set one hierarchy level’s amenity set (an empty array clears that level).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAmenitiesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/content":{"get":{"operationId":"getContentHierarchy","summary":"Read the content hierarchy (unit / type / property) + the per-field resolution.","tags":["listings"],"parameters":[{"in":"query","name":"listingId","schema":{"description":"Read the FULL hierarchy for this listing (unit + type + property).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the FULL hierarchy for this listing (unit + type + property)."},{"in":"query","name":"listingTypeId","schema":{"description":"Read the type level (+ its property default). Exactly ONE id param.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the type level (+ its property default). Exactly ONE id param."}],"responses":{"200":{"description":"Read the content hierarchy (unit / type / property) + the per-field resolution.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentHierarchyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setContentHierarchy","summary":"Replace one hierarchy level's content card (blank clears a field → it inherits again).","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetContentHierarchyBody"}}}},"responses":{"200":{"description":"Replace one hierarchy level's content card (blank clears a field → it inherits again).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentHierarchyView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/property-knowledge":{"get":{"operationId":"getPropertyKnowledge","summary":"Read the property-knowledge hierarchy (unit / type / property) + the per-field resolution.","tags":["listings"],"parameters":[{"in":"query","name":"listingId","schema":{"description":"Read the FULL hierarchy for this listing (unit + type + property).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the FULL hierarchy for this listing (unit + type + property)."},{"in":"query","name":"listingTypeId","schema":{"description":"Read the type level (+ its property default). Exactly ONE id param.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the type level (+ its property default). Exactly ONE id param."},{"in":"query","name":"propertyId","schema":{"description":"Read the building's own card — the root of every inheritance chain.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Read the building's own card — the root of every inheritance chain."}],"responses":{"200":{"description":"Read the property-knowledge hierarchy (unit / type / property) + the per-field resolution.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyKnowledgeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setPropertyKnowledge","summary":"Replace one hierarchy level's property-knowledge card (blank clears a field → it inherits).","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPropertyKnowledgeBody"}}}},"responses":{"200":{"description":"Replace one hierarchy level's property-knowledge card (blank clears a field → it inherits).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyKnowledgeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/conversation":{"get":{"operationId":"getBookingConversation","summary":"The booking's message thread (header + messages, oldest→newest); null when none yet.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"responses":{"200":{"description":"The booking's message thread (header + messages, oldest→newest); null when none yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetConversationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/messages":{"post":{"operationId":"sendBookingMessage","summary":"Send an outbound message to the guest on the booking thread (opens the thread if needed).","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"required":true,"description":"The booking id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageBody"}}}},"responses":{"201":{"description":"Send an outbound message to the guest on the booking thread (opens the thread if needed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox":{"get":{"operationId":"listInbox","summary":"Every live guest conversation, newest activity first — snippet, channels, per-seat unread.","tags":["messaging"],"parameters":[{"in":"query","name":"status","schema":{"type":"string","enum":["open","closed"]}},{"in":"query","name":"channel","schema":{"description":"One message channel, or `ota` for a thread on any OTA.","type":"string","enum":["in_app","whatsapp","email","airbnb","booking_com","expedia","agoda","vrbo","ota"]},"description":"One message channel, or `ota` for a thread on any OTA."},{"in":"query","name":"unread","schema":{"description":"Present → unread-only (per-seat).","type":"string","enum":["true"]},"description":"Present → unread-only (per-seat)."},{"in":"query","name":"search","schema":{"description":"Guest name / reference code.","type":"string","maxLength":120},"description":"Guest name / reference code."},{"in":"query","name":"limit","schema":{"description":"Page size; 100 when absent.","type":"integer","minimum":1,"maximum":200},"description":"Page size; 100 when absent."},{"in":"query","name":"cursor","schema":{"description":"The previous page's last conversation id (load older).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"The previous page's last conversation id (load older)."}],"responses":{"200":{"description":"Every live guest conversation, newest activity first — snippet, channels, per-seat unread.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInboxResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/mentionable":{"get":{"operationId":"listMentionableMembers","summary":"The tenant's active seats, for tagging a colleague in a thread. Seat ids + display names, read on the identity plane; the taggable set is every active seat, which is exactly the set the mention notification is delivered to.","tags":["messaging"],"responses":{"200":{"description":"The tenant's active seats, for tagging a colleague in a thread. Seat ids + display names, read on the identity plane; the taggable set is every active seat, which is exactly the set the mention notification is delivered to.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMentionableMembersResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}":{"get":{"operationId":"getInboxConversation","summary":"One thread at conversation grain (oldest→newest).","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"responses":{"200":{"description":"One thread at conversation grain (oldest→newest).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/notes":{"post":{"operationId":"addInternalNote","summary":"Append a staff-only note to this thread. NEVER transmitted to the guest — no recipient, no transport, and the guest-messaging suppression scope does not apply.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddInternalNoteBody"}}}},"responses":{"201":{"description":"Append a staff-only note to this thread. NEVER transmitted to the guest — no recipient, no transport, and the guest-messaging suppression scope does not apply.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-manager/backfill":{"post":{"operationId":"backfillChannelBookings","summary":"Import ALL of the connected account's booking history, past and future. Enumerates the provider's bookings, skips what we already hold, and ingests the rest through the same applier the live feed uses. Re-runnable: it resumes rather than redoing.","tags":["channel-manager"],"responses":{"200":{"description":"Import ALL of the connected account's booking history, past and future. Enumerates the provider's bookings, skips what we already hold, and ingests the rest through the same applier the live feed uses. Re-runnable: it resumes rather than redoing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelBackfillResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/imports":{"get":{"operationId":"listImportBatches","summary":"The tenant's import batches, newest first.","tags":["imports"],"responses":{"200":{"description":"The tenant's import batches, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListImportBatchesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createImportBatch","summary":"Stage a pasted or uploaded delimited file: parse every row, keep the header row, and auto-detect a column mapping as a STARTING POINT the operator confirms. Writes no bookings.","tags":["imports"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateImportBatchBody"}}}},"responses":{"201":{"description":"Stage a pasted or uploaded delimited file: parse every row, keep the header row, and auto-detect a column mapping as a STARTING POINT the operator confirms. Writes no bookings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportBatchWithRowsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/imports/{id}":{"get":{"operationId":"previewImportBatch","summary":"What WOULD happen, writing nothing: every staged row with its conflict reason, plus each distinct unit reference with a suggested listing.","tags":["imports"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The import batch id."},"required":true,"description":"The import batch id."}],"responses":{"200":{"description":"What WOULD happen, writing nothing: every staged row with its conflict reason, plus each distinct unit reference with a suggested listing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportPreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/imports/{id}/mapping":{"patch":{"operationId":"setImportMapping","summary":"Confirm the column mapping, the unit-reference mapping, and the two STATED conventions (date order, number format), then re-parse every staged row. Still writes no bookings.","tags":["imports"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The import batch id."},"required":true,"description":"The import batch id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetImportMappingBody"}}}},"responses":{"200":{"description":"Confirm the column mapping, the unit-reference mapping, and the two STATED conventions (date order, number format), then re-parse every staged row. Still writes no bookings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportBatchWithRowsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/imports/{id}/commit":{"post":{"operationId":"commitImportBatch","summary":"Mint a booking per validated row, quarantine-not-abort. Holds the nights through the same oversell guard every other booking creator uses. Posts NO money.","tags":["imports"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The import batch id."},"required":true,"description":"The import batch id."}],"responses":{"200":{"description":"Mint a booking per validated row, quarantine-not-abort. Holds the nights through the same oversell guard every other booking creator uses. Posts NO money.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitImportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/imports/{id}/money":{"get":{"operationId":"previewImportMoney","summary":"The money DRY RUN: per committed row, what would post, where the gross would be credited, and why a row is skipped. Writes nothing.","tags":["import-money"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The import batch id."},"required":true,"description":"The import batch id."}],"responses":{"200":{"description":"The money DRY RUN: per committed row, what would post, where the gross would be credited, and why a row is skipped. Writes nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportMoneyPreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postImportMoney","summary":"Post a payment per qualifying row, dated the stay's check-in and credited by the property's operating model. Idempotent per row. Revenue then recognises itself through the existing nightly sweep.","tags":["import-money"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The import batch id."},"required":true,"description":"The import batch id."}],"responses":{"200":{"description":"Post a payment per qualifying row, dated the stay's check-in and credited by the property's operating model. Idempotent per row. Revenue then recognises itself through the existing nightly sweep.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostImportMoneyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/imports/{id}/cutoff":{"patch":{"operationId":"setImportCutoff","summary":"Record the money cutoff: stays checking in on or after this date get a payment posted, earlier ones import as records only. Required before any money posts.","tags":["import-money"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The import batch id."},"required":true,"description":"The import batch id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetImportCutoffBody"}}}},"responses":{"200":{"description":"Record the money cutoff: stays checking in on or after this date get a payment posted, earlier ones import as records only. Required before any money posts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetImportCutoffResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/imports/{id}/rollback":{"post":{"operationId":"rollbackImportBatch","summary":"Discard an UNCOMMITTED batch. A committed batch is history — its bookings are real records, and unwinding them is a cancellation decision per booking.","tags":["imports"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The import batch id."},"required":true,"description":"The import batch id."}],"responses":{"200":{"description":"Discard an UNCOMMITTED batch. A committed batch is history — its bookings are real records, and unwinding them is a cancellation decision per booking.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollbackImportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/message-templates":{"get":{"operationId":"listMessageTemplates","summary":"The tenant's saved message phrases, grouped by category. Archived rows are excluded unless includeArchived is set (the library page; never the composer picker).","tags":["messaging"],"parameters":[{"in":"query","name":"includeArchived","schema":{"description":"Present → include archived templates (the library page; NOT the picker).","type":"string","enum":["true"]},"description":"Present → include archived templates (the library page; NOT the picker)."}],"responses":{"200":{"description":"The tenant's saved message phrases, grouped by category. Archived rows are excluded unless includeArchived is set (the library page; never the composer picker).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMessageTemplatesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createMessageTemplate","summary":"Create a template. The body may only use tokens from the closed whitelist — an unknown {{token}} is refused here, at the one moment a human is looking at it, rather than reaching a guest verbatim.","tags":["messaging"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMessageTemplateBody"}}}},"responses":{"201":{"description":"Create a template. The body may only use tokens from the closed whitelist — an unknown {{token}} is refused here, at the one moment a human is looking at it, rather than reaching a guest verbatim.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageTemplateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/auto-responses":{"get":{"operationId":"listAutoResponseRules","summary":"The tenant's auto-response rules, one per stay phase. Each names the template it replies with, the channels it answers on, and when it is allowed to speak.","tags":["agents"],"responses":{"200":{"description":"The tenant's auto-response rules, one per stay phase. Each names the template it replies with, the channels it answers on, and when it is allowed to speak.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAutoResponseRulesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setAutoResponseRule","summary":"Configure the auto-response for one stay phase. An UPSERT keyed on the phase — the phase IS the identity, so there is no id for a client to invent and a double submit lands the state the operator asked for rather than a constraint error. The body is a message template, so an automated reply can say no more than a hand-written one.","tags":["agents"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAutoResponseRuleBody"}}}},"responses":{"200":{"description":"Configure the auto-response for one stay phase. An UPSERT keyed on the phase — the phase IS the identity, so there is no id for a client to invent and a double submit lands the state the operator asked for rather than a constraint error. The body is a message template, so an automated reply can say no more than a hand-written one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoResponseRuleResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/auto-responses/{phase}":{"delete":{"operationId":"deleteAutoResponseRule","summary":"Remove the auto-response for one stay phase. Guests in that phase get no automatic reply.","tags":["agents"],"parameters":[{"in":"path","name":"phase","schema":{"type":"string","enum":["inquiry","pre_arrival","in_stay","post_stay"]},"required":true}],"responses":{"200":{"description":"Remove the auto-response for one stay phase. Guests in that phase get no automatic reply.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAutoResponseRuleResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/message-templates/library":{"get":{"operationId":"listStarterTemplates","summary":"The starter reply library: pre-written phrases a tenant can take into their own library, each marked as already added or not (matched by name). Carries no access code and no Wi-Fi credential — releasing a door code stays its own gated action.","tags":["messaging"],"responses":{"200":{"description":"The starter reply library: pre-written phrases a tenant can take into their own library, each marked as already added or not (matched by name). Carries no access code and no Wi-Fi credential — releasing a door code stays its own gated action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStarterTemplatesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"addStarterTemplates","summary":"Take one or more starter phrases into the library. Each becomes an ordinary template the tenant owns and can edit. An already-added key is skipped and named in the response; an unknown key is refused.","tags":["messaging"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddStarterTemplatesBody"}}}},"responses":{"201":{"description":"Take one or more starter phrases into the library. Each becomes an ordinary template the tenant owns and can edit. An already-added key is skipped and named in the response; an unknown key is refused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddStarterTemplatesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/message-templates/{id}":{"patch":{"operationId":"updateMessageTemplate","summary":"Patch a template; an absent field is left alone. isArchived retires it from the picker without losing the wording a thread may have quoted.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The message-template id."},"required":true,"description":"The message-template id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMessageTemplateBody"}}}},"responses":{"200":{"description":"Patch a template; an absent field is left alone. isArchived retires it from the picker without losing the wording a thread may have quoted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageTemplateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteMessageTemplate","summary":"Soft-delete a template. The name frees up for reuse. Refused (409 template_in_use) while an automation or an auto-reply still sends it.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The message-template id."},"required":true,"description":"The message-template id."}],"responses":{"200":{"description":"Soft-delete a template. The name frees up for reuse. Refused (409 template_in_use) while an automation or an auto-reply still sends it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteMessageTemplateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/template":{"post":{"operationId":"renderMessageTemplate","summary":"Resolve a template against THIS thread's facts and count the use. A MUTATION because it bumps use_count — call it when the operator inserts, not while they browse.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderMessageTemplateBody"}}}},"responses":{"200":{"description":"Resolve a template against THIS thread's facts and count the use. A MUTATION because it bumps use_count — call it when the operator inserts, not while they browse.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderMessageTemplateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/template-variables":{"get":{"operationId":"listTenantVariables","summary":"The tenant's own registered {{variables}}, ordered by key.","tags":["messaging"],"responses":{"200":{"description":"The tenant's own registered {{variables}}, ordered by key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTenantVariablesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setTenantVariable","summary":"Register or update one variable (upsert on the key). A key may not shadow a built-in token.","tags":["messaging"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantVariableBody"}}}},"responses":{"200":{"description":"Register or update one variable (upsert on the key). A key may not shadow a built-in token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantVariableView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/template-variables/{id}":{"delete":{"operationId":"deleteTenantVariable","summary":"Unregister a variable. Existing bodies keep the token and render it as a labelled blank.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The message-template id."},"required":true,"description":"The message-template id."}],"responses":{"200":{"description":"Unregister a variable. Existing bodies keep the token and render it as a labelled blank.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteTenantVariableResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/variables":{"get":{"operationId":"getConversationTemplateVariables","summary":"Every placeholder's value for THIS thread — the composer's variable picker. A READ: it resolves through the same pair a rendered template does, counts nothing and changes nothing. The picker inserts the VALUE, because a composer draft is sent verbatim.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"responses":{"200":{"description":"Every placeholder's value for THIS thread — the composer's variable picker. A READ: it resolves through the same pair a rendered template does, counts nothing and changes nothing. The picker inserts the VALUE, because a composer draft is sent verbatim.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationTemplateVariablesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/inquiry":{"post":{"operationId":"createInquiryFromConversation","summary":"Open a funnel inquiry from this conversation. Guest, unit and channel come from the thread; the operator supplies the stay + party (a real Airbnb inquiry carries no structured stay). Sets no money.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInquiryFromConversationBody"}}}},"responses":{"201":{"description":"Open a funnel inquiry from this conversation. Guest, unit and channel come from the thread; the operator supplies the stay + party (a real Airbnb inquiry carries no structured stay). Sets no money.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInquiryFromConversationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/read":{"post":{"operationId":"markConversationRead","summary":"Upsert THIS seat’s read mark (per-seat unread; UI bookkeeping, no domain event).","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"responses":{"200":{"description":"Upsert THIS seat’s read mark (per-seat unread; UI bookkeeping, no domain event).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkConversationReadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/attachments":{"post":{"operationId":"requestMessageAttachmentUpload","summary":"Mint a presigned PUT for a pre-send photo/video draft on the conversation.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestAttachmentUploadBody"}}}},"responses":{"201":{"description":"Mint a presigned PUT for a pre-send photo/video draft on the conversation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestAttachmentUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/attachments/{id}/confirm":{"post":{"operationId":"confirmMessageAttachmentUpload","summary":"HEAD-prove the uploaded object, then pending → ready.","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The attachment id."},"required":true,"description":"The attachment id."}],"responses":{"200":{"description":"HEAD-prove the uploaded object, then pending → ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmAttachmentUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/attachments/{id}/view-url":{"get":{"operationId":"mintMessageAttachmentViewUrl","summary":"A 300s signed GET for a SENT attachment (drafts are invisible to viewers).","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The attachment id."},"required":true,"description":"The attachment id."}],"responses":{"200":{"description":"A 300s signed GET for a SENT attachment (drafts are invisible to viewers).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/messages":{"post":{"operationId":"sendConversationMessage","summary":"Reply on a conversation (booking threads delegate to the booking send recipe).","tags":["messaging"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The conversation id."},"required":true,"description":"The conversation id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageBody"}}}},"responses":{"201":{"description":"Reply on a conversation (booking threads delegate to the booking send recipe).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/ai-assistant":{"get":{"operationId":"getAiAssistant","summary":"One property's AI assistant: profile, what it knows, the gaps and the autopilot.","tags":["ai-assistant"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"One property's AI assistant: profile, what it knows, the gaps and the autopilot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAssistantView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setAiAssistantProfile","summary":"Set the tone, standing rules, own facts, extras switch and discount policy.","tags":["ai-assistant"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tone":{"type":"string","enum":["warm","friendly","professional","concise"]},"standingRules":{"type":"string","maxLength":2000},"facts":{"maxItems":40,"type":"array","items":{"$ref":"#/components/schemas/AiFact"}},"offerExtras":{"type":"boolean"},"discountsAllowed":{"type":"boolean"},"discountPolicy":{"type":"string","maxLength":1000}},"required":["tone","standingRules","facts","offerExtras","discountsAllowed","discountPolicy"],"additionalProperties":false}}}},"responses":{"200":{"description":"Set the tone, standing rules, own facts, extras switch and discount policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAssistantView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/ai-assistant/autopilot":{"patch":{"operationId":"setAiAutopilot","summary":"Turn the AI autopilot on or off for this property and set its confidence threshold (basis points).","tags":["ai-assistant"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"thresholdBp":{"type":"integer","minimum":5000,"maximum":10000}},"required":["enabled","thresholdBp"],"additionalProperties":false}}}},"responses":{"200":{"description":"Turn the AI autopilot on or off for this property and set its confidence threshold (basis points).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAssistantView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inbox/{id}/ai-draft":{"post":{"operationId":"draftGuestReply","summary":"Draft a reply to the guest's latest message for a person to edit. Writes nothing.","tags":["ai-assistant"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Draft a reply to the guest's latest message for a person to edit. Writes nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestReplyDraftView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/daily":{"get":{"operationId":"listDailyReports","summary":"The most recent daily ops reports (meta only — date + generation instant).","tags":["reports"],"parameters":[{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":90}}],"responses":{"200":{"description":"The most recent daily ops reports (meta only — date + generation instant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDailyReportsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/daily/{date}":{"get":{"operationId":"getDailyReport","summary":"One civil day's ops report — sections + both rendered bodies + per-recipient delivery status.","tags":["reports"],"parameters":[{"in":"path","name":"date","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"One civil day's ops report — sections + both rendered bodies + per-recipient delivery status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetDailyReportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/staff-phone-links":{"get":{"operationId":"listStaffPhoneLinks","summary":"The tenant's seat → WhatsApp-number links (the report's WhatsApp recipients).","tags":["staff-phone-links"],"responses":{"200":{"description":"The tenant's seat → WhatsApp-number links (the report's WhatsApp recipients).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStaffPhoneLinksResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/staff-phone-links/{membershipId}":{"patch":{"operationId":"setStaffPhoneLink","summary":"Set or replace one seat's WhatsApp number (normalized to E.164).","tags":["staff-phone-links"],"parameters":[{"in":"path","name":"membershipId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetStaffPhoneLinkBody"}}}},"responses":{"200":{"description":"Set or replace one seat's WhatsApp number (normalized to E.164).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetStaffPhoneLinkResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"clearStaffPhoneLink","summary":"Remove one seat's WhatsApp link (idempotent).","tags":["staff-phone-links"],"parameters":[{"in":"path","name":"membershipId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Remove one seat's WhatsApp link (idempotent).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/report-recipients":{"get":{"operationId":"listReportAudience","summary":"The tenant's seats and who receives the 12 AM daily ops report by email.","tags":["report-recipients"],"responses":{"200":{"description":"The tenant's seats and who receives the 12 AM daily ops report by email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListReportAudienceResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/report-recipients/{membershipId}":{"patch":{"operationId":"addReportRecipient","summary":"Add one seat to the daily-report email audience (idempotent).","tags":["report-recipients"],"parameters":[{"in":"path","name":"membershipId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Add one seat to the daily-report email audience (idempotent).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRecipientResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeReportRecipient","summary":"Remove one seat from the daily-report email audience (idempotent).","tags":["report-recipients"],"parameters":[{"in":"path","name":"membershipId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Remove one seat from the daily-report email audience (idempotent).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/accounts":{"get":{"operationId":"listTreasuryAccounts","summary":"Every treasury money-store + the per-currency company balance.","tags":["treasury"],"responses":{"200":{"description":"Every treasury money-store + the per-currency company balance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTreasuryAccountsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createTreasuryAccount","summary":"Create a money-store (+ optional opening-balance posting to owner equity).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTreasuryAccountBody"}}}},"responses":{"201":{"description":"Create a money-store (+ optional opening-balance posting to owner equity).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTreasuryAccountResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/transactions":{"get":{"operationId":"listTreasuryTransactions","summary":"The filterable cash-movement view, derived from the ledger (inflow/outflow/transfer).","tags":["treasury"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"in":"query","name":"accountId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"kind","schema":{"type":"string","enum":["inflow","outflow","transfer"]}},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"q","schema":{"type":"string","maxLength":200}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":1000}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"The filterable cash-movement view, derived from the ledger (inflow/outflow/transfer).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTreasuryTransactionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/transfers":{"post":{"operationId":"recordTreasuryTransfer","summary":"Record a same-currency inter-account transfer (P&L-neutral; idempotent by transferId).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordTransferBody"}}}},"responses":{"201":{"description":"Record a same-currency inter-account transfer (P&L-neutral; idempotent by transferId).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordTransferResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/conversions":{"post":{"operationId":"recordTreasuryConversion","summary":"Convert between two own stores in different currencies (two journals via 1900; rate derived).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordConversionBody"}}}},"responses":{"201":{"description":"Convert between two own stores in different currencies (two journals via 1900; rate derived).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordConversionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-payouts/open":{"get":{"operationId":"listOpenChannelReceivables","summary":"Bookings whose channel payout has not been settled yet.","tags":["treasury"],"parameters":[{"in":"query","name":"currency","schema":{"type":"string","minLength":3,"maxLength":3}}],"responses":{"200":{"description":"Bookings whose channel payout has not been settled yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOpenChannelReceivablesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-payouts":{"post":{"operationId":"settleChannelPayout","summary":"Settle one OTA payout batch against its open receivables (residual to 4020).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleChannelPayoutBody"}}}},"responses":{"201":{"description":"Settle one OTA payout batch against its open receivables (residual to 4020).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleChannelPayoutResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/channel-accounts":{"get":{"operationId":"listChannelAccounts","summary":"Every connected OTA account and the money store its payouts land in.","tags":["channel-manager"],"responses":{"200":{"description":"Every connected OTA account and the money store its payouts land in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListChannelAccountsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertChannelAccount","summary":"Create or update a connected OTA account (label + where its payouts land).","tags":["channel-manager"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertChannelAccountBody"}}}},"responses":{"201":{"description":"Create or update a connected OTA account (label + where its payouts land).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertChannelAccountResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/sweep":{"get":{"operationId":"planPayoutSweep","summary":"The computed sweep plan: one leg per (source, destination) pair, plus what is blocked.","tags":["treasury"],"responses":{"200":{"description":"The computed sweep plan: one leg per (source, destination) pair, plus what is blocked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutSweepPlanResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"executePayoutSweep","summary":"Execute the sweep: every leg in one transaction, recomputed and compared first.","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecutePayoutSweepBody"}}}},"responses":{"201":{"description":"Execute the sweep: every leg in one transaction, recomputed and compared first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecutePayoutSweepResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/owner-payable":{"get":{"operationId":"getOwnerPayable","summary":"The read-only owner/investor liability balances (2100/2160) per property — the §7 V1 keep.","tags":["treasury"],"responses":{"200":{"description":"The read-only owner/investor liability balances (2100/2160) per property — the §7 V1 keep.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerPayableResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/{id}/receipts/upload-url":{"post":{"operationId":"requestExpenseReceiptUpload","summary":"Presign a PUT for one receipt (image or PDF). Mints a key; creates no row.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense id."},"required":true,"description":"The expense id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestExpenseReceiptUploadBody"}}}},"responses":{"200":{"description":"Presign a PUT for one receipt (image or PDF). Mints a key; creates no row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestExpenseReceiptUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/{id}/receipts":{"post":{"operationId":"attachExpenseReceipt","summary":"Bind an uploaded receipt key to the expense.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense id."},"required":true,"description":"The expense id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachExpenseReceiptBody"}}}},"responses":{"201":{"description":"Bind an uploaded receipt key to the expense.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachExpenseReceiptResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listExpenseReceipts","summary":"The ready receipts on one expense.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense id."},"required":true,"description":"The expense id."}],"responses":{"200":{"description":"The ready receipts on one expense.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListExpenseReceiptsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expense-receipts/{id}/view-url":{"get":{"operationId":"mintExpenseReceiptViewUrl","summary":"A 300s signed GET for one receipt, with its content type so the viewer can branch.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense-receipt id."},"required":true,"description":"The expense-receipt id."}],"responses":{"200":{"description":"A 300s signed GET for one receipt, with its content type so the viewer can branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseReceiptViewUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expense-receipts/{id}":{"delete":{"operationId":"removeExpenseReceipt","summary":"Soft-delete one receipt (the object is left to the bucket lifecycle).","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense-receipt id."},"required":true,"description":"The expense-receipt id."}],"responses":{"200":{"description":"Soft-delete one receipt (the object is left to the bucket lifecycle).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveExpenseReceiptResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expense-categories":{"get":{"operationId":"listExpenseCategories","summary":"The tenant CoA leaves (system + custom), seeding the system set on first touch.","tags":["expenses"],"responses":{"200":{"description":"The tenant CoA leaves (system + custom), seeding the system set on first touch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListExpenseCategoriesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createExpenseCategory","summary":"Add a custom leaf over the code-defined account-class catalog.","tags":["expenses"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateExpenseCategoryBody"}}}},"responses":{"201":{"description":"Add a custom leaf over the code-defined account-class catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseCategoryResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expense-categories/{id}":{"patch":{"operationId":"updateExpenseCategory","summary":"Rename / re-behavior / (de)activate a leaf (system leaves: (de)activate only).","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense-category id."},"required":true,"description":"The expense-category id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExpenseCategoryBody"}}}},"responses":{"200":{"description":"Rename / re-behavior / (de)activate a leaf (system leaves: (de)activate only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseCategoryResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses":{"get":{"operationId":"listExpenses","summary":"The filterable, paged expense book.","tags":["expenses"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"in":"query","name":"categoryId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"q","schema":{"type":"string","maxLength":200}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"The filterable, paged expense book.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListExpensesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"recordExpense","summary":"Record a PAID expense (DR class GL / CR store GL; idempotent by expenseId).","tags":["expenses"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordExpenseBody"}}}},"responses":{"201":{"description":"Record a PAID expense (DR class GL / CR store GL; idempotent by expenseId).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordExpenseResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/{id}":{"patch":{"operationId":"updateExpenseDetails","summary":"Edit an expense’s vendor, description and claimant. Touches no posting.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense id."},"required":true,"description":"The expense id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExpenseDetailsBody"}}}},"responses":{"200":{"description":"Edit an expense’s vendor, description and claimant. Touches no posting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExpenseDetailsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/{id}/corrections":{"post":{"operationId":"correctExpense","summary":"Correct a paid expense: reverse the original posting and post the corrected one. Never rewrites.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The expense id."},"required":true,"description":"The expense id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorrectExpenseBody"}}}},"responses":{"201":{"description":"Correct a paid expense: reverse the original posting and post the corrected one. Never rewrites.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorrectExpenseResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/bills":{"get":{"operationId":"listVendorBills","summary":"The unpaid book — accrued bills, open first and most urgent first.","tags":["expenses"],"parameters":[{"in":"query","name":"status","schema":{"type":"string","enum":["open","settled","void"]}}],"responses":{"200":{"description":"The unpaid book — accrued bills, open first and most urgent first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListVendorBillsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"recordVendorBill","summary":"Record a bill that has ARRIVED but not been paid (DR class GL / CR 2200).","tags":["expenses"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordVendorBillBody"}}}},"responses":{"201":{"description":"Record a bill that has ARRIVED but not been paid (DR class GL / CR 2200).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordVendorBillResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/bills/{id}/settle":{"post":{"operationId":"settleVendorBill","summary":"Pay an accrued bill (DR 2200 / CR store). The P&L is NOT touched again.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The vendor-bill id."},"required":true,"description":"The vendor-bill id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleVendorBillBody"}}}},"responses":{"200":{"description":"Pay an accrued bill (DR 2200 / CR store). The P&L is NOT touched again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleVendorBillResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/bills/{id}/void":{"post":{"operationId":"voidVendorBill","summary":"Reverse an accrued bill (DR 2200 / CR the account the accrual debited). Never deletes.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The vendor-bill id."},"required":true,"description":"The vendor-bill id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidVendorBillBody"}}}},"responses":{"200":{"description":"Reverse an accrued bill (DR 2200 / CR the account the accrual debited). Never deletes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidVendorBillResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/finance":{"get":{"operationId":"getPropertyFinance","summary":"The model in force + history, agreement terms, and funder-tagged capex lines.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."},{"in":"query","name":"listingId","schema":{"description":"View one listing’s effective config (override ?? property default).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"View one listing’s effective config (override ?? property default)."}],"responses":{"200":{"description":"The model in force + history, agreement terms, and funder-tagged capex lines.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyFinanceResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/finance/model":{"patch":{"operationId":"setPropertyModel","summary":"Switch the operating model in force (effective-dated; history never rewritten).","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPropertyModelBody"}}}},"responses":{"200":{"description":"Switch the operating model in force (effective-dated; history never rewritten).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceConfigResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/finance/lease":{"patch":{"operationId":"upsertLeaseAgreement","summary":"Replace the active lease terms (rent, term, deposit, landlord net-split %).","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertLeaseBody"}}}},"responses":{"200":{"description":"Replace the active lease terms (rent, term, deposit, landlord net-split %).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceConfigResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/finance/management":{"patch":{"operationId":"upsertManagementAgreement","summary":"Replace the active management terms (fee base net/gross, fee %, reserve %).","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertManagementBody"}}}},"responses":{"200":{"description":"Replace the active management terms (fee base net/gross, fee %, reserve %).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceConfigResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/finance/investment":{"patch":{"operationId":"upsertInvestmentAgreement","summary":"Replace the active investment terms (return model, investor split %, capital).","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertInvestmentBody"}}}},"responses":{"200":{"description":"Replace the active investment terms (return model, investor split %, capital).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceConfigResult"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/finance/pool-equity":{"post":{"operationId":"applyPoolEquity","summary":"Apply the pool capital structure — fractional units per party → derived splits.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyPoolEquityBody"}}}},"responses":{"200":{"description":"Apply the pool capital structure — fractional units per party → derived splits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyPoolEquityResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/properties/{id}/finance/investments":{"post":{"operationId":"addPropertyInvestment","summary":"Add one funder-tagged capital line to the §3 asset register (posts when paid.)","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddPropertyCapitalLineBody"}}}},"responses":{"201":{"description":"Add one funder-tagged capital line to the §3 asset register (posts when paid.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddPropertyCapitalLineResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/stay-class-revenue":{"get":{"operationId":"getStayClassRevenue","summary":"Recognised revenue split by stay class over a half-open night window (§5.1).","tags":["pnl"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Recognised revenue split by stay class over a half-open night window (§5.1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StayClassRevenueResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/occupancy":{"get":{"operationId":"getOccupancyReport","summary":"Occupancy / ADR / RevPAR over a half-open night window, per listing + day-of-week.","tags":["occupancy"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"Occupancy / ADR / RevPAR over a half-open night window, per listing + day-of-week.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OccupancyReportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/complimentary-stays":{"get":{"operationId":"complimentaryStaysReport","summary":"Complimentary (given-away) stays over a check-in window, with a per-reason rollup.","tags":["comp-report"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"Complimentary (given-away) stays over a check-in window, with a per-reason rollup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplimentaryStaysResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/pnl":{"get":{"operationId":"getPnlReport","summary":"Per-model P&L over a half-open period: revenue, opex, NOI per property and model.","tags":["pnl"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Per-model P&L over a half-open period: revenue, opex, NOI per property and model.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PnlReportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/property":{"get":{"operationId":"getPropertyReport","summary":"Property / listing-type / listing-wise income OR expense over a period, with the account breakdown and trend.","tags":["pnl"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"kind","schema":{"type":"string","enum":["income","expense"]},"required":true},{"in":"query","name":"grain","schema":{"type":"string","enum":["property","listing_type","listing"]},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"accountCode","schema":{"type":"string","pattern":"^[0-9]{4}$"}},{"in":"query","name":"bucketGrain","schema":{"type":"string","enum":["day","month"]}}],"responses":{"200":{"description":"Property / listing-type / listing-wise income OR expense over a period, with the account breakdown and trend.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyReportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/custom/catalog":{"get":{"operationId":"getCustomReportCatalog","summary":"The datasets, fields, operators and estate lists this caller may build a custom report from.","tags":["report-builder"],"responses":{"200":{"description":"The datasets, fields, operators and estate lists this caller may build a custom report from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomReportCatalogResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/custom":{"post":{"operationId":"runCustomReport","summary":"Run one composed report: filtered rows or grouped measures, with totals over the set.","tags":["report-builder"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomReportRunBody"}}}},"responses":{"200":{"description":"Run one composed report: filtered rows or grouped measures, with totals over the set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomReportRunResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/breakeven":{"get":{"operationId":"getBreakevenReport","summary":"Per-property payback, cap rate, and leased break-even — operator capital only.","tags":["pnl"],"responses":{"200":{"description":"Per-property payback, cap rate, and leased break-even — operator capital only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakevenReportResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/reports/breakeven/monthly":{"get":{"operationId":"getMonthlyBreakeven","summary":"Which day of the month cumulative recognized revenue covers the fixed nut.","tags":["pnl"],"parameters":[{"in":"query","name":"month","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}$"},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Which day of the month cumulative recognized revenue covers the fixed nut.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonthlyBreakevenResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/fees":{"get":{"operationId":"listFees","summary":"The guest-facing fee/tax schedule (cleaning, extra-guest, GST, levy).","tags":["fees"],"responses":{"200":{"description":"The guest-facing fee/tax schedule (cleaning, extra-guest, GST, levy).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListFeesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createFee","summary":"Create a fee/tax line.","tags":["fees"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertFeeBody"}}}},"responses":{"201":{"description":"Create a fee/tax line.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/fees/{id}":{"patch":{"operationId":"updateFee","summary":"Update a fee/tax line in place.","tags":["fees"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertFeeBody"}}}},"responses":{"200":{"description":"Update a fee/tax line in place.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteFee","summary":"Soft-delete a fee/tax line.","tags":["fees"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Soft-delete a fee/tax line.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payments/overview":{"get":{"operationId":"getPaymentsOverview","summary":"Processed totals, recent payments, and the dual-gate table — live data only.","tags":["payments"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Processed totals, recent payments, and the dual-gate table — live data only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentsOverviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/workspace-settings":{"get":{"operationId":"getWorkspaceSettings","summary":"The workspace's own country, timezone and base currency (+ whether the currency is still movable).","tags":["workspace-settings"],"responses":{"200":{"description":"The workspace's own country, timezone and base currency (+ whether the currency is still movable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceSettingsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateWorkspaceSettings","summary":"Correct the workspace's country/timezone; move the base currency only while the ledger is empty.","tags":["workspace-settings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWorkspaceSettingsBody"}}}},"responses":{"200":{"description":"Correct the workspace's country/timezone; move the base currency only while the ledger is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceSettingsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/white-label":{"get":{"operationId":"getWhiteLabel","summary":"The tenant's logo, refund ladder and the document boilerplate.","tags":["white-label"],"responses":{"200":{"description":"The tenant's logo, refund ladder and the document boilerplate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhiteLabelView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateWhiteLabel","summary":"Replace the refund ladder + the document boilerplate.","tags":["white-label"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWhiteLabelBody"}}}},"responses":{"200":{"description":"Replace the refund ladder + the document boilerplate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhiteLabelView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/white-label/logo/upload-url":{"post":{"operationId":"requestLogoUpload","summary":"Presign a PUT for the tenant logo. Mints a key; writes no row.","tags":["white-label"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLogoUploadBody"}}}},"responses":{"200":{"description":"Presign a PUT for the tenant logo. Mints a key; writes no row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLogoUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/white-label/logo":{"post":{"operationId":"attachLogo","summary":"Bind an uploaded logo key to the tenant.","tags":["white-label"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachLogoBody"}}}},"responses":{"200":{"description":"Bind an uploaded logo key to the tenant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhiteLabelOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeLogo","summary":"Clear the tenant logo. The policy text on the same row is untouched.","tags":["white-label"],"responses":{"200":{"description":"Clear the tenant logo. The policy text on the same row is untouched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhiteLabelOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/share":{"post":{"operationId":"createQuoteShare","summary":"Get or create the public quotation link for an inquiry (idempotent while live).","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Get or create the public quotation link for an inquiry (idempotent while live).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteShareView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"revokeQuoteShare","summary":"Revoke every live public link for an inquiry.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"required":true,"description":"The inquiry id."}],"responses":{"200":{"description":"Revoke every live public link for an inquiry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeQuoteShareResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payment-rails":{"get":{"operationId":"listTenantPaymentRails","summary":"Every payment rail this workspace has, enabled or not.","tags":["payment-rails"],"responses":{"200":{"description":"Every payment rail this workspace has, enabled or not.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTenantPaymentRailsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setTenantPaymentRail","summary":"Turn one payment rail on or off.","tags":["payment-rails"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantPaymentRailBody"}}}},"responses":{"200":{"description":"Turn one payment rail on or off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantPaymentRailView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"addTenantPaymentRail","summary":"Add a payment rail this workspace accepts.","tags":["payment-rails"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddTenantPaymentRailBody"}}}},"responses":{"201":{"description":"Add a payment rail this workspace accepts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantPaymentRailView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/types":{"get":{"operationId":"listTreasuryTypes","summary":"The money-store types this workspace registered beyond the built-in ones.","tags":["treasury"],"responses":{"200":{"description":"The money-store types this workspace registered beyond the built-in ones.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTreasuryTypesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"registerTreasuryType","summary":"Register a money-store type of your own (the GL code is minted server-side).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterTreasuryTypeBody"}}}},"responses":{"201":{"description":"Register a money-store type of your own (the GL code is minted server-side).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantTreasuryTypeView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/treasury/types/{key}":{"delete":{"operationId":"retireTreasuryType","summary":"Retire one — refused while a money store or a payment rail still names it.","tags":["treasury"],"parameters":[{"in":"path","name":"key","schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"required":true}],"responses":{"200":{"description":"Retire one — refused while a money store or a payment rail still names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetireTreasuryTypeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/billing/invoices":{"get":{"operationId":"listSaasInvoices","summary":"The SaaS invoice book, newest first.","tags":["billing"],"responses":{"200":{"description":"The SaaS invoice book, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSaasInvoicesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/billing/invoices/{id}/receipt":{"post":{"operationId":"submitSaasReceipt","summary":"Attach the PKR payment-receipt facts (no money moves; no status beyond submitted).","tags":["billing"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitSaasReceiptBody"}}}},"responses":{"200":{"description":"Attach the PKR payment-receipt facts (no money moves; no status beyond submitted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/billing/payments":{"get":{"operationId":"listSaasPayments","summary":"The payment transaction history (submit → verify/reject), newest first.","tags":["billing"],"responses":{"200":{"description":"The payment transaction history (submit → verify/reject), newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSaasPaymentsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"submitSaasPayment","summary":"Submit a payment against an open invoice (method-adaptive: transfer needs a bank ref + proof; cash mints a receipt number). No money moves — a platform human verifies.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitSaasPaymentBody"}}}},"responses":{"201":{"description":"Submit a payment against an open invoice (method-adaptive: transfer needs a bank ref + proof; cash mints a receipt number). No money moves — a platform human verifies.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitSaasPaymentResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/billing/payments/evidence":{"post":{"operationId":"requestPaymentEvidenceUpload","summary":"Phase 1 of the proof upload: mint a draft evidence row + a presigned PUT.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestPaymentEvidenceBody"}}}},"responses":{"201":{"description":"Phase 1 of the proof upload: mint a draft evidence row + a presigned PUT.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestPaymentEvidenceResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/billing/payments/evidence/{id}/confirm":{"post":{"operationId":"confirmPaymentEvidence","summary":"Phase 2 of the proof upload: HEAD the object and confirm the draft (no client fields).","tags":["billing"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmPaymentEvidenceBody"}}}},"responses":{"200":{"description":"Phase 2 of the proof upload: HEAD the object and confirm the draft (no client fields).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmPaymentEvidenceResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/billing/plan":{"post":{"operationId":"changePlan","summary":"Change the caller's own tenant's base plan — upgrade applies immediately, downgrade parks at the period boundary. Public plans only.","tags":["billing"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePlanBody"}}}},"responses":{"200":{"description":"Change the caller's own tenant's base plan — upgrade applies immediately, downgrade parks at the period boundary. Public plans only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePlanResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings). This operation returns: `self_service_requires_public_plan` when the target plan is negotiated/private; `downgrade_exceeds_usage` when current usage exceeds the target plan’s limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/billing/plan/pending/{id}":{"delete":{"operationId":"cancelPendingPlanChange","summary":"Undo the caller's own tenant's still-pending scheduled plan change.","tags":["billing"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Undo the caller's own tenant's still-pending scheduled plan change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelPendingPlanChangeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/invitations":{"get":{"operationId":"listInvitations","summary":"Pending invitations — invited people who have not yet proven their address.","tags":["members"],"responses":{"200":{"description":"Pending invitations — invited people who have not yet proven their address.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInvitationsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/invitations/{id}":{"delete":{"operationId":"revokeInvitation","summary":"Revoke a pending invitation (it can never be accepted afterwards).","tags":["members"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Revoke a pending invitation (it can never be accepted afterwards).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeInvitationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/members":{"get":{"operationId":"listMembers","summary":"The member directory — seats, roles, teams, status.","tags":["members"],"responses":{"200":{"description":"The member directory — seats, roles, teams, status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMembersResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"inviteMember","summary":"Invite a user: seat them with an account role + operational roles.","tags":["members"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteMemberBody"}}}},"responses":{"201":{"description":"Invite a user: seat them with an account role + operational roles.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteMemberResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/members/{id}":{"patch":{"operationId":"updateMemberSeat","summary":"Change a seat: account role and/or activate-deactivate (self + last-owner guarded).","tags":["members"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMemberSeatBody"}}}},"responses":{"200":{"description":"Change a seat: account role and/or activate-deactivate (self + last-owner guarded).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeMember","summary":"Remove a user from the workspace (self/owner-grant/last-owner guarded; two-mode).","tags":["members"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Remove a user from the workspace (self/owner-grant/last-owner guarded; two-mode).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveMemberResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/members/{id}/roles":{"patch":{"operationId":"updateMemberRoles","summary":"Grant/revoke operational roles from the system library (assignment only).","tags":["members"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMemberRolesBody"}}}},"responses":{"200":{"description":"Grant/revoke operational roles from the system library (assignment only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/members/{id}/credential":{"post":{"operationId":"setMemberCredential","summary":"Resend a member's unaccepted invitation (owner-grant guarded; sole-workspace users only; 409 once accepted).","tags":["members"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMemberPasswordResetBody"}}}},"responses":{"200":{"description":"Resend a member's unaccepted invitation (owner-grant guarded; sole-workspace users only; 409 once accepted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/teams":{"get":{"operationId":"listTeams","summary":"The team list with placements.","tags":["teams"],"responses":{"200":{"description":"The team list with placements.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTeamsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createTeam","summary":"Create a team.","tags":["teams"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamBody"}}}},"responses":{"201":{"description":"Create a team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/teams/{id}":{"patch":{"operationId":"updateTeam","summary":"Rename/re-describe a team and add/remove seats.","tags":["teams"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTeamBody"}}}},"responses":{"200":{"description":"Rename/re-describe a team and add/remove seats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteTeam","summary":"Soft-delete a team (placements removed; history stays).","tags":["teams"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Soft-delete a team (placements removed; history stays).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/scope-assignments":{"get":{"operationId":"listScopeAssignments","summary":"The enforced-role list plus every live property/listing grant.","tags":["scope-assignments"],"responses":{"200":{"description":"The enforced-role list plus every live property/listing grant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListScopeAssignmentsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"assignScope","summary":"Grant a seat or a team a property, or one listing under it.","tags":["scope-assignments"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignScopeBody"}}}},"responses":{"201":{"description":"Grant a seat or a team a property, or one listing under it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/scope-assignments/{id}":{"delete":{"operationId":"unassignScope","summary":"Revoke one property/listing grant.","tags":["scope-assignments"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The scope-assignment id."},"required":true,"description":"The scope-assignment id."}],"responses":{"200":{"description":"Revoke one property/listing grant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/scope-enforcement":{"patch":{"operationId":"setEnforcedScopeRoles","summary":"Replace the set of operational roles this tenant scopes.","tags":["scope-assignments"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetEnforcedScopeRolesBody"}}}},"responses":{"200":{"description":"Replace the set of operational roles this tenant scopes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetEnforcedScopeRolesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/staff-shifts":{"get":{"operationId":"listStaffShifts","summary":"The duty & on-call roster for a from/to window, with staff names.","tags":["staff-shifts"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"required":true}],"responses":{"200":{"description":"The duty & on-call roster for a from/to window, with staff names.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStaffShiftsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createStaffShift","summary":"Roster a duty or on-call shift for a seat.","tags":["staff-shifts"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateStaffShiftBody"}}}},"responses":{"201":{"description":"Roster a duty or on-call shift for a seat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/staff-shifts/{id}":{"delete":{"operationId":"deleteStaffShift","summary":"Remove a shift from the roster (soft delete; history stays).","tags":["staff-shifts"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Remove a shift from the roster (soft delete; history stays).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/overview":{"get":{"operationId":"getInvestorsOverview","summary":"Every investor party: capital, agreements, accrued vs distributed, payouts.","tags":["investors"],"responses":{"200":{"description":"Every investor party: capital, agreements, accrued vs distributed, payouts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvestorsOverviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/payouts":{"post":{"operationId":"requestInvestorPayout","summary":"MAKER: request a payout (ceiling-checked against the outstanding payable).","tags":["investors"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestInvestorPayoutBody"}}}},"responses":{"201":{"description":"MAKER: request a payout (ceiling-checked against the outstanding payable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/payouts/{id}/decide":{"post":{"operationId":"decideInvestorPayout","summary":"CHECKER: approve — posts DR 2160 / CR store — or reject.","tags":["investors"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideInvestorPayoutBody"}}}},"responses":{"200":{"description":"CHECKER: approve — posts DR 2160 / CR store — or reject.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideInvestorPayoutResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/capital-contributions":{"post":{"operationId":"recordCapitalContribution","summary":"Record a received investor capital tranche — posts DR store-GL / CR 2150 (0202).","tags":["investors"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordCapitalContributionBody"}}}},"responses":{"201":{"description":"Record a received investor capital tranche — posts DR store-GL / CR 2150 (0202).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investor-portal":{"get":{"operationId":"getInvestorPortal","summary":"The signed-in investor's assets, stay performance over a window, capital, terms and payback.","tags":["investor-portal"],"parameters":[{"in":"query","name":"from","schema":{"type":"string"}},{"in":"query","name":"to","schema":{"type":"string"}},{"in":"query","name":"party","schema":{"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party."}],"responses":{"200":{"description":"The signed-in investor's assets, stay performance over a window, capital, terms and payback.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvestorPortalResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investor-portal/capital-notices":{"get":{"operationId":"listMyCapitalNotices","summary":"The signed-in investor's capital-structure notices, unread first.","tags":["investor-portal"],"parameters":[{"in":"query","name":"party","schema":{"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party."}],"responses":{"200":{"description":"The signed-in investor's capital-structure notices, unread first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCapitalNoticesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investor-portal/statements/{id}":{"get":{"operationId":"getInvestorStatementDetail","summary":"One frozen monthly statement with its per-booking lines — the own party's only.","tags":["investor-portal"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The statement id."},"required":true,"description":"The statement id."},{"in":"query","name":"party","schema":{"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party."}],"responses":{"200":{"description":"One frozen monthly statement with its per-booking lines — the own party's only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvestorStatementDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investor-portal/capital-notices/{id}/acknowledge":{"post":{"operationId":"acknowledgeCapitalNotice","summary":"Mark a capital-structure notice as read. Records who and when; changes no split.","tags":["investor-portal"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Mark a capital-structure notice as read. Records who and when; changes no split.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcknowledgeCapitalNoticeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/exits/preview":{"get":{"operationId":"previewInvestorExit","summary":"An exit's schedule and §10.2c written-down value, before it is given.","tags":["treasury"],"parameters":[{"in":"query","name":"partyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"noticeOn","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"noticeDays","schema":{"type":"integer","minimum":0,"maximum":3650}}],"responses":{"200":{"description":"An exit's schedule and §10.2c written-down value, before it is given.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExitPreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/exits":{"get":{"operationId":"listInvestorExits","summary":"Every investor exit, newest notice first, with the computed and settled figures.","tags":["treasury"],"responses":{"200":{"description":"Every investor exit, newest notice first, with the computed and settled figures.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInvestorExitsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"noticeInvestorExit","summary":"Give notice of an investor exit; closes the agreement at the final accrual month.","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoticeInvestorExitBody"}}}},"responses":{"201":{"description":"Give notice of an investor exit; closes the agreement at the final accrual month.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoticeInvestorExitResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/exits/{id}/decide":{"post":{"operationId":"decideInvestorExit","summary":"Approve or cancel an exit. A different human from the one who gave notice.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideInvestorExitBody"}}}},"responses":{"200":{"description":"Approve or cancel an exit. A different human from the one who gave notice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideInvestorExitResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/exits/{id}/settle":{"post":{"operationId":"settleInvestorExit","summary":"Pay an approved exit — DR Investor Capital Payable / CR the paying account.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleInvestorExitBody"}}}},"responses":{"200":{"description":"Pay an approved exit — DR Investor Capital Payable / CR the paying account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettleInvestorExitResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/investor-assignments":{"get":{"operationId":"listInvestorAssignments","summary":"Live investor assignments + the investor-party picker (management view).","tags":["property-finance"],"responses":{"200":{"description":"Live investor assignments + the investor-party picker (management view).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvestorAssignmentsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createInvestorAssignment","summary":"Grant a party visibility of one property XOR one listing.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvestorAssignmentBody"}}}},"responses":{"201":{"description":"Grant a party visibility of one property XOR one listing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/investor-parties":{"post":{"operationId":"createInvestorParty","summary":"Create an investor party by name (get-or-create — the picker is never a dead end).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvestorPartyBody"}}}},"responses":{"201":{"description":"Create an investor party by name (get-or-create — the picker is never a dead end).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvestorPartyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/payee-accounts":{"get":{"operationId":"listPayeeAccounts","summary":"Every payment destination, with how many payments have used each.","tags":["property-finance"],"responses":{"200":{"description":"Every payment destination, with how many payments have used each.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPayeeAccountsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertPayeeAccount","summary":"Add or correct one destination for a party or a staff seat.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertPayeeAccountBody"}}}},"responses":{"201":{"description":"Add or correct one destination for a party or a staff seat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/payee-accounts/{id}":{"delete":{"operationId":"retirePayeeAccount","summary":"Retire a destination — deactivated when used, removed when never used.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"required":true,"description":"The property id."}],"responses":{"200":{"description":"Retire a destination — deactivated when used, removed when never used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetirePayeeAccountResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/operating-models":{"get":{"operationId":"listOperatingModels","summary":"Every live unit with the operating model the ledger will actually post it under.","tags":["property-finance"],"responses":{"200":{"description":"Every live unit with the operating model the ledger will actually post it under.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOperatingModelsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/owners":{"get":{"operationId":"listOwners","summary":"Owner and landlord parties with the units they hold, plus units nobody owns.","tags":["property-finance"],"responses":{"200":{"description":"Owner and landlord parties with the units they hold, plus units nobody owns.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOwnersResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/owner-parties":{"post":{"operationId":"createOwnerParty","summary":"Create an owner or landlord party by name (get-or-create, idempotent).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOwnerPartyBody"}}}},"responses":{"201":{"description":"Create an owner or landlord party by name (get-or-create, idempotent).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOwnerPartyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/owner-user-links":{"post":{"operationId":"linkOwnerSeat","summary":"Bind an owner seat to the party it represents, by id.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkOwnerSeatBody"}}}},"responses":{"201":{"description":"Bind an owner seat to the party it represents, by id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkOwnerSeatResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/owner-holdings/unassign":{"post":{"operationId":"unassignOwnerHolding","summary":"Deactivate the agreement that grants an owner a unit or a whole property.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnassignOwnerHoldingBody"}}}},"responses":{"200":{"description":"Deactivate the agreement that grants an owner a unit or a whole property.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnassignOwnerHoldingResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/investor-assignments/{id}":{"delete":{"operationId":"revokeInvestorAssignment","summary":"Revoke (soft-delete) a live investor assignment.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"Revoke (soft-delete) a live investor assignment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/counterparties":{"get":{"operationId":"listCounterparties","summary":"The tenant’s counterparties of one kind, with whether each has a login.","tags":["property-finance"],"parameters":[{"in":"query","name":"kind","schema":{"type":"string","enum":["owner","landlord","investor"]},"required":true}],"responses":{"200":{"description":"The tenant’s counterparties of one kind, with whether each has a login.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CounterpartiesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/investor-user-links":{"post":{"operationId":"linkInvestorUser","summary":"Bind an investor login seat (task_only membership) to its party.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkInvestorUserBody"}}}},"responses":{"201":{"description":"Bind an investor login seat (task_only membership) to its party.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/track-record":{"get":{"operationId":"listTrackRecordSnapshots","summary":"Captured track-record snapshots, newest first (stored figures, never re-derived).","tags":["property-finance"],"responses":{"200":{"description":"Captured track-record snapshots, newest first (stored figures, never re-derived).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTrackRecordSnapshotsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"captureTrackRecordSnapshot","summary":"Freeze a citable track record over a window (figures derived server-side).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptureTrackRecordBody"}}}},"responses":{"201":{"description":"Freeze a citable track record over a window (figures derived server-side).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/deployment-plan":{"get":{"operationId":"readDeploymentPlan","summary":"Intended capital allocation reconciled against the asset register: plan · actual · variance.","tags":["property-finance"],"responses":{"200":{"description":"Intended capital allocation reconciled against the asset register: plan · actual · variance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentPlanResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"savePlanLine","summary":"Plan one cell of a party’s capital deployment. Upserted per (party, property, unit, category).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavePlanLineBody"}}}},"responses":{"200":{"description":"Plan one cell of a party’s capital deployment. Upserted per (party, property, unit, category).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/deals":{"get":{"operationId":"listInvestorDeals","summary":"The deal pipeline with each deal’s capital schedule and what has actually landed.","tags":["property-finance"],"responses":{"200":{"description":"The deal pipeline with each deal’s capital schedule and what has actually landed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInvestorDealsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createInvestorDeal","summary":"Open a deal at any pipeline stage. Moves no money.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveDealBody"}}}},"responses":{"201":{"description":"Open a deal at any pipeline stage. Moves no money.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/deals/{id}":{"patch":{"operationId":"updateInvestorDeal","summary":"Advance or amend a deal. Executed and beyond require a party AND an agreement.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveDealBody"}}}},"responses":{"200":{"description":"Advance or amend a deal. Executed and beyond require a party AND an agreement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/deals/{id}/tranches":{"post":{"operationId":"addCapitalTranche","summary":"Schedule an expected capital tranche. A promise with a date — it moves no money.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddTrancheBody"}}}},"responses":{"201":{"description":"Schedule an expected capital tranche. A promise with a date — it moves no money.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/deals/tranches/match":{"post":{"operationId":"matchCapitalTranche","summary":"Reconcile a tranche to a capital receipt that already posted. Writes one FK.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchTrancheBody"}}}},"responses":{"200":{"description":"Reconcile a tranche to a capital receipt that already posted. Writes one FK.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/deals/unmatched-contributions":{"get":{"operationId":"listUnmatchedContributions","summary":"Capital receipts with no tranche against them — the reconciliation pick-list.","tags":["property-finance"],"responses":{"200":{"description":"Capital receipts with no tranche against them — the reconciliation pick-list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUnmatchedContributionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/unit-launches":{"get":{"operationId":"listUnitLaunches","summary":"Every unit’s launch milestones, plus the \"N of M live\" roll-up per property.","tags":["property-finance"],"responses":{"200":{"description":"Every unit’s launch milestones, plus the \"N of M live\" roll-up per property.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUnitLaunchesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"saveUnitLaunch","summary":"Set a unit’s go-live target and stamp its milestones. Upserted per listing.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveUnitLaunchBody"}}}},"responses":{"200":{"description":"Set a unit’s go-live target and stamp its milestones. Upserted per listing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/unit-launches/ramp":{"get":{"operationId":"readObservedRamp","summary":"What the ramp ACTUALLY was — median days to live and variance against target.","tags":["property-finance"],"responses":{"200":{"description":"What the ramp ACTUALLY was — median days to live and variance against target.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObservedRampResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/proposals":{"get":{"operationId":"listProposals","summary":"Investor proposals, newest first, each with its live share link when one exists.","tags":["property-finance"],"responses":{"200":{"description":"Investor proposals, newest first, each with its live share link when one exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListProposalsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createProposal","summary":"Start a proposal draft (terms only — the figures come from generation).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveProposalBody"}}}},"responses":{"201":{"description":"Start a proposal draft (terms only — the figures come from generation).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/proposals/{id}":{"patch":{"operationId":"updateProposal","summary":"Edit a DRAFT proposal. A generated one refuses — revise it instead.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveProposalBody"}}}},"responses":{"200":{"description":"Edit a DRAFT proposal. A generated one refuses — revise it instead.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/proposals/{id}/generate":{"post":{"operationId":"generateProposal","summary":"Freeze the figures from the model + scenario. Server-derived; no figure is accepted.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Freeze the figures from the model + scenario. Server-derived; no figure is accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/proposals/{id}/send":{"post":{"operationId":"sendProposal","summary":"Mark sent and mint the expiring public link, atomically.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendProposalBody"}}}},"responses":{"200":{"description":"Mark sent and mint the expiring public link, atomically.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendProposalResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/proposals/{id}/revise":{"post":{"operationId":"reviseProposal","summary":"Mint version N+1 as a new draft and withdraw its predecessor.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"201":{"description":"Mint version N+1 as a new draft and withdraw its predecessor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviseProposalResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/proposals/{id}/decision":{"post":{"operationId":"decideProposal","summary":"Record accepted / declined / withdrawn; the public link dies with the decision.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideProposalBody"}}}},"responses":{"200":{"description":"Record accepted / declined / withdrawn; the public link dies with the decision.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/proposals/{id}/share":{"delete":{"operationId":"revokeProposalShare","summary":"Retract the live link without changing the proposal (the wrong-recipient case).","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Retract the live link without changing the proposal (the wrong-recipient case).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeProposalShareResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/track-record/preview":{"get":{"operationId":"previewTrackRecord","summary":"What a capture over this window would freeze right now — the confirm screen.","tags":["property-finance"],"parameters":[{"in":"query","name":"from","schema":{"type":"string"},"required":true},{"in":"query","name":"to","schema":{"type":"string"},"required":true}],"responses":{"200":{"description":"What a capture over this window would freeze right now — the confirm screen.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackRecordPreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/owner-party-links":{"post":{"operationId":"linkOwnerParty","summary":"Bind an owner seat to the party it represents (get-or-create by name).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkOwnerPartyBody"}}}},"responses":{"201":{"description":"Bind an owner seat to the party it represents (get-or-create by name).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/owner-portal":{"get":{"operationId":"getOwnerPortal","summary":"The signed-in property owner's listings, month-to-date share, and distributions.","tags":["owner-portal"],"parameters":[{"in":"query","name":"party","schema":{"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party."}],"responses":{"200":{"description":"The signed-in property owner's listings, month-to-date share, and distributions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerPortalResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/owner-portal/statements":{"get":{"operationId":"listMyOwnerStatements","summary":"The signed-in owner's frozen monthly statements, newest month first.","tags":["owner-portal"],"parameters":[{"in":"query","name":"party","schema":{"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party."}],"responses":{"200":{"description":"The signed-in owner's frozen monthly statements, newest month first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOwnerStatementsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/owner-portal/statements/{id}":{"get":{"operationId":"getOwnerStatementDetail","summary":"One frozen monthly statement with its per-booking lines — the own party's only.","tags":["owner-portal"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The statement id."},"required":true,"description":"The statement id."},{"in":"query","name":"party","schema":{"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"A staff preview of this party's portal. Only a seat that may open the owners and investors pages may name one; absent, the read is the seat's own party."}],"responses":{"200":{"description":"One frozen monthly statement with its per-booking lines — the own party's only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnerStatementDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/owners/payouts":{"post":{"operationId":"requestOwnerPayout","summary":"MAKER: request an owner distribution (ceiling-checked against the accrued share).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestOwnerPayoutBody"}}}},"responses":{"201":{"description":"MAKER: request an owner distribution (ceiling-checked against the accrued share).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/owners/payouts/{id}/decide":{"post":{"operationId":"decideOwnerPayout","summary":"CHECKER: approve — posts DR 2100 / CR store — or reject.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideOwnerPayoutBody"}}}},"responses":{"200":{"description":"CHECKER: approve — posts DR 2100 / CR store — or reject.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecideOwnerPayoutResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-claims":{"get":{"operationId":"listDamageClaims","summary":"The damage-claim book — what was asked, what was recovered, and what was refused.","tags":["treasury"],"responses":{"200":{"description":"The damage-claim book — what was asked, what was recovered, and what was refused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDamageClaimsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"fileDamageClaim","summary":"File a damage claim — posts NOTHING; the route is decided by the booking channel.","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileDamageClaimBody"}}}},"responses":{"201":{"description":"File a damage claim — posts NOTHING; the route is decided by the booking channel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileDamageClaimResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-claims/{id}/pending":{"post":{"operationId":"markDamageClaimPending","summary":"The channel acknowledged the claim. Still posts nothing.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkDamageClaimPendingBody"}}}},"responses":{"200":{"description":"The channel acknowledged the claim. Still posts nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkDamageClaimPendingResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-claims/{id}/pay":{"post":{"operationId":"payDamageClaim","summary":"Record what the claim actually recovered — DR the store / CR 4500.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayDamageClaimBody"}}}},"responses":{"200":{"description":"Record what the claim actually recovered — DR the store / CR 4500.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayDamageClaimResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/damage-claims/{id}/deny":{"post":{"operationId":"denyDamageClaim","summary":"The claim was refused, with its reason. Posts nothing — there was nothing to reverse.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DenyDamageClaimBody"}}}},"responses":{"200":{"description":"The claim was refused, with its reason. Posts nothing — there was nothing to reverse.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DenyDamageClaimResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/charges":{"post":{"operationId":"recordBookingCharge","summary":"Record a collected guest charge — posts DR store / CR 4010/4020/4500 atomically.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordBookingChargeBody"}}}},"responses":{"201":{"description":"Record a collected guest charge — posts DR store / CR 4010/4020/4500 atomically.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordBookingChargeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listBookingCharges","summary":"One booking's recorded charges, newest first.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"responses":{"200":{"description":"One booking's recorded charges, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBookingChargesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/charges":{"get":{"operationId":"listCharges","summary":"Every recorded guest charge in a date window, with per-kind totals.","tags":["treasury"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true},{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"kind","schema":{"type":"string","maxLength":40}},{"in":"query","name":"fineKey","schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"}}],"responses":{"200":{"description":"Every recorded guest charge in a date window, with per-kind totals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListChargesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/bookings/{id}/delete":{"post":{"operationId":"deleteDuplicateBooking","summary":"Delete a duplicate booking — releases its nights, keeps the audit trail.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicateBody"}}}},"responses":{"200":{"description":"Delete a duplicate booking — releases its nights, keeps the audit trail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicateBookingResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/inquiries/{id}/delete":{"post":{"operationId":"deleteDuplicateInquiry","summary":"Delete a duplicate inquiry — ends any hold, keeps the audit trail.","tags":["bookings"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicateBody"}}}},"responses":{"200":{"description":"Delete a duplicate inquiry — ends any hold, keeps the audit trail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicateInquiryResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payments/{id}/delete":{"post":{"operationId":"deleteDuplicatePayment","summary":"Delete a duplicate payment — posts the reversing journal, then hides the receipt.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicateBody"}}}},"responses":{"200":{"description":"Delete a duplicate payment — posts the reversing journal, then hides the receipt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicatePaymentResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/expenses/{id}/delete":{"post":{"operationId":"deleteDuplicateExpense","summary":"Delete a duplicate expense — posts the reversing journal, then hides the cost.","tags":["expenses"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicateBody"}}}},"responses":{"200":{"description":"Delete a duplicate expense — posts the reversing journal, then hides the cost.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDuplicateExpenseResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/charges/{id}/void":{"post":{"operationId":"voidBookingCharge","summary":"Void a collected charge — posts the reversing DR income / CR store entry.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidBookingChargeBody"}}}},"responses":{"200":{"description":"Void a collected charge — posts the reversing DR income / CR store entry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidBookingChargeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/fine-policies":{"get":{"operationId":"listHouseRuleFines","summary":"The §3.6 fine book (party / smoking amounts as config).","tags":["property-finance"],"responses":{"200":{"description":"The §3.6 fine book (party / smoking amounts as config).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListHouseRuleFinesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertHouseRuleFine","summary":"Set a fine's configured amount (property row overrides the tenant row).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertHouseRuleFineBody"}}}},"responses":{"201":{"description":"Set a fine's configured amount (property row overrides the tenant row).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/staff-compensation":{"get":{"operationId":"listStaffCompensation","summary":"The pay rules per staff seat (compensation-sensitive — org settings only).","tags":["staff-compensation"],"responses":{"200":{"description":"The pay rules per staff seat (compensation-sensitive — org settings only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStaffCompensationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertStaffCompensation","summary":"Set one seat's pay rule (base + allowances + add-on rates + third-party flag).","tags":["staff-compensation"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertStaffCompensationBody"}}}},"responses":{"201":{"description":"Set one seat's pay rule (base + allowances + add-on rates + third-party flag).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/preview":{"get":{"operationId":"getPayrollPreview","summary":"One month's computed pay per seat — posting rides recordExpense(salaries).","tags":["staff-compensation"],"parameters":[{"in":"query","name":"month","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"One month's computed pay per seat — posting rides recordExpense(salaries).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayrollPreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/assets":{"get":{"operationId":"listAssets","summary":"The itemized §3 asset register, funder-tagged, with cost totals per funder.","tags":["property-finance"],"parameters":[{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"The itemized §3 asset register, funder-tagged, with cost totals per funder.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAssetsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertAsset","summary":"Register (or correct) one asset line — category, funder, cost, sub-unit label.","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAssetBody"}}}},"responses":{"201":{"description":"Register (or correct) one asset line — category, funder, cost, sub-unit label.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAssetResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/leases/{id}/outlays":{"post":{"operationId":"recordLeaseOutlay","summary":"Post the deposit / advance rent paid to the landlord — DR 1520/1530, CR store.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordLeaseOutlayBody"}}}},"responses":{"201":{"description":"Post the deposit / advance rent paid to the landlord — DR 1520/1530, CR store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordLeaseOutlayResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/leases/{id}/terminate":{"post":{"operationId":"terminateLease","summary":"Terminate the lease and settle the deposit (refund vs withheld) in one journal.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id (UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The property id (UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerminateLeaseBody"}}}},"responses":{"200":{"description":"Terminate the lease and settle the deposit (refund vs withheld) in one journal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerminateLeaseResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/term-watch":{"get":{"operationId":"getTermWatch","summary":"Leases ending inside the §10 90-day notice window.","tags":["property-finance"],"responses":{"200":{"description":"Leases ending inside the §10 90-day notice window.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TermWatchResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pool-models":{"get":{"operationId":"listPoolModels","summary":"Saved pool models with their scenario columns, newest effective date first.","tags":["property-finance"],"parameters":[{"in":"query","name":"propertyId","schema":{"description":"Only this property’s models (portfolio-wide models are NOT included).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"Only this property’s models (portfolio-wide models are NOT included)."}],"responses":{"200":{"description":"Saved pool models with their scenario columns, newest effective date first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPoolModelsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createPoolModel","summary":"Save a new pool model and seed its three scenarios (conservative/expected/optimistic).","tags":["property-finance"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePoolModelBody"}}}},"responses":{"201":{"description":"Save a new pool model and seed its three scenarios (conservative/expected/optimistic).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePoolModelResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pool-models/{id}":{"get":{"operationId":"getPoolModel","summary":"One saved model with its scenarios. A cross-tenant id is a plain 404, never a leak.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The saved pool model’s id."},"required":true,"description":"The saved pool model’s id."}],"responses":{"200":{"description":"One saved model with its scenarios. A cross-tenant id is a plain 404, never a leak.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolModelView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updatePoolModel","summary":"Replace a saved model’s assumptions. Never touches the prefill provenance stamp.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The saved pool model’s id."},"required":true,"description":"The saved pool model’s id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePoolModelBody"}}}},"responses":{"200":{"description":"Replace a saved model’s assumptions. Never touches the prefill provenance stamp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolModelIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pool-models/{id}/scenarios":{"post":{"operationId":"upsertPoolModelScenario","summary":"Create or update one scenario column, keyed on its slug. Overrides are PUT-shaped.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The saved pool model’s id."},"required":true,"description":"The saved pool model’s id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertPoolModelScenarioBody"}}}},"responses":{"200":{"description":"Create or update one scenario column, keyed on its slug. Overrides are PUT-shaped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertPoolModelScenarioResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pool-models/{id}/prefill":{"post":{"operationId":"prefillPoolModel","summary":"Seed ADR / opex% / expected occupancy from the trailing ledger, and stamp the window.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The saved pool model’s id."},"required":true,"description":"The saved pool model’s id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrefillPoolModelBody"}}}},"responses":{"200":{"description":"Seed ADR / opex% / expected occupancy from the trailing ledger, and stamp the window.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrefillPoolModelResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/pool-models/{id}/projection":{"get":{"operationId":"getDealProjection","summary":"Size a deal against a saved model: units, split, per-scenario returns, loss preview.","tags":["property-finance"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The saved pool model’s id."},"required":true,"description":"The saved pool model’s id."},{"in":"query","name":"capitalMinor","schema":{"type":"string","pattern":"^\\d+$","description":"The investor’s capital, minor units in the MODEL’s currency."},"required":true,"description":"The investor’s capital, minor units in the MODEL’s currency."},{"in":"query","name":"unitSharePriceMinor","schema":{"type":"string","pattern":"^\\d+$","description":"What one whole unit (apartment) of the pool costs, minor units."},"required":true,"description":"What one whole unit (apartment) of the pool costs, minor units."},{"in":"query","name":"lossPreviewMinor","schema":{"type":"string","pattern":"^\\d+$"}}],"responses":{"200":{"description":"Size a deal against a saved model: units, split, per-scenario returns, loss preview.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealProjectionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/owners":{"get":{"operationId":"getOwnersOverview","summary":"Owners and landlords with their accrued share, pending and paid distributions.","tags":["treasury"],"parameters":[{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingTypeId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"listingId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"Owners and landlords with their accrued share, pending and paid distributions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnersOverviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/month-end-accruals":{"get":{"operationId":"previewMonthEndAccruals","summary":"The month's management fee and owner cost recharge per managed unit, and their state.","tags":["treasury"],"parameters":[{"in":"query","name":"month","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-01$"},"required":true}],"responses":{"200":{"description":"The month's management fee and owner cost recharge per managed unit, and their state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonthEndAccrualPreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postMonthEndAccruals","summary":"Post the month's owner accruals — the management fee and the owner cost recharge.","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostMonthEndAccrualsBody"}}}},"responses":{"201":{"description":"Post the month's owner accruals — the management fee and the owner cost recharge.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostMonthEndAccrualsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/depreciation":{"get":{"operationId":"previewDepreciation","summary":"The month's depreciation charge per asset, with net book value and posting state.","tags":["treasury"],"parameters":[{"in":"query","name":"month","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-01$"},"required":true}],"responses":{"200":{"description":"The month's depreciation charge per asset, with net book value and posting state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepreciationPreviewResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"postDepreciation","summary":"Post the month's depreciation — DR 6090 / CR 1590 per operator-funded asset.","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostDepreciationBody"}}}},"responses":{"201":{"description":"Post the month's depreciation — DR 6090 / CR 1590 per operator-funded asset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostDepreciationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/capital-notices":{"get":{"operationId":"listOutstandingCapitalNotices","summary":"Capital-structure notices no investor has acknowledged yet, oldest first.","tags":["treasury"],"responses":{"200":{"description":"Capital-structure notices no investor has acknowledged yet, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutstandingCapitalNoticesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/periods":{"get":{"operationId":"listPeriodCloses","summary":"The month-end close history — live closes and reopened rows, newest month first.","tags":["treasury"],"responses":{"200":{"description":"The month-end close history — live closes and reopened rows, newest month first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPeriodClosesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"closePeriod","summary":"Close one finished calendar month — freezes its GL (postings into it are rejected).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClosePeriodBody"}}}},"responses":{"201":{"description":"Close one finished calendar month — freezes its GL (postings into it are rejected).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/finance/periods/reopen":{"post":{"operationId":"reopenPeriod","summary":"Reopen a closed month (audited) so a correction can post into it.","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReopenPeriodBody"}}}},"responses":{"200":{"description":"Reopen a closed month (audited) so a correction can post into it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payables":{"get":{"operationId":"listPayableCalendar","summary":"The §7 payment calendar — this window's instances, due-order, with overdue flags.","tags":["treasury"],"parameters":[{"in":"query","name":"from","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"in":"query","name":"to","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"The §7 payment calendar — this window's instances, due-order, with overdue flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayableCalendarResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertScheduledPayable","summary":"Create or update a standing payment instruction (cadence, due day, route, payee).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertScheduledPayableBody"}}}},"responses":{"201":{"description":"Create or update a standing payment instruction (cadence, due day, route, payee).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payables/{id}/verify":{"post":{"operationId":"setPayableVerify","summary":"Confirm (or re-flag) a payable's figure — §9.7 verify-before-pay.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The scheduled payable or instance id."},"required":true,"description":"The scheduled payable or instance id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPayableVerifyBody"}}}},"responses":{"200":{"description":"Confirm (or re-flag) a payable's figure — §9.7 verify-before-pay.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payables/instances/{id}/settle":{"post":{"operationId":"settlePayableInstance","summary":"Settle (or skip) one calendar instance — the human hop before money leaves.","tags":["treasury"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The scheduled payable or instance id."},"required":true,"description":"The scheduled payable or instance id."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlePayableBody"}}}},"responses":{"200":{"description":"Settle (or skip) one calendar instance — the human hop before money leaves.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedIdResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payables/accruals":{"get":{"operationId":"previewPayableAccruals","summary":"Preview the recurring costs due to be accrued — posts nothing.","tags":["treasury"],"parameters":[{"in":"query","name":"asOf","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"Preview the recurring costs due to be accrued — posts nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewPayableAccrualsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"accrueDuePayables","summary":"Raise the accrued bill for every due recurring cost (DR category GL / CR 2200).","tags":["treasury"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccrueDuePayablesBody"}}}},"responses":{"200":{"description":"Raise the accrued bill for every due recurring cost (DR category GL / CR 2200).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccrueDuePayablesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payees":{"get":{"operationId":"getPayeeDirectory","summary":"The payee directory — who gets paid, how, and for which units.","tags":["treasury"],"responses":{"200":{"description":"The payee directory — who gets paid, how, and for which units.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayeeDirectoryResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/runs":{"post":{"operationId":"preparePayRun","summary":"Prepare (or re-prepare) a month's pay run. Snapshots every figure; posts nothing.","tags":["payroll"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreparePayRunBody"}}}},"responses":{"201":{"description":"Prepare (or re-prepare) a month's pay run. Snapshots every figure; posts nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreparePayRunResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listPayRuns","summary":"The pay-run history, newest month first.","tags":["payroll"],"responses":{"200":{"description":"The pay-run history, newest month first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPayRunsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/runs/{id}":{"get":{"operationId":"getPayRun","summary":"One pay run with its per-seat payslips and applied deductions.","tags":["payroll"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"One pay run with its per-seat payslips and applied deductions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetPayRunResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/runs/{id}/approve":{"post":{"operationId":"approvePayRun","summary":"Approve a draft run — accrues DR 6040 / CR 2400 + 2410 + 1210, dated to the month EARNED.","tags":["payroll"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovePayRunBody"}}}},"responses":{"200":{"description":"Approve a draft run — accrues DR 6040 / CR 2400 + 2410 + 1210, dated to the month EARNED.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovePayRunResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/runs/{id}/pay":{"post":{"operationId":"payPayRun","summary":"Pay an approved run: DR 2400 / CR the store. Never re-debits 6040.","tags":["payroll"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPayRunBody"}}}},"responses":{"200":{"description":"Pay an approved run: DR 2400 / CR the store. Never re-debits 6040.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayPayRunResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/runs/{id}/cancel":{"post":{"operationId":"cancelPayRun","summary":"Cancel a DRAFT run. An approved run is corrected by a reversing entry, never cancelled.","tags":["payroll"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelPayRunBody"}}}},"responses":{"200":{"description":"Cancel a DRAFT run. An approved run is corrected by a reversing entry, never cancelled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelPayRunResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/withholding":{"get":{"operationId":"getWithholdingPosition","summary":"What is still owed to the authority on 2410, derived from the ledger.","tags":["payroll"],"responses":{"200":{"description":"What is still owed to the authority on 2410, derived from the ledger.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithholdingPositionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/withholding/remit":{"post":{"operationId":"remitWithholding","summary":"Hand withheld tax to the authority: DR 2410 / CR the store. Refuses to over-remit.","tags":["payroll"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemitWithholdingBody"}}}},"responses":{"200":{"description":"Hand withheld tax to the authority: DR 2410 / CR the store. Refuses to over-remit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemitWithholdingResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/deductions":{"get":{"operationId":"listStaffDeductions","summary":"Every seat's outstanding advances, loans and fines.","tags":["payroll"],"parameters":[{"in":"query","name":"includeSettled","schema":{"type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Every seat's outstanding advances, loans and fines.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStaffDeductionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"recordStaffDeduction","summary":"Record something a seat owes back. An advance posts DR 1210 / CR store; a fine posts nothing.","tags":["payroll"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordStaffDeductionBody"}}}},"responses":{"201":{"description":"Record something a seat owes back. An advance posts DR 1210 / CR store; a fine posts nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordStaffDeductionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/payroll/tax-tables":{"get":{"operationId":"listPayrollTaxTables","summary":"The tenant's own withholding slab tables, newest first.","tags":["staff-compensation"],"responses":{"200":{"description":"The tenant's own withholding slab tables, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPayrollTaxTablesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertPayrollTaxTable","summary":"Save a withholding slab table. Refuses a table with a gap before writing anything.","tags":["staff-compensation"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertPayrollTaxTableBody"}}}},"responses":{"200":{"description":"Save a withholding slab table. Refuses a table with a gap before writing anything.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertPayrollTaxTableResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/accounting/fx-rates":{"post":{"operationId":"recordFxRate","summary":"Record an observed FX rate. Config a money read depends on, so it is nameable later.","tags":["fx"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordFxRateBody"}}}},"responses":{"201":{"description":"Record an observed FX rate. Config a money read depends on, so it is nameable later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordFxRateResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/accounting/fx-revaluations":{"post":{"operationId":"revaluateFx","summary":"Revalue every foreign store at the month-end rate; the difference posts to 4950. Idempotent per month.","tags":["fx"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevaluateFxBody"}}}},"responses":{"200":{"description":"Revalue every foreign store at the month-end rate; the difference posts to 4950. Idempotent per month.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevaluateFxResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listFxRevaluations","summary":"A month's revaluation history: what was restated, at what rate, for what difference.","tags":["fx"],"parameters":[{"in":"query","name":"month","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}$"},"required":true}],"responses":{"200":{"description":"A month's revaluation history: what was restated, at what rate, for what difference.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListFxRevaluationsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/investors/unit-transfers":{"post":{"operationId":"recordUnitTransfer","summary":"A secondary unit sale's consideration. The route decides the postings; a direct operator sale posts nothing.","tags":["unit-transfers"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordUnitTransferBody"}}}},"responses":{"201":{"description":"A secondary unit sale's consideration. The route decides the postings; a direct operator sale posts nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordUnitTransferResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"listUnitTransfers","summary":"The secondary-sale history: who sold what to whom, for how much, by which route.","tags":["unit-transfers"],"parameters":[{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"responses":{"200":{"description":"The secondary-sale history: who sold what to whom, for how much, by which route.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUnitTransfersResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agent-requests/upload":{"post":{"operationId":"requestAgentRequestUpload","summary":"Presign a PUT for one agent-request attachment (a screenshot, mock-up or export).","tags":["agent-requests"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestAgentRequestUploadBody"}}}},"responses":{"200":{"description":"Presign a PUT for one agent-request attachment (a screenshot, mock-up or export).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestAgentRequestUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/agent-requests":{"post":{"operationId":"submitAgentRequest","summary":"Ask for an automation the Agent Hub does not offer yet, with any attached files.","tags":["agent-requests"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitAgentRequestBody"}}}},"responses":{"201":{"description":"Ask for an automation the Agent Hub does not offer yet, with any attached files.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitAgentRequestResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/feedback/upload":{"post":{"operationId":"requestFeedbackUpload","summary":"Presign a PUT for one feedback image (the auto page screenshot or a manual attachment).","tags":["feedback"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestFeedbackUploadBody"}}}},"responses":{"200":{"description":"Presign a PUT for one feedback image (the auto page screenshot or a manual attachment).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestFeedbackUploadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/feedback":{"post":{"operationId":"submitFeedback","summary":"File a product-feedback report (bug/improvement) with page context + uploaded image keys.","tags":["feedback"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitFeedbackBody"}}}},"responses":{"201":{"description":"File a product-feedback report (bug/improvement) with page context + uploaded image keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitFeedbackResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/support":{"get":{"operationId":"listSupportThreads","summary":"List the support threads this seat may see (own reports; the whole workspace for an admin seat).","tags":["support"],"responses":{"200":{"description":"List the support threads this seat may see (own reports; the whole workspace for an admin seat).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSupportThreadsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/support/{id}":{"get":{"operationId":"getSupportThread","summary":"Read one support thread with its messages and short-lived signed image URLs.","tags":["support"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The support thread id (the underlying report UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The support thread id (the underlying report UUID)."}],"responses":{"200":{"description":"Read one support thread with its messages and short-lived signed image URLs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportThreadResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/support/{id}/messages":{"post":{"operationId":"postSupportMessage","summary":"Reply on a support thread, optionally with uploaded image keys.","tags":["support"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The support thread id (the underlying report UUID).","example":"11111111-1111-4111-8111-111111111111"},"required":true,"description":"The support thread id (the underlying report UUID)."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostSupportMessageBody"}}}},"responses":{"201":{"description":"Reply on a support thread, optionally with uploaded image keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostSupportMessageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/app":{"get":{"operationId":"getGuestAppTenant","summary":"Read the workspace's one guest app (null until a property is set up).","tags":["guest-app"],"responses":{"200":{"description":"Read the workspace's one guest app (null until a property is set up).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetGuestAppTenantResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateGuestAppTenant","summary":"Replace the workspace's guest-app identity (whole-object; null clears).","tags":["guest-app"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGuestAppTenantBody"}}}},"responses":{"200":{"description":"Replace the workspace's guest-app identity (whole-object; null clears).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAppTenantResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/config":{"get":{"operationId":"getGuestAppConfig","summary":"Read one property's guest-app configuration (null until first ensured).","tags":["guest-app"],"parameters":[{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Read one property's guest-app configuration (null until first ensured).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetGuestAppConfigResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"ensureGuestAppConfig","summary":"Find-or-mint the guest-app config row for a property (idempotent; starts disabled).","tags":["guest-app"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnsureGuestAppConfigBody"}}}},"responses":{"200":{"description":"Find-or-mint the guest-app config row for a property (idempotent; starts disabled).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAppConfigResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/config/{id}":{"patch":{"operationId":"updateGuestAppConfig","summary":"Replace a property's guest-app configuration (whole-object; null clears).","tags":["guest-app"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGuestAppConfigBody"}}}},"responses":{"200":{"description":"Replace a property's guest-app configuration (whole-object; null clears).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAppConfigResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/logo/upload-url":{"post":{"operationId":"requestGuestAppLogoUpload","summary":"Presign a PUT for a property's app-icon logo (png/jpeg only). Writes no row.","tags":["guest-app"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestGuestAppLogoUploadBody"}}}},"responses":{"200":{"description":"Presign a PUT for a property's app-icon logo (png/jpeg only). Writes no row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoUploadTicket"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/logo":{"post":{"operationId":"setGuestAppLogo","summary":"Bind an uploaded object as a property's app-icon logo.","tags":["guest-app"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetGuestAppLogoBody"}}}},"responses":{"200":{"description":"Bind an uploaded object as a property's app-icon logo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAppOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/logo/clear":{"post":{"operationId":"clearGuestAppLogo","summary":"Drop a property's app-icon logo (falls back to the site logo, then the monogram).","tags":["guest-app"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearGuestAppLogoBody"}}}},"responses":{"200":{"description":"Drop a property's app-icon logo (falls back to the site logo, then the monogram).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAppOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/pages":{"get":{"operationId":"listGuestAppPages","summary":"List a property's guest-app content pages (drafts included).","tags":["guest-app"],"parameters":[{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"List a property's guest-app content pages (drafts included).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListGuestAppPagesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createGuestAppPage","summary":"Create a guest-app content page (home tile or Info A–Z category/article).","tags":["guest-app"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGuestAppPageBody"}}}},"responses":{"201":{"description":"Create a guest-app content page (home tile or Info A–Z category/article).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAppPageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/pages/{id}":{"patch":{"operationId":"updateGuestAppPage","summary":"Update a guest-app content page (whole-object; section/property never move).","tags":["guest-app"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGuestAppPageBody"}}}},"responses":{"200":{"description":"Update a guest-app content page (whole-object; section/property never move).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestAppPageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/pages/{id}/delete":{"post":{"operationId":"deleteGuestAppPage","summary":"Soft-delete a guest-app content page (refuses while live children exist).","tags":["guest-app"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Soft-delete a guest-app content page (refuses while live children exist).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteGuestAppPageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/checkins":{"get":{"operationId":"listGuestCheckins","summary":"List guest self check-in submissions (newest first, optionally one property).","tags":["guest-app"],"parameters":[{"in":"query","name":"propertyId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"List guest self check-in submissions (newest first, optionally one property).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListGuestCheckinsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/checkins/{id}":{"get":{"operationId":"getGuestCheckin","summary":"One self check-in submission with its per-guest identity rows.","tags":["guest-app"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"One self check-in submission with its per-guest identity rows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCheckinDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/guest-app/checkins/{id}/signature-url":{"post":{"operationId":"mintGuestCheckinSignatureUrl","summary":"Mint a 120s presigned GET for a check-in's finger-drawn signature.","tags":["guest-app"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Mint a 120s presigned GET for a check-in's finger-drawn signature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCheckinSignatureUrlResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/access":{"get":{"operationId":"getAccessOverview","summary":"Every unit's Wi-Fi, door and arrival instructions, with the gaps (0441).","tags":["guest-app"],"responses":{"200":{"description":"Every unit's Wi-Fi, door and arrival instructions, with the gaps (0441).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessOverview"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/access/units/{id}/wifi":{"patch":{"operationId":"setUnitWifi","summary":"Set a unit's own Wi-Fi over its property's (both null clears it).","tags":["guest-app"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetUnitWifiBody"}}}},"responses":{"200":{"description":"Set a unit's own Wi-Fi over its property's (both null clears it).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/access/properties/{id}":{"patch":{"operationId":"updatePropertyAccess","summary":"Edit a property's Wi-Fi, door or arrival text (through its guest-app config).","tags":["guest-app"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePropertyAccessBody"}}}},"responses":{"200":{"description":"Edit a property's Wi-Fi, door or arrival text (through its guest-app config).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/access/wifi-rotation":{"post":{"operationId":"rotateWifi","summary":"Rotate the Wi-Fi key of a selection of units and properties, all or nothing.","tags":["guest-app"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateWifiBody"}}}},"responses":{"200":{"description":"Rotate the Wi-Fi key of a selection of units and properties, all or nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateWifiResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site":{"get":{"operationId":"getSite","summary":"Read the workspace's booking site and its property scope (null until first ensured).","tags":["site"],"responses":{"200":{"description":"Read the workspace's booking site and its property scope (null until first ensured).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSiteResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"ensureSite","summary":"Find-or-mint the workspace's booking site (idempotent; starts as a draft).","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnsureSiteBody"}}}},"responses":{"200":{"description":"Find-or-mint the workspace's booking site (idempotent; starts as a draft).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/{id}":{"patch":{"operationId":"updateSite","summary":"Replace the booking site's settings and theme (whole-object; publishing gated).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSiteBody"}}}},"responses":{"200":{"description":"Replace the booking site's settings and theme (whole-object; publishing gated).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/logo/upload-url":{"post":{"operationId":"requestSiteLogoUpload","summary":"Presign a PUT for the site logo / tenant-app icon (png/jpeg only). Writes no row.","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestSiteLogoUploadBody"}}}},"responses":{"200":{"description":"Presign a PUT for the site logo / tenant-app icon (png/jpeg only). Writes no row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoUploadTicket"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/logo":{"post":{"operationId":"setSiteLogo","summary":"Bind an uploaded object as the site logo / tenant-app icon.","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSiteLogoBody"}}}},"responses":{"200":{"description":"Bind an uploaded object as the site logo / tenant-app icon.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"clearSiteLogo","summary":"Drop the site logo (falls back to the white-label mark, then a monogram).","tags":["site"],"responses":{"200":{"description":"Drop the site logo (falls back to the white-label mark, then a monogram).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteOk"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/tracking":{"patch":{"operationId":"updateSiteTracking","summary":"Set or clear the site’s GA4, GTM and Meta pixel ids. Nothing loads on the public site until a visitor consents.","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSiteTrackingBody"}}}},"responses":{"200":{"description":"Set or clear the site’s GA4, GTM and Meta pixel ids. Nothing loads on the public site until a visitor consents.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/domain":{"get":{"operationId":"getSiteCustomDomain","summary":"The tenant's own domain for their booking site, and its DNS-TXT proof state.","tags":["site"],"responses":{"200":{"description":"The tenant's own domain for their booking site, and its DNS-TXT proof state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCustomDomainResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setSiteCustomDomain","summary":"Claim a domain and mint its DNS-TXT challenge. Proves nothing and serves nothing yet.","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetSiteCustomDomainBody"}}}},"responses":{"200":{"description":"Claim a domain and mint its DNS-TXT challenge. Proves nothing and serves nothing yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCustomDomainResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"clearSiteCustomDomain","summary":"Drop the claim. Takes a live site off that domain immediately and frees the name.","tags":["site"],"responses":{"200":{"description":"Drop the claim. Takes a live site off that domain immediately and frees the name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCustomDomainResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/domain/verify":{"post":{"operationId":"verifySiteCustomDomain","summary":"Look for the challenge in the zone and, if it is there, record the proof. A failed check is a state, not an error.","tags":["site"],"responses":{"200":{"description":"Look for the challenge in the zone and, if it is there, record the proof. A failed check is a state, not an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCustomDomainResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/properties":{"post":{"operationId":"addSiteProperty","summary":"Put a property on the booking site (slug defaults to a derivation of its name).","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSitePropertyBody"}}}},"responses":{"201":{"description":"Put a property on the booking site (slug defaults to a derivation of its name).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePropertyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/properties/{id}":{"patch":{"operationId":"updateSiteProperty","summary":"Replace a site property's slug, copy, order and published state (whole-object).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSitePropertyBody"}}}},"responses":{"200":{"description":"Replace a site property's slug, copy, order and published state (whole-object).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePropertyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeSiteProperty","summary":"Take a property off the booking site (soft delete; the trail keeps what was public).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Take a property off the booking site (soft delete; the trail keeps what was public).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveSitePropertyResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/room-content":{"get":{"operationId":"listSiteRoomContent","summary":"Every room type on the site, each with the operator's own copy where they have written it.","tags":["site"],"responses":{"200":{"description":"Every room type on the site, each with the operator's own copy where they have written it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSiteRoomContentResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"upsertSiteRoomContent","summary":"Write one room type's own copy, bed breakdown and equipment list (upsert).","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSiteRoomContentBody"}}}},"responses":{"200":{"description":"Write one room type's own copy, bed breakdown and equipment list (upsert).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteRoomContentResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/room-content/{id}":{"delete":{"operationId":"removeSiteRoomContent","summary":"Drop a room's own copy and fall back to the inventory's. Does not delist the room.","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Drop a room's own copy and fall back to the inventory's. Does not delist the room.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveSiteRoomContentResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/promo-codes":{"get":{"operationId":"listSitePromoCodes","summary":"Every promo campaign on the booking site, with its redemption count.","tags":["site"],"responses":{"200":{"description":"Every promo campaign on the booking site, with its redemption count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSitePromoCodesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createSitePromoCode","summary":"Create a promo campaign. Configuration only; it moves no money.","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSitePromoCodeBody"}}}},"responses":{"201":{"description":"Create a promo campaign. Configuration only; it moves no money.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePromoCodeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/promo-codes/{id}":{"patch":{"operationId":"updateSitePromoCode","summary":"Edit a promo campaign. Never restates a discount already given to a guest.","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSitePromoCodeBody"}}}},"responses":{"200":{"description":"Edit a promo campaign. Never restates a discount already given to a guest.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePromoCodeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteSitePromoCode","summary":"Retire a promo campaign (soft delete; redeemed bookings keep their discount).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Retire a promo campaign (soft delete; redeemed bookings keep their discount).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveSitePromoCodeResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/pages":{"get":{"operationId":"listSitePages","summary":"List the booking site’s authored pages (drafts included).","tags":["site"],"responses":{"200":{"description":"List the booking site’s authored pages (drafts included).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSitePagesResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createSitePage","summary":"Create an authored page (born unpublished).","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSitePageBody"}}}},"responses":{"201":{"description":"Create an authored page (born unpublished).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/pages/{id}":{"get":{"operationId":"getSitePage","summary":"Read one authored page with its blocks (drafts included).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Read one authored page with its blocks (drafts included).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePageDetailResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"updateSitePage","summary":"Replace an authored page (whole-object; publishing gated on a published block).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSitePageBody"}}}},"responses":{"200":{"description":"Replace an authored page (whole-object; publishing gated on a published block).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SitePageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteSitePage","summary":"Soft-delete an authored page (refuses while it still holds blocks).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Soft-delete an authored page (refuses while it still holds blocks).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteSitePageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/collections":{"get":{"operationId":"listSiteCollections","summary":"List the booking site’s curated collections (drafts included).","tags":["site"],"responses":{"200":{"description":"List the booking site’s curated collections (drafts included).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSiteCollectionsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createSiteCollection","summary":"Create a curated collection (born unpublished).","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSiteCollectionBody"}}}},"responses":{"201":{"description":"Create a curated collection (born unpublished).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCollectionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/collections/{id}":{"patch":{"operationId":"updateSiteCollection","summary":"Replace a collection (whole-object; includes publish/unpublish and the saved filter).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSiteCollectionBody"}}}},"responses":{"200":{"description":"Replace a collection (whole-object; includes publish/unpublish and the saved filter).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteCollectionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteSiteCollection","summary":"Soft-delete a collection. Its public URL stops resolving; the trail stays.","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Soft-delete a collection. Its public URL stops resolving; the trail stays.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteSiteCollectionResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/blocks":{"post":{"operationId":"createSiteBlock","summary":"Append a typed content block to a page (payload validated in the domain).","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSiteBlockBody"}}}},"responses":{"201":{"description":"Append a typed content block to a page (payload validated in the domain).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteBlockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/blocks/{id}":{"patch":{"operationId":"updateSiteBlock","summary":"Replace a block’s payload, order and visibility (kind is immutable).","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSiteBlockBody"}}}},"responses":{"200":{"description":"Replace a block’s payload, order and visibility (kind is immutable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteBlockResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"deleteSiteBlock","summary":"Soft-delete a content block.","tags":["site"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Soft-delete a content block.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteSitePageResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/tax/rules":{"get":{"operationId":"listTaxRules","summary":"Every tax rule, the ones in force first.","tags":["tax"],"responses":{"200":{"description":"Every tax rule, the ones in force first.","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/TaxRuleView"}}},"required":["rules"],"additionalProperties":false}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createTaxRule","summary":"Author a new tax rule.","tags":["tax"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTaxRuleBody"}}}},"responses":{"201":{"description":"Author a new tax rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRuleView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/tax/rules/supersede":{"post":{"operationId":"supersedeTaxRule","summary":"Close the standing rule and open its replacement. A rate change is never an edit.","tags":["tax"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupersedeTaxRuleBody"}}}},"responses":{"201":{"description":"Close the standing rule and open its replacement. A rate change is never an edit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaxRuleView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/tax/rules/retire":{"post":{"operationId":"retireTaxRule","summary":"Stop a rule with no replacement — a levy that was abolished. Closes; never deletes.","tags":["tax"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetireTaxRuleBody"}}}},"responses":{"200":{"description":"Stop a rule with no replacement — a levy that was abolished. Closes; never deletes.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/tax/assess":{"post":{"operationId":"assessBookingTax","summary":"Assess one booking against the rules in force and freeze the lines.","tags":["tax"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssessBookingTaxBody"}}}},"responses":{"200":{"description":"Assess one booking against the rules in force and freeze the lines.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingTaxView"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/tax/post":{"post":{"operationId":"postBookingTax","summary":"Post the assessed tax: DR the deferred pool, CR the tax liabilities.","tags":["tax-posting"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostBookingTaxBody"}}}},"responses":{"200":{"description":"Post the assessed tax: DR the deferred pool, CR the tax liabilities.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostBookingTaxResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/tenant-settings":{"get":{"operationId":"listTenantSettings","summary":"Every declared workspace setting, with its resolved value.","tags":["tenant-settings"],"responses":{"200":{"description":"Every declared workspace setting, with its resolved value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTenantSettingsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"setTenantSetting","summary":"Set ONE declared setting. A gate key is refused.","tags":["tenant-settings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantSettingBody"}}}},"responses":{"200":{"description":"Set ONE declared setting. A gate key is refused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTenantSettingResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/page-views":{"post":{"operationId":"recordPageViews","summary":"Record a batch of in-app page views. Paths are resolved to route TEMPLATES server-side; a path matching no served route is dropped.","tags":["page-views"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordPageViewsBody"}}}},"responses":{"200":{"description":"Record a batch of in-app page views. Paths are resolved to route TEMPLATES server-side; a path matching no served route is dropped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordPageViewsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/terms-acceptances":{"get":{"operationId":"getTermsStatus","summary":"The legal documents the asking person still has to accept in this workspace.","tags":["terms"],"responses":{"200":{"description":"The legal documents the asking person still has to accept in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TermsStatusResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"acceptTerms","summary":"Accept the current version of the named documents (customer terms need org settings).","tags":["terms"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptTermsBody"}}}},"responses":{"200":{"description":"Accept the current version of the named documents (customer terms need org settings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptTermsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/site/translations":{"get":{"operationId":"listContentTranslations","summary":"Every translatable text on the site and guest app, with its translation into a locale.","tags":["site"],"parameters":[{"in":"query","name":"locale","schema":{"type":"string","enum":["ar","de","es","fr","it","pt","ru","tr","ur","zh"]},"required":true}],"responses":{"200":{"description":"Every translatable text on the site and guest app, with its translation into a locale.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListContentTranslationsResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"operationId":"setContentTranslation","summary":"Write a translation by hand. The automatic translation never overwrites it.","tags":["site"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetContentTranslationBody"}}}},"responses":{"200":{"description":"Write a translation by hand. The automatic translation never overwrites it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentTranslationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeContentTranslation","summary":"Drop a hand-written translation; the automatic one returns on the next pass.","tags":["site"],"parameters":[{"in":"query","name":"entityType","schema":{"type":"string","enum":["tenant_site","tenant_site_property","property","listing_type","site_room_content","site_page","site_block","site_collection","guest_app_config","guest_app_page"]},"required":true},{"in":"query","name":"entityId","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"field","schema":{"type":"string","minLength":1,"maxLength":40},"required":true},{"in":"query","name":"locale","schema":{"type":"string","enum":["ar","de","es","fr","it","pt","ru","tr","ur","zh"]},"required":true}],"responses":{"200":{"description":"Drop a hand-written translation; the automatic one returns on the next pass.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveContentTranslationResponse"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/api-keys":{"get":{"operationId":"listApiKeys","summary":"Every workspace API key (never the token itself) and the scopes the caller may grant.","tags":["api-keys"],"responses":{"200":{"description":"Every workspace API key (never the token itself) and the scopes the caller may grant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeysPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createApiKey","summary":"Create an API key with scopes the caller holds. The token is returned once.","tags":["api-keys"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyBody"}}}},"responses":{"201":{"description":"Create an API key with scopes the caller holds. The token is returned once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedApiKey"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/api-keys/{id}/revoke":{"post":{"operationId":"revokeApiKey","summary":"Revoke an API key; it stops working on its next request.","tags":["api-keys"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Revoke an API key; it stops working on its next request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhooks":{"get":{"operationId":"listWebhooks","summary":"Every webhook endpoint with its last delivery, and the events it may subscribe to.","tags":["webhooks"],"responses":{"200":{"description":"Every webhook endpoint with its last delivery, and the events it may subscribe to.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"createWebhook","summary":"Register a webhook endpoint (https only). The signing key is returned once.","tags":["webhooks"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointBody"}}}},"responses":{"201":{"description":"Register a webhook endpoint (https only). The signing key is returned once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookWithSecret"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhooks/{id}":{"patch":{"operationId":"updateWebhook","summary":"Replace a webhook endpoint's name, URL, events and switches.","tags":["webhooks"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointBody"}}}},"responses":{"200":{"description":"Replace a webhook endpoint's name, URL, events and switches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removeWebhook","summary":"Remove a webhook endpoint; anything still queued for it is dropped.","tags":["webhooks"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Remove a webhook endpoint; anything still queued for it is dropped.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhooks/{id}/rotate-signing-key":{"post":{"operationId":"rotateWebhookSecret","summary":"Replace the signing key. The new one is returned once.","tags":["webhooks"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Replace the signing key. The new one is returned once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookWithSecret"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhooks/{id}/test":{"post":{"operationId":"sendTestWebhook","summary":"Queue a harmless test event to the endpoint.","tags":["webhooks"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"201":{"description":"Queue a harmless test event to the endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhooks/{id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"The delivery log of one endpoint, newest first, 50 at a time.","tags":["webhooks"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true},{"in":"query","name":"before","schema":{"type":"string","maxLength":40}}],"responses":{"200":{"description":"The delivery log of one endpoint, newest first, 50 at a time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveriesPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhook-deliveries/{id}":{"get":{"operationId":"getWebhookDelivery","summary":"One delivery with the exact JSON body that was signed and sent.","tags":["webhooks"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"One delivery with the exact JSON body that was signed and sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/webhook-deliveries/{id}/resend":{"post":{"operationId":"resendWebhookDelivery","summary":"Send a delivery again: the same body, signed afresh, as a new log row.","tags":["webhooks"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"201":{"description":"Send a delivery again: the same body, signed afresh, as a new log row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/accounting-export":{"get":{"operationId":"getAccountingExport","summary":"The chart of accounts, the Xero and QuickBooks account map, and the export history.","tags":["accounting-export"],"responses":{"200":{"description":"The chart of accounts, the Xero and QuickBooks account map, and the export history.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingExportPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/accounting-export/mappings":{"patch":{"operationId":"setAccountMappings","summary":"Set or clear how our accounts map to Xero or QuickBooks codes.","tags":["accounting-export"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetAccountMappingsBody"}}}},"responses":{"200":{"description":"Set or clear how our accounts map to Xero or QuickBooks codes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountMappingsChanged"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/accounting-export/exports":{"post":{"operationId":"createAccountingExport","summary":"Export one period of journals as a Xero or QuickBooks import file. Reads the ledger only.","tags":["accounting-export"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccountingExportBody"}}}},"responses":{"201":{"description":"Export one period of journals as a Xero or QuickBooks import file. Reads the ledger only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedAccountingExport"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/accounting-export/exports/{id}/file":{"get":{"operationId":"getAccountingExportFile","summary":"The file of an earlier export, exactly as it was produced.","tags":["accounting-export"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"The file of an earlier export, exactly as it was produced.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingExportFile"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/push-devices":{"get":{"operationId":"listPushDevices","summary":"The browsers this seat receives push notifications on, and the server key to subscribe with.","tags":["push-devices"],"responses":{"200":{"description":"The browsers this seat receives push notifications on, and the server key to subscribe with.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushDevicesPage"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"operationId":"subscribePushDevice","summary":"Opt this browser in to push notifications for this seat.","tags":["push-devices"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushSubscribeBody"}}}},"responses":{"201":{"description":"Opt this browser in to push notifications for this seat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/push-devices/{id}":{"patch":{"operationId":"updatePushDevice","summary":"Rename a device or choose which notification categories reach it.","tags":["push-devices"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushDeviceUpdateBody"}}}},"responses":{"200":{"description":"Rename a device or choose which notification categories reach it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"removePushDevice","summary":"Stop push notifications on one device.","tags":["push-devices"],"parameters":[{"in":"path","name":"id","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"required":true}],"responses":{"200":{"description":"Stop push notifications on one device.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationId"}}}},"400":{"description":"Validation failed (malformed body/query/path).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthenticated (no session or no bound tenant).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not found (or access denied — indistinguishable, no existence leak).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (duplicate code / already archived / has live listings).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (request body exceeds the size cap).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal error (no internals leaked).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"AgentConditions":{"type":"object","properties":{"excludeProperties":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"channels":{"type":"array","items":{"type":"string"}},"excludeChannels":{"type":"array","items":{"type":"string"}},"advanceNotice":{"type":"string","enum":["any","same_day","at_least_days"]},"advanceNoticeDays":{"type":"integer","minimum":0,"maximum":3650},"stayLength":{"type":"string","enum":["any","single_night","multiple_nights"]},"guestsMin":{"type":"integer","minimum":0,"maximum":99},"guestsMax":{"type":"integer","minimum":0,"maximum":99},"returningGuest":{"type":"boolean"},"idVerified":{"type":"boolean"},"nightsFreeAfterMin":{"type":"integer","minimum":0,"maximum":3650},"nightsFreeAfterMax":{"type":"integer","minimum":0,"maximum":3650}},"additionalProperties":false},"AskDocsBody":{"type":"object","properties":{"question":{"type":"string","minLength":1,"maxLength":500,"description":"The operator question, as typed. Ranked against the help centre."}},"required":["question"],"additionalProperties":false},"MarkAllNotificationsReadBody":{"type":"object","properties":{"asOf":{"type":"string","description":"Mark read only up to this instant — the newest the client actually displayed."}},"required":["asOf"],"additionalProperties":false},"SetNotificationPreferenceBody":{"type":"object","properties":{"scope":{"type":"string","enum":["seat","tenant"]},"activeSeverities":{"maxItems":3,"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"badgeSeverities":{"maxItems":3,"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"mutedKinds":{"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":100}}},"required":["scope","activeSeverities","badgeSeverities"],"additionalProperties":false},"CreatePropertyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Human-facing property name.","example":"Seaview Apartments"},"code":{"type":"string","minLength":1,"description":"Tenant-unique property code (uppercased; backs the unique key; editable post-create).","example":"SV-01"},"checkInTime":{"description":"Default check-in time (HH:MM).","example":"15:00","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"checkOutTime":{"description":"Default check-out time (HH:MM).","example":"11:00","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"propertyType":{"description":"The property type (absent → the apartment default).","example":"villa","type":"string","enum":["apartment","suite","loft","house","studio","villa","multi_unit","complex","hotel","hostel"]},"channelSyncMode":{"description":"How this property sells on booking channels: unit = each listing is its own channel property; pool = room classes (hotel/hostel/villa). Absent → derived from the property type. Locked once channel sync is provisioned.","example":"unit","type":"string","enum":["unit","pool"]},"location":{"$ref":"#/components/schemas/PropertyLocationCreateInput"},"managerMembershipId":{"description":"The INFORMATIONAL manager membership id (null → unassigned).","example":"22222222-2222-4222-8222-222222222222","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"reception":{"description":"The structured reception contact (all fields optional; absent → none).","$ref":"#/components/schemas/PropertyReceptionInput"}},"required":["name","code","location"],"additionalProperties":false,"description":"Fields to create a property (id is server-minted)."},"PropertyLocationCreateInput":{"type":"object","properties":{"addressLine":{"description":"Freeform street line.","example":"1 Sea Road","type":"string","minLength":1},"city":{"description":"City tier.","example":"Kreuzberg","type":"string","minLength":1},"region":{"description":"State/province/region.","example":"Berlin","type":"string","minLength":1},"area":{"description":"District within the city.","example":"Clifton","type":"string","minLength":1},"countryCode":{"description":"ISO-3166-1 alpha-2 country code (2 uppercase letters).","example":"DE","type":"string","pattern":"^[A-Z]{2}$"},"latitude":{"description":"WGS84 latitude in [-90, 90].","example":52.520008,"type":"number","minimum":-90,"maximum":90},"longitude":{"description":"WGS84 longitude in [-180, 180].","example":13.404954,"type":"number","minimum":-180,"maximum":180}},"additionalProperties":false,"description":"The structured location on a create body — city is required.","$ref":"#/components/schemas/PropertyLocationInput"},"PropertyLocationInput":{"type":"object","properties":{"addressLine":{"description":"Freeform street line.","example":"1 Sea Road","type":"string","minLength":1},"city":{"description":"City tier.","example":"Kreuzberg","type":"string","minLength":1},"region":{"description":"State/province/region.","example":"Berlin","type":"string","minLength":1},"area":{"description":"District within the city.","example":"Clifton","type":"string","minLength":1},"countryCode":{"description":"ISO-3166-1 alpha-2 country code (2 uppercase letters).","example":"DE","type":"string","pattern":"^[A-Z]{2}$"},"latitude":{"description":"WGS84 latitude in [-90, 90].","example":52.520008,"type":"number","minimum":-90,"maximum":90},"longitude":{"description":"WGS84 longitude in [-180, 180].","example":13.404954,"type":"number","minimum":-180,"maximum":180}},"additionalProperties":false,"description":"The structured location on a create/edit body."},"PropertyReceptionInput":{"type":"object","properties":{"email":{"description":"Reception email address.","example":"front@x.com","type":"string","pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"},"phone":{"description":"Reception phone (E.164-preferred; normalized).","example":"+923001234567","type":"string","pattern":"^[+()\\d\\s.-]{7,20}$"},"whatsapp":{"description":"Reception WhatsApp number (drives the wa.me link; may differ from phone).","example":"+923009999999","type":"string","pattern":"^[+()\\d\\s.-]{7,20}$"}},"additionalProperties":false,"description":"The structured reception contact on a create/edit body."},"QuickAddPropertyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Property name.","example":"Seaview House"},"propertyType":{"type":"string","enum":["apartment","suite","loft","house","studio","villa","multi_unit","complex","hotel","hostel"],"description":"The property type.","example":"villa"},"city":{"type":"string","minLength":1,"maxLength":120,"description":"City.","example":"Lahore"},"countryCode":{"description":"ISO-3166-1 alpha-2 country code.","example":"PK","type":"string","pattern":"^[A-Z]{2}$"},"checkInTime":{"description":"Check-in time (HH:MM).","example":"15:00","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"checkOutTime":{"description":"Check-out time (HH:MM).","example":"11:00","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"unitTypeName":{"type":"string","minLength":1,"maxLength":120,"description":"The unit type.","example":"Studio"},"units":{"type":"integer","minimum":1,"maximum":50,"description":"How many units to add (1 to 50).","example":4},"nightlyRateMinor":{"type":"string","pattern":"^[1-9]\\d{0,14}$","description":"Nightly rate in minor units (decimal string).","example":"1500000"}},"required":["name","propertyType","city","unitTypeName","units","nightlyRateMinor"],"additionalProperties":false,"description":"A property, one unit type, its units and their nightly rate, in one form."},"EditPropertyBody":{"type":"object","properties":{"name":{"description":"New property name.","example":"Seaview Suites","type":"string","minLength":1},"code":{"description":"New property code (absent → unchanged; uppercased; backs the unique key — re-validated + uniqueness-checked on change).","example":"SV-02","type":"string","minLength":1},"checkInTime":{"description":"New check-in time (HH:MM); absent → unchanged, null → clear.","example":"14:00","anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"checkOutTime":{"description":"New check-out time (HH:MM); absent → unchanged, null → clear.","example":"10:00","anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"propertyType":{"description":"New property type (absent → unchanged).","example":"studio","type":"string","enum":["apartment","suite","loft","house","studio","villa","multi_unit","complex","hotel","hostel"]},"channelSyncMode":{"description":"New sync shape (absent → unchanged). REFUSED once channel sync is provisioned for this property (channel_sync_mode_locked) — disconnect first.","example":"pool","type":"string","enum":["unit","pool"]},"location":{"description":"The full replacement location (absent → unchanged; whole-object patch).","$ref":"#/components/schemas/PropertyLocationInput"},"managerMembershipId":{"description":"The INFORMATIONAL manager membership id (null → unassigned).","example":"22222222-2222-4222-8222-222222222222","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"reception":{"description":"The full replacement reception contact (absent → unchanged; whole-object patch).","$ref":"#/components/schemas/PropertyReceptionInput"}},"additionalProperties":false,"description":"Mutable fields to patch (code is mutable; re-validated + uniqueness-checked on change)."},"RequestPhotoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime"],"description":"The image content type (jpeg/png/webp/avif; SVG barred).","example":"image/jpeg"},"byteSizeHint":{"description":"An optional declared byte size (confirm re-checks the real size).","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false,"description":"Request a presigned PUT for a new property photo (id + key are server-minted)."},"ConfirmPhotoUploadBody":{"type":"object","properties":{},"additionalProperties":false,"description":"Confirm a pending photo upload (no client fields)."},"ReorderPhotoBody":{"type":"object","properties":{"setLead":{"description":"Promote this photo to the lead (position 0).","type":"boolean","const":true},"orderedPhotoIds":{"description":"The full new ordering (photo ids; position 0 = lead).","minItems":1,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"additionalProperties":false,"description":"Set-lead (this photo) OR reorder (full ordering) — exactly one action."},"SetWhatsAppConnectionBody":{"type":"object","properties":{"phoneNumberId":{"type":"string","pattern":"^[0-9]{5,32}$"},"wabaId":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"displayPhone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}]},"accessToken":{"type":"string","minLength":8,"maxLength":512},"appSecret":{"type":"string","minLength":8,"maxLength":512},"webhookVerifyToken":{"type":"string","minLength":8,"maxLength":512},"dailyTemplate":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}]},"templateLang":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}]},"guestTemplate":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}]},"isActive":{"type":"boolean"}},"required":["phoneNumberId"],"additionalProperties":false},"SetPropertyContentBody":{"type":"object","properties":{"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"description":"Guest-facing property description (pushed to channels); null clears."},"importantInformation":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"description":"Important information / house notes for guests; null clears."},"paymentInstructions":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"description":"Bank details shown on this property’s quotations, overriding the workspace default; null clears (the workspace default is then used)."},"logoPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The property photo elected as the logo (must be a READY photo of THIS property's gallery); null clears. The server stores the underlying object key — a client never sends a key."},"petsPolicy":{"anyOf":[{"type":"string","enum":["allowed","by_arrangements","not_allowed"]},{"type":"null"}],"description":"Pets policy; null = unset."},"smokingPolicy":{"anyOf":[{"type":"string","enum":["no_smoking","smoking_allowed","designated_areas"]},{"type":"null"}],"description":"Smoking policy; null = unset."},"parkingType":{"anyOf":[{"type":"string","enum":["on_site","nearby","none"]},{"type":"null"}],"description":"Parking availability; null = unset."},"wifiCoverage":{"anyOf":[{"type":"string","enum":["entire_property","public_areas","none"]},{"type":"null"}],"description":"Wi-Fi coverage; null = unset."}},"required":["description","importantInformation","paymentInstructions","logoPhotoId","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false,"description":"A whole-object replace of the property's content & policies card (the editor round-trips every field; null clears)."},"SetListingContentBody":{"type":"object","properties":{"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"description":"Guest-facing unit description (pushed to the channel room type); null clears."}},"required":["description"],"additionalProperties":false,"description":"A whole-object replace of the listing's content card (null clears)."},"SetPropertyRefundPolicyBody":{"type":"object","properties":{"policyHeading":{"type":"string","minLength":1,"maxLength":200},"policyNotes":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"description":"Printed under the generated bullets, in the operator’s own words; null clears."},"refundTiers":{"minItems":1,"maxItems":6,"type":"array","items":{"$ref":"#/components/schemas/RefundTier"}}},"required":["policyHeading","policyNotes","refundTiers"],"additionalProperties":false,"description":"A whole-object replace of one property's cancellation & refund policy."},"RefundTier":{"type":"object","properties":{"hoursBeforeCheckIn":{"type":"integer","minimum":0,"maximum":8760,"description":"Hours before the scheduled check-in. 0 is the floor rung (the \"no refund\" tail)."},"refundPct":{"type":"integer","minimum":0,"maximum":100}},"required":["hoursBeforeCheckIn","refundPct"],"additionalProperties":false},"SetPropertyQuotationBody":{"type":"object","properties":{"termsText":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"footerText":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["termsText","footerText"],"additionalProperties":false,"description":"A whole-object replace of one property's quotation boilerplate; null clears."},"SetCleaningRulesBody":{"type":"object","properties":{"stayoverCleanEveryDays":{"anyOf":[{"type":"integer","minimum":1,"maximum":60},{"type":"null"}],"description":"A mid-stay clean every N days of a stay. Null = off."},"stayoverMinNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}],"description":"Only stays of at least this many nights get stayover cleans. Null = any stay."},"deepCleanEveryTurnovers":{"anyOf":[{"type":"integer","minimum":2,"maximum":100},{"type":"null"}],"description":"A deep clean on every Nth checkout of a unit. Null = off."}},"required":["stayoverCleanEveryDays","stayoverMinNights","deepCleanEveryTurnovers"],"additionalProperties":false},"CreateListingTypeBody":{"type":"object","properties":{"propertyId":{"description":"The owning property (a property-scoped type). Omit for a legacy tenant-wide type. Immutable post-create.","example":"22222222-2222-4222-8222-222222222222","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"key":{"type":"string","minLength":1,"description":"Property-unique (or tenant-unique for a legacy type), immutable listing-type key.","example":"1BED"},"name":{"type":"string","minLength":1,"description":"Human-facing listing-type name.","example":"One Bedroom"},"defaultSqft":{"description":"Default square-footage for this type (positive integer).","example":550,"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"attributes":{"description":"Ordered {label,value} attribute rows (max 20).","maxItems":20,"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"description":"The attribute label (e.g. \"Type\", \"View\").","example":"View"},"value":{"type":"string","minLength":1,"description":"The attribute value (e.g. \"Sea\").","example":"Sea"}},"required":["label","value"],"additionalProperties":false}}},"required":["key","name"],"additionalProperties":false,"description":"Fields to create a listing_type (id is server-minted)."},"EditListingTypeBody":{"type":"object","properties":{"name":{"description":"New listing-type name.","example":"One-Bed Deluxe","type":"string","minLength":1},"defaultSqft":{"description":"New default square-footage (positive integer), or null to clear it.","example":600,"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"attributes":{"description":"Ordered {label,value} attribute rows (max 20) — REPLACES the whole set; an empty array clears them.","maxItems":20,"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"description":"The attribute label (e.g. \"Type\", \"View\").","example":"View"},"value":{"type":"string","minLength":1,"description":"The attribute value (e.g. \"Sea\").","example":"Sea"}},"required":["label","value"],"additionalProperties":false}}},"additionalProperties":false,"description":"Mutable fields to patch (key + propertyId are immutable; not accepted)."},"SetListingTypeCapacityBody":{"$ref":"#/components/schemas/ListingTypeCapacityView"},"ListingTypeCapacityView":{"type":"object","properties":{"occAdults":{"type":"integer","minimum":1,"maximum":20},"occChildren":{"type":"integer","minimum":0,"maximum":20},"occInfants":{"type":"integer","minimum":0,"maximum":20},"defaultOccupancy":{"type":"integer","minimum":1,"maximum":20,"description":"The occupancy the base rate is quoted at (1..occAdults)."},"minStayDefault":{"type":"integer","minimum":1,"maximum":90},"maxStayDefault":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]}},"required":["occAdults","occChildren","occInfants","defaultOccupancy","minStayDefault","maxStayDefault"],"additionalProperties":false},"CreateListingBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property (must exist in the caller tenant).","example":"11111111-1111-4111-8111-111111111111"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing type (must exist in the caller tenant).","example":"22222222-2222-4222-8222-222222222222"},"listingCode":{"type":"string","minLength":1,"description":"Property-unique listing code (uppercased; backs the unique key; editable post-create).","example":"628"},"lockMode":{"description":"The lock mode (absent → the static default).","example":"static","type":"string","enum":["static","integrated"]},"checkInTime":{"description":"Listing check-in override (HH:MM).","example":"15:00","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"checkOutTime":{"description":"Listing check-out override (HH:MM).","example":"11:00","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"parentListingId":{"description":"Optional parent listing to nest under (must be SAME property/tenant).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"childOccupancyPolicy":{"description":"How this listing's own children interact (absent → 'coexist'; 'exclusive' = one child at a time).","type":"string","enum":["coexist","exclusive"]},"bedrooms":{"description":"Number of bedrooms (0 = studio; absent → 0).","example":2,"type":"integer","minimum":0,"maximum":50},"beds":{"description":"Number of beds (absent → 0).","example":3,"type":"integer","minimum":0,"maximum":50},"bathrooms":{"description":"Number of bathrooms (absent → 0).","example":1,"type":"integer","minimum":0,"maximum":50},"sizeValue":{"description":"Unit size magnitude in `sizeUnit` (must be paired with `sizeUnit`).","example":90,"type":"number","exclusiveMinimum":0,"maximum":100000},"sizeUnit":{"description":"Unit-size measurement system (`sqm`|`sqft`).","example":"sqm","type":"string","enum":["sqm","sqft"]},"amenities":{"description":"The amenity keys offered (canonical set; de-duplicated server-side; absent → []).","example":["wifi","kitchen","air_conditioning"],"type":"array","items":{"type":"string","enum":["accessible_by_lift","adapter","air_conditioning","air_purifiers_available","alarm_clock","allergy_free","blu_ray_player","board_games_puzzles","book_dvd_music_library_for_children","bottle_of_water","cable_channels","carpeted_floor","cd_player","children_crib_cots","chocolate_cookies","clothes_drying_rack","clothes_rack","clothing_iron","coffee_machine","coffee_tea_maker","computer","desk","detached","dining_area","dining_table","dressing_room","dryer","dvd_player","earplugs","electric_blankets","electric_kettle","entire_property_on_ground_floor","entire_unit_wheelchair_accessible","executive_lounge_access","fan","fax","feather_pillow","flat_screen_tv","fruits","game_console","game_console_nintendo_wii","game_console_ps2","game_console_ps3","game_console_ps4","game_console_wii_u","game_console_xbox_360","game_console_xbox_one","hair_dryer","hand_sanitiser","heating","hypoallergenic_pillow","indoor_fireplace","interconnecting_room_s_available","internet_facilities","ipad","ipod_docking_station","ironing_facilities","kitchenware","laptop","linen","mini_bar","mosquito_net","non_feather_pillow","outdoor_dining_area","outdoor_furniture","pajamas","patio","pay_per_view_channels","portable_wifi","private_curtain","private_entrance","private_flat_in_block_of_flats","radio","reading_light","rollaway_bed","satellite_channels","seating_area","semi_detached","single_room_air_conditioning_for_guest_accommodation","slippers","smartphone","socket_near_the_bed","sofa","sofa_bed","soundproofing","streaming_service_such_as_netflix","telephone","terrace","tiled_marble_floor","towels_linens_at_surcharge","trash_cans","trouser_press","tv","upper_floor_reachable_by_lift","upper_floor_reachable_by_stairs_only","video","video_games","wake_up_service","wake_up_service_alarm_clock","wardrobe_closet","washer","wifi","wine_champagne","wireless_internet","wooden_parquet_floor","yukata","adapted_bath","additional_bathroom","additional_toilet","bath","bath_or_shower","bath_robe","bathroom","bidet","body_soap","conditioner","free_toiletries","guest_toilet","higher_level_toilet","low_bathroom_sink","roll_in_shower","sauna","shampoo","shower","shower_cap","jacuzzi","shower_chair","spa_bath","toilet","toilet_paper","toilet_with_grab_rails","toothbrush","towels","walk_in_shower","children_highchair","cleaning_products","dishwasher","kitchen","kitchenette","microwave","oven","refrigerator","shared_bathroom","stove","toaster","tumble_dryer_machine","wine_glasses","bbq_grill","garden_or_backyard","hot_tub","infinity_pool","patio_or_balcony","plunge_pool","pool","pool_cover","pool_towels","pool_with_view","private_pool","rooftop_pool","salt_water_pool","shallow_end","ski_in_out","beachfront","city_view","extra_long_beds_2_meter","inner_courtyard_view","lake_access","landmark_view","mountain_view","pool_view","quiet_street_view","river_view","sea_view","view","waterfront","baby_safety_gates","bathroom_emergency_pull_cord","carbon_monoxide_detector","carbon_monoxide_source","child_safety_socket_covers","electronic_key_card_access","fire_alarms_or_smoke_detectors","fire_extinguishers","laptop_safe_box","lockers","metal_keys_access","safe_deposit_box","100_amps","20_amps","30_amps","50_amps","big_rig_friendly","dump_station","free_parking","gym","sewer_hookups","slide_outs","water_hookups"]}}},"required":["propertyId","listingTypeId","listingCode"],"additionalProperties":false,"description":"Fields to create a listing (id is server-minted; readiness is system-managed)."},"EditListingBody":{"type":"object","properties":{"listingCode":{"description":"New listing code (absent → unchanged; uppercased; backs the unique key — re-validated + uniqueness-checked on change).","example":"629","type":"string","minLength":1},"listingTypeId":{"description":"New listing type (absent → unchanged; must be same-tenant).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"lockMode":{"description":"New lock mode (absent → unchanged).","example":"integrated","type":"string","enum":["static","integrated"]},"checkInTime":{"description":"New check-in override (HH:MM); absent → unchanged, null → clear.","example":"14:00","anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"checkOutTime":{"description":"New check-out override (HH:MM); absent → unchanged, null → clear.","example":"10:00","anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"isActive":{"description":"Toggle the listing active/inactive (absent → unchanged).","type":"boolean"},"parentListingId":{"description":"Re-parent (SAME property): absent → unchanged, null → unlink (become a root), uuid → link. Re-parenting a subtree with live holds/bookings is refused.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"childOccupancyPolicy":{"description":"New child-occupancy policy (absent → unchanged). Flipping to 'exclusive' over live occupancy is refused.","type":"string","enum":["coexist","exclusive"]},"bedrooms":{"description":"New bedroom count (absent → unchanged).","example":2,"type":"integer","minimum":0,"maximum":50},"beds":{"description":"New bed count (absent → unchanged).","example":3,"type":"integer","minimum":0,"maximum":50},"bathrooms":{"description":"New bathroom count (absent → unchanged).","example":1,"type":"integer","minimum":0,"maximum":50},"sizeValue":{"description":"New unit-size magnitude; absent → unchanged, null → clear (paired with `sizeUnit`).","example":90,"anyOf":[{"type":"number","exclusiveMinimum":0,"maximum":100000},{"type":"null"}]},"sizeUnit":{"description":"New unit-size measurement system (`sqm`|`sqft`); absent → unchanged, null → clear.","example":"sqm","anyOf":[{"type":"string","enum":["sqm","sqft"]},{"type":"null"}]},"amenities":{"description":"Replace the amenity set (canonical keys; de-duplicated server-side); absent → unchanged.","example":["wifi","pool"],"type":"array","items":{"type":"string","enum":["accessible_by_lift","adapter","air_conditioning","air_purifiers_available","alarm_clock","allergy_free","blu_ray_player","board_games_puzzles","book_dvd_music_library_for_children","bottle_of_water","cable_channels","carpeted_floor","cd_player","children_crib_cots","chocolate_cookies","clothes_drying_rack","clothes_rack","clothing_iron","coffee_machine","coffee_tea_maker","computer","desk","detached","dining_area","dining_table","dressing_room","dryer","dvd_player","earplugs","electric_blankets","electric_kettle","entire_property_on_ground_floor","entire_unit_wheelchair_accessible","executive_lounge_access","fan","fax","feather_pillow","flat_screen_tv","fruits","game_console","game_console_nintendo_wii","game_console_ps2","game_console_ps3","game_console_ps4","game_console_wii_u","game_console_xbox_360","game_console_xbox_one","hair_dryer","hand_sanitiser","heating","hypoallergenic_pillow","indoor_fireplace","interconnecting_room_s_available","internet_facilities","ipad","ipod_docking_station","ironing_facilities","kitchenware","laptop","linen","mini_bar","mosquito_net","non_feather_pillow","outdoor_dining_area","outdoor_furniture","pajamas","patio","pay_per_view_channels","portable_wifi","private_curtain","private_entrance","private_flat_in_block_of_flats","radio","reading_light","rollaway_bed","satellite_channels","seating_area","semi_detached","single_room_air_conditioning_for_guest_accommodation","slippers","smartphone","socket_near_the_bed","sofa","sofa_bed","soundproofing","streaming_service_such_as_netflix","telephone","terrace","tiled_marble_floor","towels_linens_at_surcharge","trash_cans","trouser_press","tv","upper_floor_reachable_by_lift","upper_floor_reachable_by_stairs_only","video","video_games","wake_up_service","wake_up_service_alarm_clock","wardrobe_closet","washer","wifi","wine_champagne","wireless_internet","wooden_parquet_floor","yukata","adapted_bath","additional_bathroom","additional_toilet","bath","bath_or_shower","bath_robe","bathroom","bidet","body_soap","conditioner","free_toiletries","guest_toilet","higher_level_toilet","low_bathroom_sink","roll_in_shower","sauna","shampoo","shower","shower_cap","jacuzzi","shower_chair","spa_bath","toilet","toilet_paper","toilet_with_grab_rails","toothbrush","towels","walk_in_shower","children_highchair","cleaning_products","dishwasher","kitchen","kitchenette","microwave","oven","refrigerator","shared_bathroom","stove","toaster","tumble_dryer_machine","wine_glasses","bbq_grill","garden_or_backyard","hot_tub","infinity_pool","patio_or_balcony","plunge_pool","pool","pool_cover","pool_towels","pool_with_view","private_pool","rooftop_pool","salt_water_pool","shallow_end","ski_in_out","beachfront","city_view","extra_long_beds_2_meter","inner_courtyard_view","lake_access","landmark_view","mountain_view","pool_view","quiet_street_view","river_view","sea_view","view","waterfront","baby_safety_gates","bathroom_emergency_pull_cord","carbon_monoxide_detector","carbon_monoxide_source","child_safety_socket_covers","electronic_key_card_access","fire_alarms_or_smoke_detectors","fire_extinguishers","laptop_safe_box","lockers","metal_keys_access","safe_deposit_box","100_amps","20_amps","30_amps","50_amps","big_rig_friendly","dump_station","free_parking","gym","sewer_hookups","slide_outs","water_hookups"]}}},"additionalProperties":false,"description":"Mutable fields to patch (readiness is system-managed; not accepted)."},"SetListingOccupancyBody":{"type":"object","properties":{"occAdults":{"anyOf":[{"type":"integer","minimum":1,"maximum":20},{"type":"null"}]},"occChildren":{"anyOf":[{"type":"integer","minimum":0,"maximum":20},{"type":"null"}]},"occInfants":{"anyOf":[{"type":"integer","minimum":0,"maximum":20},{"type":"null"}]},"defaultOccupancy":{"anyOf":[{"type":"integer","minimum":1,"maximum":20},{"type":"null"}]}},"required":["occAdults","occChildren","occInfants","defaultOccupancy"],"additionalProperties":false},"RequestListingPhotoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime"],"description":"The image content type (jpeg/png/webp/avif; SVG barred).","example":"image/jpeg"},"byteSizeHint":{"description":"An optional declared byte size (confirm re-checks the real size).","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"categoryKey":{"description":"The gallery bucket to file this photo under. Omitted ⇒ uncategorized (a plain drag with no bucket picked still uploads). An unregistered key is rejected — it is not silently accepted into a bucket nothing renders.","type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","example":"main_hero_shots"}},"required":["contentType"],"additionalProperties":false,"description":"Request a presigned PUT for a new listing photo (id + key are server-minted)."},"ConfirmListingPhotoUploadBody":{"type":"object","properties":{},"additionalProperties":false,"description":"Confirm a pending photo upload (no client fields)."},"ReorderListingPhotoBody":{"type":"object","properties":{"setLead":{"description":"Promote this photo to the lead (position 0).","type":"boolean","const":true},"orderedPhotoIds":{"description":"The full new ordering (photo ids; position 0 = lead).","minItems":1,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"additionalProperties":false,"description":"Set-lead (this photo) OR reorder (full ordering) — exactly one action."},"BackfillPhotoDerivativesBody":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":25}},"additionalProperties":false,"description":"Generate the missing resized copies (thumb/card/full) for photos that have none. Bounded per call; repeat until `remaining` is 0."},"ReconcilePhotoDerivativesBody":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":250},"cursor":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"additionalProperties":false,"description":"Check that every recorded derivative is really in the store, and narrow the record where it is not. Bounded per call; repeat while `nextCursor` is non-null."},"SetListingPhotoCategoryBody":{"type":"object","properties":{"categoryKey":{"anyOf":[{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","description":"A gallery bucket key — a built-in (`living_room`) or one of the tenant's registered custom keys.","example":"main_hero_shots"},{"type":"null"}],"description":"The destination bucket, or null for uncategorized."}},"required":["categoryKey"],"additionalProperties":false,"description":"Move a listing photo into a gallery bucket (null = uncategorized)."},"RegisterListingPhotoCategoryBody":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":60,"description":"The bucket name (\"Bedroom 2\"). The key is derived from it.","example":"Bedroom 2"}},"required":["label"],"additionalProperties":false,"description":"Register a custom listing-photo category (the key is server-derived from the label)."},"RequestListingTypePhotoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime"],"description":"The image content type (jpeg/png/webp/avif; SVG barred).","example":"image/jpeg"},"byteSizeHint":{"description":"An optional declared byte size (confirm re-checks the real size).","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"categoryKey":{"description":"The gallery bucket to file this photo under. Omitted ⇒ uncategorized. An unregistered key is rejected rather than silently accepted into a bucket nothing renders.","type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","example":"bedroom_2"}},"required":["contentType"],"additionalProperties":false,"description":"Request a presigned PUT for a new listing-type photo (id + key are server-minted)."},"ConfirmListingTypePhotoUploadBody":{"type":"object","properties":{},"additionalProperties":false,"description":"Confirm a pending photo upload (no client fields)."},"ReorderListingTypePhotoBody":{"type":"object","properties":{"setLead":{"description":"Promote this photo to the lead (position 0).","type":"boolean","const":true},"orderedPhotoIds":{"description":"The full new ordering (photo ids; position 0 = lead).","minItems":1,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"additionalProperties":false,"description":"Set-lead (this photo) OR reorder (full ordering) — exactly one action."},"PushListingTypePhotosBody":{"type":"object","properties":{},"additionalProperties":false,"description":"Push this type's photos onto every unit of the type (no client fields)."},"SetListingTypePhotoCategoryBody":{"type":"object","properties":{"categoryKey":{"anyOf":[{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","description":"A gallery bucket key — a built-in (`living_room`) or one of the tenant's registered custom keys.","example":"bedroom_2"},{"type":"null"}],"description":"The destination bucket, or null for uncategorized."}},"required":["categoryKey"],"additionalProperties":false,"description":"Move a listing-type photo into a gallery bucket (null = uncategorized)."},"SetListingChannelLinksBody":{"type":"object","properties":{"links":{"maxItems":25,"type":"array","items":{"$ref":"#/components/schemas/ChannelLinkInput"},"description":"The full desired set of channel links (replaces the current set)."}},"required":["links"],"additionalProperties":false,"description":"Replace a listing’s channel links with the given set (bounded, idempotent)."},"ChannelLinkInput":{"type":"object","properties":{"channel":{"type":"string","enum":["airbnb","booking_com","vrbo","expedia","agoda","tripadvisor","google","direct","other"],"description":"The external channel this URL points at (the domain allow-list).","example":"airbnb"},"url":{"type":"string","minLength":1,"maxLength":2048,"description":"The public listing URL on that channel (absolute http(s))."},"label":{"description":"An optional display label (for the `other`/custom channel).","anyOf":[{"type":"string","maxLength":80},{"type":"null"}]}},"required":["channel","url"],"additionalProperties":false},"CreateInquiryBody":{"type":"object","properties":{"listingTypeId":{"description":"Optional: the requested listing type.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"description":"Optional: pin the stay to a single property.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"description":"Optional: pin the exact listing (unit) — must match the property + type.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingIds":{"description":"Optional: two or more units quoted together as one group inquiry.","minItems":2,"maxItems":20,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"channel":{"type":"string","enum":["airbnb","offline","direct","booking_com","expedia","agoda","vrbo"],"description":"The settlement channel (airbnb | offline)."},"source":{"description":"The acquisition source — where this guest came from (0129 — one vocabulary).","type":"string","enum":["direct_site","airbnb","booking_com","expedia","agoda","vrbo","whatsapp","instagram","facebook","tiktok","referral","walk_in","call","host_to_host","other"]},"existingGuestId":{"description":"Optional: link an existing guest instead of capturing a new one.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"guest":{"description":"The guest contact captured with the inquiry (0022).","$ref":"#/components/schemas/CreateInquiryGuestBody"},"note":{"description":"A free-form operator note (0022).","type":"string","maxLength":2000},"occupancy":{"description":"The guest party composition (0024); omit = all-zero.","$ref":"#/components/schemas/Occupancy"},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Check-in date (YYYY-MM-DD).","example":"2026-07-10"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Check-out date (YYYY-MM-DD; exclusive — checkout night free).","example":"2026-07-13"}},"required":["channel","checkIn","checkOut"],"additionalProperties":false},"CreateInquiryGuestBody":{"type":"object","properties":{"fullName":{"type":"string","minLength":1,"maxLength":160,"description":"The guest's display name."},"phone":{"description":"Contact phone.","type":"string","minLength":3,"maxLength":40},"email":{"description":"Contact email.","type":"string","maxLength":254,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"whatsapp":{"description":"WhatsApp number.","type":"string","minLength":3,"maxLength":40},"socialUrls":{"description":"Social media profile URLs (Instagram, Facebook, …).","maxItems":10,"type":"array","items":{"type":"string","maxLength":500,"format":"uri"}}},"required":["fullName"],"additionalProperties":false},"Occupancy":{"type":"object","properties":{"adults":{"default":0,"description":"Adults (ages 13+).","type":"integer","minimum":0,"maximum":50},"children":{"default":0,"description":"Children (ages 2–12).","type":"integer","minimum":0,"maximum":50},"infants":{"default":0,"description":"Infants (under 2).","type":"integer","minimum":0,"maximum":50},"pets":{"default":0,"description":"Pets.","type":"integer","minimum":0,"maximum":50}},"additionalProperties":false},"UpdateInquiryBody":{"type":"object","properties":{"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingIds":{"maxItems":20,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"adults":{"type":"integer","minimum":0,"maximum":9007199254740991},"children":{"type":"integer","minimum":0,"maximum":9007199254740991},"infants":{"type":"integer","minimum":0,"maximum":9007199254740991},"pets":{"type":"integer","minimum":0,"maximum":9007199254740991},"source":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["checkIn","checkOut","adults","children","infants","pets"],"additionalProperties":false},"QuoteInquiryBody":{"type":"object","properties":{"amountMinor":{"type":"string","pattern":"^[1-9]\\d{0,17}$","description":"The manual whole-stay quote in MINOR units (integer string).","example":"4500000"},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO-4217 — must equal the tenant's base currency.","example":"PKR"},"advanceMinor":{"description":"The advance due NOW to lock (minor units; ≤ total; advance + onProperty must equal total). Default: the full quote.","type":"string","pattern":"^[1-9]\\d{0,17}$"},"onPropertyMinor":{"description":"The at-the-property portion (minor units; advance + onProperty must equal total — the total AFTER any promo discount).","type":"string","pattern":"^(0|[1-9]\\d{0,17})$"},"promoCode":{"description":"Optional: a promo code published on the tenant’s direct-booking site (0295). amountMinor is then the GROSS stay price and the discount comes off it; the server re-decides eligibility and refuses a code that does not apply. Omit to quote with no discount (and to clear one a previous quote carried).","example":"SPRING26","type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9-]{1,31}$"},"complimentaryReason":{"description":"Optional (0343): the stay is being GIVEN rather than sold. Whatever remains payable after any promo discount is WAIVED — the saved total is exactly 0 — and amountMinor is recorded as the list value given away. Requires the `inquiry:comp` capability, which is separate from the `inquiry:create` that quotes. Omit to quote an ordinary paid stay (and to clear a comp a previous quote carried). advanceMinor / onPropertyMinor are refused alongside it: a stay that costs nothing has no split to agree.","example":"influencer","type":"string","enum":["influencer","family_friends","staff","owner_stay","goodwill","marketing_shoot"]},"complimentaryNote":{"description":"Optional free text recorded with a complimentary stay (0343). Comp-only — ignored unless complimentaryReason is set. Never enters the audit log: it is operator prose about a named guest, and the append-only log cannot be corrected in place.","type":"string","maxLength":2000}},"required":["amountMinor","currency"],"additionalProperties":false},"QuotePreviewBody":{"type":"object","properties":{"legs":{"minItems":1,"maxItems":20,"type":"array","items":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["listingId","checkIn","checkOut"],"additionalProperties":false},"description":"Stay legs to price (≥1; a single leg is the direct/inquiry case)."}},"required":["legs"],"additionalProperties":false},"SubmitPaymentProofBody":{"type":"object","properties":{"method":{"type":"string","enum":["bank_transfer","easypaisa","jazzcash","raast","other"],"description":"The settlement rail per the proof."},"amountMinor":{"type":"string","pattern":"^[1-9]\\d{0,17}$","description":"The paid amount in MINOR units — must equal the quote exactly (100% advance)."},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO-4217 — must equal the quoted currency."},"txnRef":{"description":"Bank/wallet txn reference.","type":"string","minLength":1,"maxLength":120},"senderName":{"description":"The sender per the proof.","type":"string","minLength":1,"maxLength":120},"paidAt":{"description":"The transfer instant per the proof (ISO-8601).","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"receivingAccountId":{"description":"Optional: the treasury money store the payment landed in. Omit to route on the property assignment.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["method","amountMinor","currency"],"additionalProperties":false},"ConvertInquiryBody":{"type":"object","properties":{"listingId":{"description":"Optional: the convertor-confirmed/overridden unit; omit = keep the held unit.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"quotedAmountMinor":{"description":"Optional: the FINAL agreed total for the stay, in minor units. Omit = keep the inquiry’s quote. Becomes the booking total; a change revokes any live public quotation.","type":"string","pattern":"^[1-9]\\d{0,17}$"},"verifiedAmountMinor":{"description":"Optional: the amount confirmed received, in minor units (≤ the total). Omit = accept the claimed amount. The rest of the total becomes the on-property balance.","type":"string","pattern":"^[1-9]\\d{0,17}$"}},"additionalProperties":false},"ConfirmComplimentaryBody":{"type":"object","properties":{},"additionalProperties":false},"CreateDirectBookingBody":{"type":"object","properties":{"guestId":{"description":"An EXISTING guest this stay belongs to (null/omitted = none yet). Mutually exclusive with `guest`.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"guest":{"description":"A NEW guest captured inline. Mutually exclusive with `guestId`.","$ref":"#/components/schemas/CreateInquiryGuestBody"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The exact unit — validated live + free for the whole stay."},"channel":{"type":"string","enum":["airbnb","offline","direct","booking_com","expedia","agoda","vrbo"],"description":"The settlement channel (airbnb | offline)."},"source":{"type":"string","enum":["direct_site","airbnb","booking_com","expedia","agoda","vrbo","whatsapp","instagram","facebook","tiktok","referral","walk_in","call","host_to_host","other"],"description":"The acquisition source for a source-trusted booking (0129 — one vocabulary)."},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Check-in date (YYYY-MM-DD).","example":"2026-07-10"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Check-out date (YYYY-MM-DD; exclusive — checkout night free).","example":"2026-07-13"},"totalAmountMinor":{"type":"string","pattern":"^[1-9]\\d{0,17}$","description":"The whole-stay settled total in MINOR units (integer string).","example":"4500000"},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO-4217 currency of the settled total."},"adults":{"default":0,"description":"Adults (ages 13+).","type":"integer","minimum":0,"maximum":50},"children":{"default":0,"description":"Children (ages 2–12).","type":"integer","minimum":0,"maximum":50},"infants":{"default":0,"description":"Infants (under 2).","type":"integer","minimum":0,"maximum":50},"pets":{"default":0,"description":"Pets.","type":"integer","minimum":0,"maximum":50}},"required":["listingId","channel","source","checkIn","checkOut","totalAmountMinor","currency"],"additionalProperties":false},"CreateGroupBookingBody":{"type":"object","properties":{"guestId":{"description":"An EXISTING guest the whole group belongs to. Mutually exclusive with `guest`.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"guest":{"description":"A NEW booker captured inline. Mutually exclusive with `guestId`.","$ref":"#/components/schemas/CreateInquiryGuestBody"},"source":{"type":"string","enum":["direct_site","airbnb","booking_com","expedia","agoda","vrbo","whatsapp","instagram","facebook","tiktok","referral","walk_in","call","host_to_host","other"],"description":"The acquisition source shared by every leg (0129 — one vocabulary)."},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO-4217 currency of the settled group total."},"legs":{"minItems":2,"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/CreateGroupBookingLeg"},"description":"The group legs (≥2 units — a single unit is the direct-booking path)."}},"required":["source","currency","legs"],"additionalProperties":false},"CreateGroupBookingLeg":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The exact unit for this leg — validated live + free for its stay."},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Check-in date (YYYY-MM-DD).","example":"2026-07-10"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Check-out date (YYYY-MM-DD; exclusive — checkout night free).","example":"2026-07-13"},"totalAmountMinor":{"type":"string","pattern":"^[1-9]\\d{0,17}$","description":"This leg's settled amount in MINOR units (the group total is the sum of the legs).","example":"4500000"},"adults":{"default":0,"description":"Adults (ages 13+).","type":"integer","minimum":0,"maximum":50},"children":{"default":0,"description":"Children (ages 2–12).","type":"integer","minimum":0,"maximum":50},"infants":{"default":0,"description":"Infants (under 2).","type":"integer","minimum":0,"maximum":50},"pets":{"default":0,"description":"Pets.","type":"integer","minimum":0,"maximum":50}},"required":["listingId","checkIn","checkOut","totalAmountMinor"],"additionalProperties":false},"UpdateBookingBody":{"type":"object","properties":{"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The target unit (same id = keep the unit)."},"adults":{"type":"integer","minimum":0,"maximum":9007199254740991},"children":{"type":"integer","minimum":0,"maximum":9007199254740991},"infants":{"type":"integer","minimum":0,"maximum":9007199254740991},"pets":{"type":"integer","minimum":0,"maximum":9007199254740991},"totalAmountMinor":{"type":"string","pattern":"^\\d+$","description":"The quote total in minor units (decimal string; never a float)."},"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the booking is being edited, MANDATORY - recorded on the audit trail and shown on the booking history."}},"required":["checkIn","checkOut","listingId","adults","children","infants","pets","totalAmountMinor","reason"],"additionalProperties":false},"CheckInBookingBody":{"type":"object","properties":{"conditionWaiverReason":{"description":"Override the condition-evidence gate for this transition, stating why. Requires booking:update; recorded on the booking’s audit trail.","type":"string","minLength":8,"maxLength":500}},"additionalProperties":false},"CheckOutBookingBody":{"type":"object","properties":{"conditionWaiverReason":{"description":"Override the condition-evidence gate for this transition, stating why. Requires booking:update; recorded on the booking’s audit trail.","type":"string","minLength":8,"maxLength":500},"recordArrival":{"description":"Record the ARRIVAL as part of this check-out — the late write-up of a stay entered after it ended. Accepted only on a pre-arrival stay whose check-out day has arrived or passed; every edge is still walked and audited individually. Absent (the default) a pre-arrival stay is refused.","type":"boolean"},"settlement":{"type":"object","properties":{"option":{"type":"string","enum":["keep_all","cancellation_fee","refund_all"]},"feeMinor":{"description":"The cancellation fee to KEEP, minor units as a decimal STRING (only for cancellation_fee); clamped to the unused pool.","type":"string","pattern":"^(0|[1-9]\\d{0,17})$"}},"required":["option"],"additionalProperties":false}},"additionalProperties":false},"RequestConditionMediaUploadBody":{"type":"object","properties":{"phase":{"type":"string","enum":["pre_check_in","post_check_out"],"description":"pre_check_in | post_check_out."},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime","application/pdf"],"description":"The image/video/PDF MIME type (the attachment allow-list; no SVG)."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"capturedAtSource":{"type":"string","enum":["exif","video_metadata","file_modified","unknown"]},"capturedAt":{"type":"string","maxLength":40},"originalFilename":{"type":"string","maxLength":200},"caption":{"type":"string","maxLength":500}},"required":["phase","contentType"],"additionalProperties":false},"AnnotateConditionMediaBody":{"type":"object","properties":{"caption":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"damageReportId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"additionalProperties":false},"OpenBookingDamageBody":{"type":"object","properties":{"kind":{"type":"string","enum":["damage","item_missing"]},"description":{"type":"string","minLength":1,"maxLength":4000},"estimatedCostMinor":{"description":"An ESTIMATE in integer minor units, as a string. Never posts to the ledger.","type":"string","pattern":"^\\d+$"},"airbnbReviewRequested":{"type":"boolean"}},"required":["kind","description"],"additionalProperties":false},"CancelBookingBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the booking is cancelled — recorded on the audit trail."},"settlement":{"type":"object","properties":{"option":{"type":"string","enum":["keep_all","cancellation_fee","refund_all"]},"feeMinor":{"description":"The cancellation fee to KEEP, minor units as a decimal STRING (only for cancellation_fee); clamped to the deferred pool.","type":"string","pattern":"^(0|[1-9]\\d{0,17})$"}},"required":["option"],"additionalProperties":false}},"required":["reason"],"additionalProperties":false},"RequestRefundBody":{"type":"object","properties":{"amountMinor":{"type":"string","pattern":"^[1-9]\\d*$","description":"The refund in minor units (decimal string; ≤ verified − already committed)."},"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the money goes back — recorded on the audit trail."},"kind":{"description":"What kind of refund this is (0394). `price_adjustment` (the default, and every refund before 0394) means the stay costs less than quoted: the liability is drained first and the total is expected to have been lowered to match. `allowance` means the price STANDS and this is compensation: it debits 4910 Refunds & Allowances alone, leaves the deferred pool whole so the full quote still recognises, and answers to the cash and ledger bounds but NOT to the overpayment one — which is why a stay paid exactly in full can be refunded at all.","type":"string","enum":["price_adjustment","allowance"]}},"required":["amountMinor","reason"],"additionalProperties":false},"DecideRefundBody":{"type":"object","properties":{"decision":{"type":"string","enum":["pay","reject"]}},"required":["decision"],"additionalProperties":false},"RecordGuestCashBody":{"type":"object","properties":{"amountMinor":{"type":"string","pattern":"^[1-9]\\d*$","description":"The cash received in minor units (positive decimal string; never a float)."},"senderName":{"description":"Who handed over the cash (the guest), for the receipt/audit.","type":"string","minLength":1,"maxLength":120},"paidAt":{"description":"When the guest paid (ISO-8601 instant; defaults to now).","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"note":{"type":"string","maxLength":500}},"required":["amountMinor"],"additionalProperties":false},"PaymentAttachmentUploadBody":{"type":"object","properties":{"contentType":{"type":"string","maxLength":100},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"AttachPaymentScreenshotBody":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["guest_proof","operator_receipt","refund_proof","extension_proof"]},"objectKey":{"type":"string","maxLength":300},"contentType":{"type":"string","maxLength":100},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"refundId":{"description":"Which refund this proof evidences (0393). Only valid on a `refund_proof`, and the refund must be one of THIS payment - a refund of another booking is refused. Absent leaves the proof attributed to the payment alone, which is the pre-0393 behaviour.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["paymentId","kind","objectKey","contentType"],"additionalProperties":false},"SplitPaymentTransfersBody":{"type":"object","properties":{"transfers":{"minItems":2,"maxItems":8,"type":"array","items":{"type":"object","properties":{"attachmentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","maxLength":20,"pattern":"^\\d+$"},"txnRef":{"type":"string","maxLength":120},"senderName":{"type":"string","maxLength":120}},"required":["attachmentId","amountMinor"],"additionalProperties":false}}},"required":["transfers"],"additionalProperties":false},"RepairStrandedPaymentBody":{"type":"object","properties":{"expectedAmountMinor":{"type":"string","maxLength":20,"pattern":"^\\d+$"}},"required":["expectedAmountMinor"],"additionalProperties":false},"CreateBankAccountBody":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120,"description":"The operator's own name for the account. NEVER shown to a guest."},"bankName":{"type":"string","minLength":1,"maxLength":120,"description":"e.g. HBL, Meezan."},"accountTitle":{"type":"string","minLength":1,"maxLength":160,"description":"The name the account is held in."},"accountNumber":{"type":"string","minLength":1,"maxLength":64},"iban":{"type":"string","minLength":15,"maxLength":42,"pattern":"^[A-Za-z0-9 ]+$","description":"ISO 13616 IBAN, mod-97 validated. Stored and printed grouped in fours (`PK36 SCBL 0000 …`)."},"swift":{"anyOf":[{"type":"string","minLength":8,"maxLength":11},{"type":"null"}]},"branch":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"notes":{"description":"Free lines printed under the table, verbatim — the escape hatch.","anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["label","bankName","accountTitle","accountNumber","iban"],"additionalProperties":false},"UpdateBankAccountBody":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120,"description":"The operator's own name for the account. NEVER shown to a guest."},"bankName":{"type":"string","minLength":1,"maxLength":120,"description":"e.g. HBL, Meezan."},"accountTitle":{"type":"string","minLength":1,"maxLength":160,"description":"The name the account is held in."},"accountNumber":{"type":"string","minLength":1,"maxLength":64},"iban":{"type":"string","minLength":15,"maxLength":42,"pattern":"^[A-Za-z0-9 ]+$","description":"ISO 13616 IBAN, mod-97 validated. Stored and printed grouped in fours (`PK36 SCBL 0000 …`)."},"swift":{"anyOf":[{"type":"string","minLength":8,"maxLength":11},{"type":"null"}]},"branch":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"notes":{"description":"Free lines printed under the table, verbatim — the escape hatch.","anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["label","bankName","accountTitle","accountNumber","iban"],"additionalProperties":false},"SetBankAccountPropertiesBody":{"type":"object","properties":{"propertyIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"The FULL set of properties this account serves — a whole-set replace. An empty array releases every property currently assigned to it."}},"required":["propertyIds"],"additionalProperties":false},"RequestVerificationBody":{"type":"object","properties":{"note":{"type":"string","maxLength":500},"guestName":{"description":"Who this check covers — omit for the booking primary guest.","type":"string","maxLength":120}},"additionalProperties":false},"SetDocRequirementBody":{"type":"object","properties":{"verificationId":{"description":"Which per-guest check to act on. Optional when the booking has exactly one; required (409 verification_ambiguous otherwise) once it has several.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"requirement":{"type":"string","enum":["passport","mrc"],"description":"passport = foreign guest; mrc = couple with mismatched CNIC addresses."}},"required":["requirement"],"additionalProperties":false},"RecordVerificationDetailsBody":{"type":"object","properties":{"verificationId":{"description":"Which per-guest check to act on. Optional when the booking has exactly one; required (409 verification_ambiguous otherwise) once it has several.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"idKind":{"type":"string","enum":["cnic","passport","national_id"]},"docNumber":{"type":"string","minLength":5,"maxLength":40,"description":"The full identity number — stored server-side; never echoed back."},"nationality":{"anyOf":[{"type":"string","pattern":"^[A-Za-z]{2}$"},{"type":"null"}]}},"required":["idKind","docNumber"],"additionalProperties":false},"RequestVerificationDocUploadBody":{"type":"object","properties":{"verificationId":{"description":"Which per-guest check to act on. Optional when the booking has exactly one; required (409 verification_ambiguous otherwise) once it has several.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"docKind":{"type":"string","enum":["cnic_front","cnic_back","passport","passport_back","mrc","national_id_front","national_id_back"]},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","image/heic","image/heif","video/mp4","video/webm","video/quicktime","application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.oasis.opendocument.text"]},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["docKind","contentType"],"additionalProperties":false},"VerificationDecisionBody":{"type":"object","properties":{"verificationId":{"description":"Which per-guest check to act on. Optional when the booking has exactly one; required (409 verification_ambiguous otherwise) once it has several.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"additionalProperties":false},"RevokeVerificationBody":{"type":"object","properties":{"verificationId":{"description":"Which per-guest check to act on. Optional when the booking has exactly one; required (409 verification_ambiguous otherwise) once it has several.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["reason"],"additionalProperties":false},"DeleteVerificationBody":{"type":"object","properties":{"verificationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The per-guest check to soft-delete."}},"required":["verificationId"],"additionalProperties":false},"WaiveBookingVerificationBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Why verification is being waived for the booking — mandatory; audited."}},"required":["reason"],"additionalProperties":false},"WaiveVerificationBody":{"type":"object","properties":{"verificationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The per-guest check to skip (waive)."},"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Why the check is being skipped — mandatory; recorded on the check + audit trail."}},"required":["verificationId","reason"],"additionalProperties":false},"CarryForwardVerificationBody":{"type":"object","properties":{"verificationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The per-guest check on THIS stay."},"priorVerificationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"A previously VERIFIED check for the same guest. Server-validated: same guest, same tenant, status 'verified', not itself."}},"required":["verificationId","priorVerificationId"],"additionalProperties":false},"CreateListingBlockBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The unit to withdraw from sale."},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First blocked night (inclusive)."},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End date (EXCLUSIVE — the first free night)."},"kind":{"type":"string","enum":["maintenance","owner_use","renovation","other"],"description":"Why the unit is withdrawn."},"note":{"description":"Optional operator note.","anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"startTime":{"description":"Optional intra-day window start HH:MM (with endTime; single-day; ops-only).","anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"endTime":{"description":"Optional intra-day window end HH:MM (EXCLUSIVE).","anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]}},"required":["listingId","startDate","endDate","kind"],"additionalProperties":false},"UpdateListingBlockBody":{"type":"object","properties":{"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"kind":{"type":"string","enum":["maintenance","owner_use","renovation","other"]},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"startTime":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"endTime":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"listingId":{"description":"Optional target unit (calendar drag across rows); absent = keep.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["startDate","endDate","kind"],"additionalProperties":false},"AssignCleaningBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The unit to clean."},"bookingId":{"description":"The departed stay this turnover cleans up after (optional — ad-hoc).","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"assignedTo":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaner's membership id."},"note":{"description":"A free-form dispatch note.","type":"string","maxLength":2000}},"required":["listingId","assignedTo"],"additionalProperties":false},"ScheduleCleaningBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"startDate":{"type":"string","description":"First day of the window (YYYY-MM-DD)."},"endDate":{"type":"string","description":"EXCLUSIVE end day (YYYY-MM-DD)."},"startTime":{"description":"Optional intra-day start (HH:MM); both-or-neither with endTime.","type":["string","null"]},"endTime":{"type":["string","null"]},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["listingId","startDate","endDate"],"additionalProperties":false},"CleaningStepBody":{"type":"object","properties":{"evidenceSkipReason":{"description":"Go on without this step's photo/video, stating why (8-500 characters once trimmed). Stored on the task and shown to the inspector. Ignored when the evidence is on record.","type":"string","minLength":1,"maxLength":2000}},"additionalProperties":false},"CompleteCleaningBody":{"type":"object","properties":{"evidenceSkipReason":{"description":"Go on without this step's photo/video, stating why (8-500 characters once trimmed). Stored on the task and shown to the inspector. Ignored when the evidence is on record.","type":"string","minLength":1,"maxLength":2000},"markReady":{"description":"Also clear this turnover's inspection, so the unit is ready at once. Needs inspection:clear and the after-photo on record. Ignored on an ad-hoc clean.","type":"boolean"}},"additionalProperties":false},"ReassignCleaningBody":{"type":"object","properties":{"assignedTo":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The NEW cleaner's membership id."}},"required":["assignedTo"],"additionalProperties":false},"AssignPlannedCleaningBody":{"type":"object","properties":{"assignedTo":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The cleaner's membership id."}},"required":["assignedTo"],"additionalProperties":false},"AbortCleaningBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":2000,"description":"Why the clean was aborted (cleaner no-show, …) — required."}},"required":["reason"],"additionalProperties":false},"RequestCleaningPhotoUploadBody":{"type":"object","properties":{"kind":{"type":"string","enum":["before","after"],"description":"before | after."},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime","application/pdf"],"description":"The image/video/PDF MIME type (the attachment allow-list)."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["kind","contentType"],"additionalProperties":false},"InspectionNotesBody":{"type":"object","properties":{"notes":{"type":"string","maxLength":2000}},"additionalProperties":false},"RecordInspectionFindingBody":{"type":"object","properties":{"outcome":{"type":"string","enum":["damage_found","item_missing","extra_cleaning_required"],"description":"The §1.6a finding."},"notes":{"type":"string","maxLength":2000},"description":{"description":"The damage-report body — REQUIRED for damage/missing findings.","type":"string","maxLength":4000},"estimatedCostMinor":{"description":"Optional estimate (MINOR units). The currency is SERVER-STAMPED from the tenant base currency and is not a client field (bug 2026-07-16).","type":"string","pattern":"^[1-9]\\d{0,17}$"}},"required":["outcome"],"additionalProperties":false},"RequestDamagePhotoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime","application/pdf"],"description":"The image/video/PDF MIME type (the attachment allow-list)."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"RequestInspectionPhotoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime","application/pdf"],"description":"The image/video/PDF MIME type (the attachment allow-list)."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"ReportMaintenanceTicketBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"title":{"type":"string","minLength":1,"maxLength":120},"description":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"priority":{"description":"Defaults to normal.","type":"string","enum":["low","normal","high","urgent"]}},"required":["propertyId","title"],"additionalProperties":false},"UpdateMaintenanceTicketBody":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120},"description":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"status":{"description":"Resolved is reached through the resolve action, which takes a note.","type":"string","enum":["open","in_progress","on_hold","cancelled"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"assignedTo":{"description":"An active membership of this workspace; null = anyone.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"expenseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"bookingId":{"description":"One stay on this unit or property (the booking id); null unlinks.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"additionalProperties":false},"ResolveMaintenanceTicketBody":{"type":"object","properties":{"resolutionNote":{"type":"string","minLength":1,"maxLength":2000}},"required":["resolutionNote"],"additionalProperties":false},"RequestMaintenancePhotoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/avif","video/mp4","video/webm","video/quicktime","application/pdf"]},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"SetListingLockCodeBody":{"type":"object","properties":{"audience":{"type":"string","enum":["guest","cleaner"]},"code":{"type":"string","minLength":4,"maxLength":32}},"required":["audience","code"],"additionalProperties":false},"LockCodeAudienceBody":{"type":"object","properties":{"audience":{"type":"string","enum":["guest","cleaner"]}},"required":["audience"],"additionalProperties":false},"ConnectLockVendorBody":{"type":"object","properties":{"vendor":{"type":"string","enum":["ttlock","nuki","simulator"]},"label":{"type":"string","minLength":1,"maxLength":80},"credentials":{"type":"object","propertyNames":{"type":"string","maxLength":40},"additionalProperties":{"type":"string","maxLength":400}}},"required":["vendor","label","credentials"],"additionalProperties":false},"ReconnectLockVendorBody":{"type":"object","properties":{"credentials":{"type":"object","propertyNames":{"type":"string","maxLength":40},"additionalProperties":{"type":"string","maxLength":400}}},"required":["credentials"],"additionalProperties":false},"MapListingLockBody":{"type":"object","properties":{"role":{"type":"string","enum":["unit","front_door"]},"connectionId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"externalLockId":{"type":"string","minLength":1,"maxLength":120},"codeLength":{"type":"integer","minimum":4,"maximum":9}},"required":["role","connectionId","externalLockId","codeLength"],"additionalProperties":false},"CreateGuestBody":{"type":"object","properties":{"fullName":{"type":"string","minLength":1,"maxLength":200},"phone":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"email":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"whatsapp":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"nationality":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"source":{"anyOf":[{"type":"string","enum":["direct_site","airbnb","booking_com","expedia","agoda","vrbo","whatsapp","instagram","facebook","tiktok","referral","walk_in","call","host_to_host","other"]},{"type":"null"}]}},"required":["fullName"],"additionalProperties":false},"MergeGuestBody":{"type":"object","properties":{"duplicateIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"The duplicate guests to merge INTO the path guest (their records move over). A LIST, because a duplicate set is resolved as one atomic operation — see the use-case."}},"required":["duplicateIds"],"additionalProperties":false},"UpdateGuestBody":{"type":"object","properties":{"fullName":{"type":"string","minLength":1,"maxLength":200},"phone":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"email":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"whatsapp":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"nationality":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"source":{"anyOf":[{"type":"string","enum":["direct_site","airbnb","booking_com","expedia","agoda","vrbo","whatsapp","instagram","facebook","tiktok","referral","walk_in","call","host_to_host","other"]},{"type":"null"}]}},"required":["fullName"],"additionalProperties":false},"SetGuestNoteBody":{"type":"object","properties":{"note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"additionalProperties":false},"SetGuestFlagBody":{"type":"object","properties":{"flag":{"type":"string","enum":["vip","watchlist","long_stay"]},"on":{"type":"boolean"}},"required":["flag","on"],"additionalProperties":false},"SetGuestBlacklistBody":{"type":"object","properties":{"blacklisted":{"type":"boolean"},"reason":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["blacklisted"],"additionalProperties":false},"RequestReviewBody":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"platform":{"type":"string","enum":["airbnb","google","booking_com","expedia","agoda","vrbo"]},"send":{"type":"boolean"}},"required":["bookingId","platform"],"additionalProperties":false},"RecordReviewBody":{"type":"object","properties":{"rating":{"type":"integer","minimum":1,"maximum":5},"reviewText":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["rating"],"additionalProperties":false},"ReplyReviewBody":{"type":"object","properties":{"reply":{"type":"string","minLength":1,"maxLength":4000,"description":"The host’s ONE public reply to the guest review."}},"required":["reply"],"additionalProperties":false},"HostReviewBody":{"type":"object","properties":{"respectHouseRules":{"type":"integer","minimum":1,"maximum":5},"communication":{"type":"integer","minimum":1,"maximum":5},"cleanliness":{"type":"integer","minimum":1,"maximum":5},"recommend":{"type":"boolean"},"publicText":{"type":"string","minLength":1,"maxLength":4000},"privateText":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["respectHouseRules","communication","cleanliness","recommend","publicText"],"additionalProperties":false},"RequestExtensionBody":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"newCheckOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"paymentStatus":{"type":"string","enum":["paid","partial","pending"]}},"required":["bookingId","newCheckOut","amountMinor","paymentStatus"],"additionalProperties":false},"HostedConnectSessionBody":{"type":"object","properties":{"channels":{"minItems":1,"maxItems":8,"type":"array","items":{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo","google"]}}},"additionalProperties":false},"SetChannelHoldbackBody":{"type":"object","properties":{"holdback":{"anyOf":[{"type":"integer","minimum":0,"maximum":1000},{"type":"null"}]}},"required":["holdback"],"additionalProperties":false},"SetDistributionCurrencyBody":{"type":"object","properties":{"currency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]}},"required":["currency"],"additionalProperties":false},"SetSpanAvailabilityBody":{"type":"object","properties":{"from":{"type":"string","description":"Half-open span start (yyyy-mm-dd)."},"to":{"type":"string","description":"Half-open span end (exclusive)."},"mode":{"type":"string","enum":["open","close"]},"channelExternalIds":{"description":"Channels to close (subset lane); absent/empty = all channels (stop-sell).","type":"array","items":{"type":"string"}}},"required":["from","to","mode"],"additionalProperties":false},"ChangeSyncModeBody":{"type":"object","properties":{"mode":{"type":"string","enum":["unit","pool"]}},"required":["mode"],"additionalProperties":false},"SetPaymentCollectorBody":{"type":"object","properties":{"paymentCollector":{"anyOf":[{"type":"string","enum":["channel","property"]},{"type":"null"}],"description":"Who collects this OTA's bookings by default; null returns to the channel's own."}},"required":["paymentCollector"],"additionalProperties":false},"SetChannelMarkupBody":{"type":"object","properties":{"markupBp":{"type":"integer","minimum":0,"maximum":10000,"description":"The percentage in basis points (1500 = 15%), 0 to 100%."},"markupAddMinor":{"type":"string","pattern":"^\\d+$","description":"A flat add per night in `markupCurrency` minor units (bigint-safe string)."},"markupCurrency":{"anyOf":[{"type":"string","pattern":"^[A-Z]{3}$"},{"type":"null"}],"description":"An upper-case ISO 4217 code; a flat add rides only into its own."}},"required":["markupBp","markupAddMinor","markupCurrency"],"additionalProperties":false},"ChannelHibernationBody":{"type":"object","properties":{"action":{"type":"string","enum":["pause","wake"]},"propertyId":{"description":"One property; absent = every connected property.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["action"],"additionalProperties":false},"SetBaseRateBody":{"type":"object","properties":{"scope":{"type":"string","enum":["property","listing_type","listing"],"description":"The hierarchy level to set."},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property / listing-type / listing id."},"rateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"The nightly BASE rate in minor units (decimal string; currency = the tenant base currency, server-stamped), or null to CLEAR this level."}},"required":["scope","entityId","rateMinor"],"additionalProperties":false},"SetWeekendAdjustBody":{"type":"object","properties":{"scope":{"type":"string","enum":["property","listing_type","listing"],"description":"The hierarchy level to set."},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property / listing-type / listing id."},"adjustBp":{"anyOf":[{"type":"integer","minimum":-10000,"maximum":50000},{"type":"null"}],"description":"The weekend percentage in BASIS POINTS (2000 = 20% higher, -1500 = 15% lower), or null to CLEAR this level. Applies to Friday, Saturday and Sunday nights, over whatever base rate resolves."}},"required":["scope","entityId","adjustBp"],"additionalProperties":false},"SetDateRateBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing to price per-date."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First night (inclusive), date-only ISO."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"End night (EXCLUSIVE), date-only ISO — must be after `from` (the night convention)."},"rateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"The nightly rate in minor units for every night in [from, to) (decimal string; currency = the tenant base currency, server-stamped), or null to CLEAR the override back to the base rate."}},"required":["listingId","from","to","rateMinor"],"additionalProperties":false},"AdjustDateRateBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing whose nights are re-priced."},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"First night (inclusive), date-only ISO."},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Night AFTER the last (exclusive), date-only ISO."},"adjustBp":{"type":"integer","minimum":-10000,"maximum":50000,"description":"The percentage in BASIS POINTS (2000 = 20% higher, -1500 = 15% lower), applied to what each night currently costs — an existing per-date override, else the base rate with the weekend percentage. Writes concrete per-date overrides, so it does NOT stack idempotently."}},"required":["listingId","from","to","adjustBp"],"additionalProperties":false},"AdjustChannelDateRateBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channelKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,30}$"},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"adjustBp":{"type":"integer","minimum":-10000,"maximum":50000}},"required":["listingId","channelKey","from","to","adjustBp"],"additionalProperties":false},"SetChannelRateBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channelKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,30}$"},"rateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"Minor units, or null = remove the lane (its date overrides drop too)."},"currency":{"description":"REQUIRED when setting — the lane currency; ignored on clear.","type":"string","pattern":"^[A-Z]{3}$"}},"required":["channelKey","rateMinor"],"additionalProperties":false},"SetChannelDateRatesBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channelKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,30}$"},"from":{"type":"string","description":"Half-open night span start (yyyy-mm-dd)."},"to":{"type":"string","description":"Half-open night span end (exclusive)."},"rateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"Minor units, or null = clear back to the lane base."}},"required":["listingId","channelKey","from","to","rateMinor"],"additionalProperties":false},"SetChannelRateAuthorityBody":{"type":"object","properties":{"roomTypeMapId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The channel_room_type_map row (the mapped lane) to steer."},"authority":{"type":"string","enum":["internal","external"],"description":"internal = we resolve and push the nightly rate. external = a third-party pricing tool owns the price on the OTA, so we push availability and stay rules but no rate."}},"required":["roomTypeMapId","authority"],"additionalProperties":false},"SetDateRestrictionBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"from":{"type":"string","description":"Half-open span start (yyyy-mm-dd)."},"to":{"type":"string","description":"Half-open span end (exclusive)."},"minStay":{"anyOf":[{"type":"integer","minimum":1,"maximum":90},{"type":"null"}]},"maxStay":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"closedToArrival":{"type":["boolean","null"]},"closedToDeparture":{"type":["boolean","null"]},"stopSell":{"type":["boolean","null"]},"clear":{"description":"True = clear the span back to defaults.","type":"boolean"}},"required":["listingId","from","to"],"additionalProperties":false},"PriceRuleBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"scope":{"$ref":"#/components/schemas/PriceRuleScope"},"weekdays":{"anyOf":[{"minItems":1,"maxItems":7,"type":"array","items":{"type":"integer","minimum":1,"maximum":7}},{"type":"null"}],"description":"ISO weekdays (1 = Monday … 7 = Sunday); null = any day."},"dateFrom":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"dateTo":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"minNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"maxNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"leadMinDays":{"anyOf":[{"type":"integer","minimum":0,"maximum":730},{"type":"null"}]},"leadMaxDays":{"anyOf":[{"type":"integer","minimum":0,"maximum":730},{"type":"null"}]},"occupancyMinPct":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"occupancyMaxPct":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"paceSoldPct":{"anyOf":[{"type":"integer","minimum":0,"maximum":99},{"type":"null"}]},"paceWindowDays":{"anyOf":[{"type":"integer","minimum":1,"maximum":180},{"type":"null"}]},"adjustBp":{"type":"integer","minimum":-10000,"maximum":50000,"description":"The percentage change in basis points (+1500 = +15%)."},"addMinor":{"anyOf":[{"type":"string","pattern":"^-?\\d{1,13}$"},{"type":"null"}],"description":"A flat amount per night in minor units, signed; null = none."},"priority":{"type":"integer","minimum":0,"maximum":9999},"active":{"type":"boolean"}},"required":["name","scope","weekdays","dateFrom","dateTo","minNights","maxNights","leadMinDays","leadMaxDays","occupancyMinPct","occupancyMaxPct","paceSoldPct","paceWindowDays","adjustBp","addMinor","priority","active"],"additionalProperties":false},"PriceRuleScope":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","const":"workspace"}},"required":["kind"],"additionalProperties":false},{"type":"object","properties":{"kind":{"type":"string","enum":["property","listing_type","listing"]},"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["kind","id"],"additionalProperties":false}],"description":"Where the rule applies: the whole workspace, or one property, type or unit.","type":"object"},"PriceRulePreviewBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"nights":{"type":"integer","minimum":1,"maximum":90},"stayNights":{"type":"integer","minimum":1,"maximum":365},"draft":{"description":"An unsaved rule to fold in.","$ref":"#/components/schemas/PriceRuleBody"},"replacesRuleId":{"description":"The saved rule the draft replaces, left out of the preview.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["listingId"],"additionalProperties":false},"SetPriceRuleLimitsBody":{"type":"object","properties":{"level":{"type":"string","enum":["property","listing_type"]},"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"floorMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}]},"ceilingMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}]}},"required":["level","id","floorMinor","ceilingMinor"],"additionalProperties":false},"AddFolioChargeBody":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120},"category":{"type":"string","enum":["early_checkin","late_checkout","cleaning","transport","food","experience","other"]},"amountMinor":{"type":"string","pattern":"^\\d{1,12}$"},"quantity":{"type":"integer","minimum":1,"maximum":99}},"required":["label","category","amountMinor"],"additionalProperties":false,"description":"An amount the guest owes; moves no money."},"ReverseFolioChargeBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["reason"],"additionalProperties":false},"CollectFolioChargeBody":{"type":"object","properties":{"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"collectedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["financialAccountId"],"additionalProperties":false,"description":"Record that the guest paid one folio charge."},"DecideExtraRequestBody":{"type":"object","properties":{"decision":{"type":"string","enum":["confirm","decline"]},"reason":{"type":"string","maxLength":500}},"required":["decision"],"additionalProperties":false},"UpsellSettingsBody":{"type":"object","properties":{"offerInGuestApp":{"type":"boolean"},"category":{"anyOf":[{"type":"string","enum":["early_checkin","late_checkout","cleaning","transport","food","experience","other"]},{"type":"null"}]},"maxPerStay":{"anyOf":[{"type":"integer","minimum":1,"maximum":99},{"type":"null"}]},"cutoffHours":{"anyOf":[{"type":"integer","minimum":0,"maximum":720},{"type":"null"}]},"minNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"maxNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"availableFrom":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"availableTo":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"variants":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60},"amountMinor":{"type":"string","pattern":"^\\d{1,12}$"}},"required":["name","amountMinor"],"additionalProperties":false}}},"required":["offerInGuestApp","category","maxPerStay","cutoffHours","minNights","maxNights","availableFrom","availableTo","variants"],"additionalProperties":false,"description":"How an optional extra is offered in the guest app."},"UpsellPhotoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","minLength":1,"maxLength":100},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"SetUpsellPhotoBody":{"type":"object","properties":{"objectKey":{"anyOf":[{"type":"string","minLength":1,"maxLength":512},{"type":"null"}]}},"required":["objectKey"],"additionalProperties":false},"SetAmenitiesBody":{"type":"object","properties":{"scope":{"type":"string","enum":["property","listing_type","listing"],"description":"The hierarchy level — the same three grains the base rate uses."},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property / listing-type / listing id."},"amenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"description":"The canonical amenity keys for THIS level. An empty array CLEARS the level, so it falls through to the one below."}},"required":["scope","entityId","amenities"],"additionalProperties":false},"SetContentHierarchyBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"importantInformation":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"petsPolicy":{"anyOf":[{"type":"string","enum":["allowed","by_arrangements","not_allowed"]},{"type":"null"}]},"smokingPolicy":{"anyOf":[{"type":"string","enum":["no_smoking","smoking_allowed","designated_areas"]},{"type":"null"}]},"parkingType":{"anyOf":[{"type":"string","enum":["on_site","nearby","none"]},{"type":"null"}]},"wifiCoverage":{"anyOf":[{"type":"string","enum":["entire_property","public_areas","none"]},{"type":"null"}]}},"required":["description","importantInformation","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false,"description":"A whole-object replace of ONE level's content card. Blank/null clears the field at that level, which makes it inherit again."},"SetPropertyKnowledgeBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"houseManual":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkInInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkOutInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"cleaningInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"parkingInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"trashInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"luggageStorage":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"buildingName":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["houseManual","checkInInstructions","checkOutInstructions","cleaningInstructions","parkingInstructions","trashInstructions","luggageStorage","buildingName"],"additionalProperties":false,"description":"A whole-object replace of ONE level's property-knowledge card. Blank/null clears the field at that level, which makes it inherit again."},"SendMessageBody":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":4000,"description":"The outbound message text (trimmed; 1..4000 chars)."},"channel":{"description":"The transport — defaults to in_app (the thread itself). An OTA replies into that OTA's linked thread.","type":"string","enum":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"]},"attachmentIds":{"description":"READY pre-send drafts on this conversation to bind (≤8).","maxItems":8,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"mentions":{"description":"Seats (membership ids) tagged in this message (0244). Each must be an ACTIVE seat in the tenant; one that is not rejects the whole send rather than being dropped, so a message can never claim to have tagged somebody who was never told.","maxItems":10,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["body"],"additionalProperties":false},"AddInternalNoteBody":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":4000},"mentions":{"description":"Seats (membership ids) tagged in this note (0244) — the hand-off case: the text stays staff-only and the person named is notified.","maxItems":10,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["body"],"additionalProperties":false},"CreateImportBatchBody":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":200},"text":{"type":"string","minLength":1,"maxLength":2000000,"description":"Pasted or uploaded delimited text. Tab or comma, detected from the header line."}},"required":["filename","text"],"additionalProperties":false},"SetImportMappingBody":{"type":"object","properties":{"columnMapping":{"type":"object","propertyNames":{"type":"string","enum":["externalId","listingRef","checkIn","checkOut","guestName","guestPhone","guestEmail","amount","commission","currency"]},"additionalProperties":{"type":"string"},"description":"{ ourField: theirHeader }. Missing a required field is refused."},"listingMapping":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"{ theirUnitRef: ourListingId }. An unmapped ref quarantines its rows."},"dateOrder":{"type":"string","enum":["dmy","mdy","ymd"],"description":"How to read an ambiguous numeric date IN THIS FILE. 03/04/2026 is 3 April under dmy and 4 March under mdy; nothing in the value distinguishes them."},"numberFormat":{"type":"string","enum":["dot_decimal","comma_decimal"],"description":"Which separator is the decimal point. 1.005 is 1.005 under dot_decimal and 1005 under comma_decimal — a 1000x difference."},"defaultCurrency":{"type":"string","minLength":3,"maxLength":3,"description":"The currency imported amounts are in when the file does not carry one."}},"required":["columnMapping","listingMapping","dateOrder","numberFormat","defaultCurrency"],"additionalProperties":false},"SetImportCutoffBody":{"type":"object","properties":{"recognizeFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Stays CHECKING IN on or after this date get their payment posted. Earlier stays import as records with no ledger entry at all."}},"required":["recognizeFrom"],"additionalProperties":false},"CreateMessageTemplateBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"body":{"type":"string","minLength":1,"maxLength":4000},"channels":{"default":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"],"minItems":1,"type":"array","items":{"type":"string","enum":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"]}},"categories":{"default":["general"],"minItems":1,"type":"array","items":{"type":"string","enum":["inquiry","pre_arrival","in_stay","checkout","review","general"]}}},"required":["name","body"],"additionalProperties":false},"SetAutoResponseRuleBody":{"type":"object","properties":{"phase":{"type":"string","enum":["inquiry","pre_arrival","in_stay","post_stay"]},"templateId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"enabled":{"default":true,"type":"boolean"},"channels":{"default":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"],"minItems":1,"type":"array","items":{"type":"string","enum":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"]}},"respondWhen":{"default":"outside_hours","type":"string","enum":["always","outside_hours"]},"hoursFrom":{"default":null,"anyOf":[{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},{"type":"null"}]},"hoursTo":{"default":null,"anyOf":[{"type":"string","pattern":"^([01][0-9]|2[0-3]):[0-5][0-9]$"},{"type":"null"}]},"cooldownMinutes":{"default":240,"type":"integer","minimum":15,"maximum":10080}},"required":["phase","templateId"],"additionalProperties":false},"AddStarterTemplatesBody":{"type":"object","properties":{"keys":{"minItems":1,"maxItems":63,"type":"array","items":{"type":"string","minLength":1,"maxLength":64},"description":"Catalog keys to take. An unknown key is an ERROR (client and server disagree about the catalog); an already-added one is SKIPPED, so one collision never loses the rest of the batch."}},"required":["keys"],"additionalProperties":false},"UpdateMessageTemplateBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"body":{"type":"string","minLength":1,"maxLength":4000},"channels":{"minItems":1,"type":"array","items":{"type":"string","enum":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"]}},"categories":{"minItems":1,"type":"array","items":{"type":"string","enum":["inquiry","pre_arrival","in_stay","checkout","review","general"]}},"isArchived":{"type":"boolean"}},"additionalProperties":false},"RenderMessageTemplateBody":{"type":"object","properties":{"templateId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["templateId"],"additionalProperties":false},"SetTenantVariableBody":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","description":"The {{key}}. Lower-case, 2–41 chars, may not shadow a built-in token."},"label":{"type":"string","minLength":1,"maxLength":80},"value":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["key","label","value"],"additionalProperties":false},"CreateInquiryFromConversationBody":{"type":"object","properties":{"checkIn":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"checkOut":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},"adults":{"type":"integer","minimum":1,"maximum":64},"children":{"type":"integer","minimum":0,"maximum":64},"infants":{"type":"integer","minimum":0,"maximum":64},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"note":{"type":"string","maxLength":2000}},"required":["checkIn","checkOut","adults","children","infants"],"additionalProperties":false},"RequestAttachmentUploadBody":{"type":"object","properties":{"contentType":{"type":"string","maxLength":100},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"AiFact":{"type":"object","properties":{"question":{"type":"string","maxLength":200},"answer":{"type":"string","maxLength":1000}},"required":["question","answer"],"additionalProperties":false,"description":"A question guests ask and the answer the host wrote."},"SetStaffPhoneLinkBody":{"type":"object","properties":{"whatsapp":{"type":"string","minLength":8,"maxLength":20,"description":"The number as entered — normalized server-side to strict E.164."}},"required":["whatsapp"],"additionalProperties":false},"CreateTreasuryAccountBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"type":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"currency":{"type":"string","minLength":3,"maxLength":3},"openingBalanceMinor":{"type":"string","pattern":"^\\d+$"},"openedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"bankDetails":{"$ref":"#/components/schemas/TreasuryAccountBankDetails"}},"required":["name","type","currency"],"additionalProperties":false},"TreasuryAccountBankDetails":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120,"description":"The operator's own name for the account. NEVER shown to a guest."},"bankName":{"type":"string","minLength":1,"maxLength":120,"description":"e.g. HBL, Meezan."},"accountTitle":{"type":"string","minLength":1,"maxLength":160,"description":"The name the account is held in."},"accountNumber":{"type":"string","minLength":1,"maxLength":64},"iban":{"type":"string","minLength":15,"maxLength":42,"pattern":"^[A-Za-z0-9 ]+$","description":"ISO 13616 IBAN, mod-97 validated. Stored and printed grouped in fours (`PK36 SCBL 0000 …`)."},"swift":{"anyOf":[{"type":"string","minLength":8,"maxLength":11},{"type":"null"}]},"branch":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"notes":{"description":"Free lines printed under the table, verbatim — the escape hatch.","anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["label","bankName","accountTitle","accountNumber","iban"],"additionalProperties":false},"RecordTransferBody":{"type":"object","properties":{"transferId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"fromAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"toAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"occurredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"memo":{"type":"string","maxLength":300}},"required":["transferId","fromAccountId","toAccountId","amountMinor","occurredOn"],"additionalProperties":false},"RecordConversionBody":{"type":"object","properties":{"conversionId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"fromAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"toAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"fromAmountMinor":{"type":"string","pattern":"^\\d+$"},"toAmountMinor":{"type":"string","pattern":"^\\d+$"},"occurredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"memo":{"type":"string","maxLength":300}},"required":["conversionId","fromAccountId","toAccountId","fromAmountMinor","toAmountMinor","occurredOn"],"additionalProperties":false},"SettleChannelPayoutBody":{"type":"object","properties":{"payoutId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channelAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"landedMinor":{"type":"string","pattern":"^\\d+$"},"receivedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"bookingIds":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"reference":{"type":"string","maxLength":200}},"required":["payoutId","channelAccountId","landedMinor","receivedOn","bookingIds"],"additionalProperties":false},"UpsertChannelAccountBody":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string","minLength":1,"maxLength":80},"payoutFinancialAccountId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["label"],"additionalProperties":false},"ExecutePayoutSweepBody":{"type":"object","properties":{"sweepId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"occurredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"legs":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"object","properties":{"sourceAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"destinationAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"landedMinor":{"type":"string","pattern":"^\\d+$"}},"required":["sourceAccountId","destinationAccountId","amountMinor","landedMinor"],"additionalProperties":false}}},"required":["sweepId","occurredOn","legs"],"additionalProperties":false},"RequestExpenseReceiptUploadBody":{"type":"object","properties":{"contentType":{"type":"string","maxLength":100,"description":"One of the receipt allow-list: image/jpeg, image/png, image/webp, image/avif, application/pdf. Video is deliberately NOT a receipt."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"AttachExpenseReceiptBody":{"type":"object","properties":{"objectKey":{"type":"string","maxLength":500},"contentType":{"type":"string","maxLength":100},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"label":{"type":"string","maxLength":120}},"required":["objectKey","contentType"],"additionalProperties":false},"CreateExpenseCategoryBody":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,60}$"},"name":{"type":"string","minLength":1,"maxLength":120},"parentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"accountClass":{"type":"string"},"costBehavior":{"type":"string","enum":["fixed","variable"]}},"required":["key","name","accountClass"],"additionalProperties":false},"UpdateExpenseCategoryBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"costBehavior":{"anyOf":[{"type":"string","enum":["fixed","variable"]},{"type":"null"}]},"isActive":{"type":"boolean"}},"additionalProperties":false},"RecordExpenseBody":{"type":"object","properties":{"expenseId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"categoryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"scope":{"type":"string","enum":["tenant","property","listing"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"incurredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"paidFromAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"vendor":{"type":"string","maxLength":160},"memo":{"type":"string","maxLength":1000},"claimedByMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"claimedByName":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"passThroughFlag":{"type":"boolean"}},"required":["expenseId","categoryId","scope","amountMinor","incurredOn","paidFromAccountId"],"additionalProperties":false},"UpdateExpenseDetailsBody":{"type":"object","properties":{"vendor":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"memo":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]},"claimedByMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"claimedByName":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]}},"additionalProperties":false},"CorrectExpenseBody":{"type":"object","properties":{"correctionId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"categoryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"scope":{"type":"string","enum":["tenant","property","listing"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"incurredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"paidFromAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"vendor":{"type":"string","maxLength":160},"memo":{"type":"string","maxLength":1000},"claimedByMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"claimedByName":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"passThroughFlag":{"type":"boolean"},"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["correctionId","categoryId","scope","amountMinor","incurredOn","paidFromAccountId","reason"],"additionalProperties":false},"RecordVendorBillBody":{"type":"object","properties":{"expenseId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"categoryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"scope":{"type":"string","enum":["tenant","property","listing"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"incurredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"dueOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"vendor":{"type":"string","maxLength":160},"memo":{"type":"string","maxLength":1000},"claimedByMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"claimedByName":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"passThroughFlag":{"type":"boolean"},"payableInstanceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["expenseId","categoryId","scope","amountMinor","incurredOn"],"additionalProperties":false},"SettleVendorBillBody":{"type":"object","properties":{"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"paidOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"reference":{"type":"string","maxLength":160}},"required":["financialAccountId"],"additionalProperties":false},"VoidVendorBillBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":300}},"required":["reason"],"additionalProperties":false},"SetPropertyModelBody":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"model":{"type":"string","enum":["owned","leased","managed","profit_share","investor"]},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["model","effectiveFrom"],"additionalProperties":false},"UpsertLeaseBody":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"landlordPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"landlordName":{"type":"string","maxLength":160},"rentMinor":{"type":"string","pattern":"^\\d+$"},"termStart":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"termEnd":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"depositMinor":{"type":"string","pattern":"^\\d+$"},"landlordProfitSharePct":{"type":"string","pattern":"^\\d{1,3}(\\.\\d{1,2})?$"},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["rentMinor","termStart","landlordProfitSharePct"],"additionalProperties":false},"UpsertManagementBody":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"ownerPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ownerName":{"type":"string","maxLength":160},"feeBase":{"type":"string","enum":["net","gross","revenue_split"]},"feePct":{"type":"string","pattern":"^\\d{1,3}(\\.\\d{1,2})?$"},"reserveFloatPct":{"type":"string","pattern":"^\\d{1,3}(\\.\\d{1,2})?$"},"payoutSchedule":{"type":"string","enum":["monthly","quarterly"]},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["feeBase","feePct"],"additionalProperties":false},"UpsertInvestmentBody":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"investorName":{"type":"string","maxLength":160},"returnModel":{"type":"string","enum":["pro_rata_split","preferred_return_then_split"]},"investorSplitPct":{"type":"string","pattern":"^\\d{1,3}(\\.\\d{1,3})?$"},"capitalMinor":{"type":"string","pattern":"^\\d+$"},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"termStart":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"termEnd":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]}},"required":["investorSplitPct"],"additionalProperties":false},"ApplyPoolEquityBody":{"type":"object","properties":{"totalUnits":{"type":"string","pattern":"^\\d{1,5}(\\.\\d{1,3})?$"},"operatorMgmtSharePct":{"type":"string","pattern":"^\\d{1,3}(\\.\\d{1,3})?$"},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"holdings":{"minItems":1,"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/PoolHolding"}}},"required":["totalUnits","operatorMgmtSharePct","holdings"],"additionalProperties":false},"PoolHolding":{"type":"object","properties":{"investorPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"investorName":{"type":"string","minLength":1,"maxLength":160},"units":{"type":"string","pattern":"^\\d{1,5}(\\.\\d{1,3})?$"},"capitalMinor":{"type":"string","pattern":"^\\d+$"}},"required":["units"],"additionalProperties":false},"AddPropertyCapitalLineBody":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"category":{"type":"string","enum":["furniture_fixtures","appliances_electronics","interior_decor","linen_kitchenware_consumables","general_capex"]},"name":{"type":"string","minLength":1,"maxLength":160},"fundedBy":{"type":"string","enum":["operator","owner","investor"]},"funderPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"incurredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"paidFromAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"memo":{"type":"string","maxLength":300}},"required":["category","name","fundedBy","amountMinor","incurredOn"],"additionalProperties":false},"CustomReportRunBody":{"$ref":"#/components/schemas/CustomReportSpec"},"ReportDimension":{"type":"object","properties":{"field":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_]*$"},"bucket":{"type":"string","enum":["day","week","month","quarter","year","day_of_week","hour"]}},"required":["field"],"additionalProperties":false},"CustomReportMeasure":{"type":"object","properties":{"field":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_]*$"},"fn":{"type":"string","enum":["sum","avg","median","min","max","count","count_distinct"]},"derive":{"type":"string","enum":["share"]}},"required":["field","fn"],"additionalProperties":false},"CustomReportFilterGroup":{"type":"object","properties":{"match":{"type":"string","enum":["all","any"]},"negate":{"type":"boolean"},"conditions":{"minItems":1,"maxItems":25,"type":"array","items":{"$ref":"#/components/schemas/CustomReportCondition"}}},"required":["match","conditions"],"additionalProperties":false},"CustomReportCondition":{"type":"object","properties":{"field":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","enum":["eq","ne","in","not_in","contains","not_contains","starts_with","ends_with","gt","gte","lt","lte","between","is_null","is_not_null","is_empty","is_not_empty"]},"value":{"type":"string","maxLength":200},"values":{"maxItems":100,"type":"array","items":{"type":"string","maxLength":200}}},"required":["field","operator"],"additionalProperties":false},"CustomReportHaving":{"type":"object","properties":{"measure":{"type":"string","minLength":1,"maxLength":96,"pattern":"^[a-z][a-z0-9_]*$"},"operator":{"type":"string","enum":["eq","ne","gt","gte","lt","lte"]},"value":{"type":"string","maxLength":40}},"required":["measure","operator","value"],"additionalProperties":false},"CustomReportWindow":{"type":"object","properties":{"field":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_]*$"},"preset":{"type":"string","enum":["today","yesterday","last_7_days","last_30_days","last_90_days","last_365_days","this_week","last_week","this_month","last_month","this_quarter","last_quarter","this_year","last_year","month_to_date","quarter_to_date","year_to_date","all_time"]},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"additionalProperties":false},"CustomReportSort":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":96,"pattern":"^[a-z][a-z0-9_]*$"},"direction":{"type":"string","enum":["asc","desc"]},"nulls":{"type":"string","enum":["first","last"]}},"required":["key","direction"],"additionalProperties":false},"CustomReportColumnOption":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":96,"pattern":"^[a-z][a-z0-9_]*$"},"label":{"type":"string","maxLength":60},"decimals":{"type":"integer","minimum":0,"maximum":6},"compact":{"type":"boolean"},"hidden":{"type":"boolean"}},"required":["key"],"additionalProperties":false},"CustomReportExportOptions":{"type":"object","properties":{"orientation":{"type":"string","enum":["landscape","portrait"]},"pageSize":{"type":"string","enum":["a4","letter","a3"]},"includeFilters":{"type":"boolean"}},"additionalProperties":false},"CustomReportSpec":{"type":"object","properties":{"dataset":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_]*$"},"title":{"type":"string","maxLength":120},"notes":{"type":"string","maxLength":600},"columns":{"maxItems":40,"type":"array","items":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9_]*$"}},"groupBy":{"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/ReportDimension"}},"measures":{"maxItems":15,"type":"array","items":{"$ref":"#/components/schemas/CustomReportMeasure"}},"filters":{"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/CustomReportFilterGroup"}},"having":{"maxItems":10,"type":"array","items":{"$ref":"#/components/schemas/CustomReportHaving"}},"window":{"$ref":"#/components/schemas/CustomReportWindow"},"sort":{"maxItems":5,"type":"array","items":{"$ref":"#/components/schemas/CustomReportSort"}},"limit":{"type":"integer","minimum":1,"maximum":10000},"offset":{"type":"integer","minimum":0,"maximum":1000000},"distinct":{"type":"boolean"},"showTotals":{"type":"boolean"},"subtotals":{"type":"boolean"},"columnOptions":{"maxItems":40,"type":"array","items":{"$ref":"#/components/schemas/CustomReportColumnOption"}},"exportOptions":{"$ref":"#/components/schemas/CustomReportExportOptions"}},"required":["dataset"],"additionalProperties":false},"UpsertFeeBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"kind":{"type":"string","enum":["per_stay","per_night","per_guest","tax_pct","tax_per_night"]},"amountMinor":{"type":"string","pattern":"^\\d+$"},"pct":{"type":"string","pattern":"^\\d{1,3}(\\.\\d{1,2})?$"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"minGuests":{"anyOf":[{"type":"integer","minimum":0,"maximum":20},{"type":"null"}]},"taxable":{"type":"boolean"},"isActive":{"type":"boolean"},"isOptional":{"type":"boolean"},"showOnSite":{"type":"boolean"},"publicName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"publicDescription":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":0,"maximum":9999}},"required":["name","kind"],"additionalProperties":false},"UpdateWorkspaceSettingsBody":{"type":"object","properties":{"country":{"type":"string","minLength":2,"maxLength":2},"timezone":{"type":"string","minLength":1},"baseCurrency":{"type":"string","minLength":3,"maxLength":3},"dateFormat":{"type":"string","enum":["dd_mmm_yyyy","mmm_dd_yyyy","iso","dd_mm_yyyy","mm_dd_yyyy"]},"timeFormat":{"type":"string","enum":["h24","h12"]}},"required":["country","timezone","dateFormat","timeFormat"],"additionalProperties":false},"UpdateWhiteLabelBody":{"type":"object","properties":{"brandColor":{"anyOf":[{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},{"type":"null"}]}},"required":["brandColor"],"additionalProperties":false},"RequestLogoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","maxLength":100,"description":"One of the logo allow-list: image/jpeg, image/png, image/webp, image/avif. SVG is refused — it is script-bearing and the quotation page is public."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"AttachLogoBody":{"type":"object","properties":{"objectKey":{"type":"string","maxLength":500},"contentType":{"type":"string","maxLength":100},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["objectKey","contentType"],"additionalProperties":false},"SetTenantPaymentRailBody":{"type":"object","properties":{"rail":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"enabled":{"type":"boolean"}},"required":["rail","enabled"],"additionalProperties":false},"AddTenantPaymentRailBody":{"type":"object","properties":{"rail":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"label":{"type":"string","minLength":1,"maxLength":60},"settlesTo":{"anyOf":[{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},{"type":"null"}]}},"required":["rail","label","settlesTo"],"additionalProperties":false},"RegisterTreasuryTypeBody":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"label":{"type":"string","minLength":1,"maxLength":60}},"required":["key","label"],"additionalProperties":false},"SubmitSaasReceiptBody":{"type":"object","properties":{"paidSettlementMinor":{"type":"string","pattern":"^\\d+$"},"receiptReference":{"type":"string","minLength":1,"maxLength":200},"receiptRail":{"type":"string","enum":["bank_transfer","wise","payoneer","other"]}},"required":["paidSettlementMinor","receiptReference","receiptRail"],"additionalProperties":false},"SubmitSaasPaymentBody":{"type":"object","properties":{"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"method":{"type":"string","enum":["bank_transfer","cash"]},"amountSettlementMinor":{"type":"string","pattern":"^\\d+$"},"paidAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"bankTxnRef":{"type":"string","minLength":1,"maxLength":200},"receivedByName":{"type":"string","minLength":1,"maxLength":200},"receivedLocation":{"type":"string","maxLength":200},"notes":{"type":"string","maxLength":1000},"evidenceIds":{"maxItems":10,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["invoiceId","method","amountSettlementMinor","paidAt","evidenceIds"],"additionalProperties":false},"RequestPaymentEvidenceBody":{"type":"object","properties":{"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","application/pdf"]}},"required":["contentType"],"additionalProperties":false},"ConfirmPaymentEvidenceBody":{"type":"object","properties":{},"additionalProperties":false},"ChangePlanBody":{"type":"object","properties":{"targetPlanCode":{"type":"string","pattern":"^[a-z][a-z0-9_]*$"},"reason":{"type":"string","maxLength":500}},"required":["targetPlanCode"],"additionalProperties":false},"InviteMemberBody":{"type":"object","properties":{"email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"name":{"type":"string","minLength":1,"maxLength":120},"accountRole":{"type":"string","enum":["owner","admin","billing","member","task_only"]},"operationalRoles":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","enum":["poc","booking_manager","account_manager","guest_manager","property_manager","airbnb_manager","conflict_resolution_manager","cleaner","housekeeping_coordinator","inspector","maintenance","external_accountant","auditor","front_desk","co_host","investor","content_manager","availability_manager","channel_pricing_manager","channel_setup"]}}},"required":["email","name","accountRole"],"additionalProperties":false},"UpdateMemberSeatBody":{"type":"object","properties":{"accountRole":{"type":"string","enum":["owner","admin","billing","member","task_only"]},"seatStatus":{"type":"string","enum":["active","deactivated"]}},"additionalProperties":false},"UpdateMemberRolesBody":{"type":"object","properties":{"grant":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","enum":["poc","booking_manager","account_manager","guest_manager","property_manager","airbnb_manager","conflict_resolution_manager","cleaner","housekeeping_coordinator","inspector","maintenance","external_accountant","auditor","front_desk","co_host","investor","content_manager","availability_manager","channel_pricing_manager","channel_setup"]}},"revoke":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","enum":["poc","booking_manager","account_manager","guest_manager","property_manager","airbnb_manager","conflict_resolution_manager","cleaner","housekeeping_coordinator","inspector","maintenance","external_accountant","auditor","front_desk","co_host","investor","content_manager","availability_manager","channel_pricing_manager","channel_setup"]}}},"additionalProperties":false},"SendMemberPasswordResetBody":{"type":"object","properties":{},"additionalProperties":false},"CreateTeamBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"description":{"type":"string","maxLength":300},"roles":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","enum":["poc","booking_manager","account_manager","guest_manager","property_manager","airbnb_manager","conflict_resolution_manager","cleaner","housekeeping_coordinator","inspector","maintenance","external_accountant","auditor","front_desk","co_host","investor","content_manager","availability_manager","channel_pricing_manager","channel_setup"]}}},"required":["name"],"additionalProperties":false},"UpdateTeamBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"description":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"add":{"default":[],"maxItems":100,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"remove":{"default":[],"maxItems":100,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"grantRoles":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","enum":["poc","booking_manager","account_manager","guest_manager","property_manager","airbnb_manager","conflict_resolution_manager","cleaner","housekeeping_coordinator","inspector","maintenance","external_accountant","auditor","front_desk","co_host","investor","content_manager","availability_manager","channel_pricing_manager","channel_setup"]}},"revokeRoles":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","enum":["poc","booking_manager","account_manager","guest_manager","property_manager","airbnb_manager","conflict_resolution_manager","cleaner","housekeeping_coordinator","inspector","maintenance","external_accountant","auditor","front_desk","co_host","investor","content_manager","availability_manager","channel_pricing_manager","channel_setup"]}}},"additionalProperties":false},"AssignScopeBody":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"teamId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["propertyId"],"additionalProperties":false},"SetEnforcedScopeRolesBody":{"type":"object","properties":{"roleKeys":{"maxItems":20,"type":"array","items":{"type":"string","enum":["poc","booking_manager","account_manager","guest_manager","property_manager","airbnb_manager","conflict_resolution_manager","cleaner","housekeeping_coordinator","inspector","maintenance","external_accountant","auditor","front_desk","co_host","investor","content_manager","availability_manager","channel_pricing_manager","channel_setup"]}}},"required":["roleKeys"],"additionalProperties":false},"CreateStaffShiftBody":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["duty","on_call"]},"startAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"endAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"note":{"type":"string","maxLength":300}},"required":["membershipId","kind","startAt","endAt"],"additionalProperties":false},"RequestInvestorPayoutBody":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"reference":{"type":"string","maxLength":200},"memo":{"type":"string","maxLength":300}},"required":["partyId","financialAccountId","amountMinor"],"additionalProperties":false},"DecideInvestorPayoutBody":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","reject"]},"entryDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["decision"],"additionalProperties":false},"RecordCapitalContributionBody":{"type":"object","properties":{"investorPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"receivedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"memo":{"type":"string","maxLength":300}},"required":["investorPartyId","propertyId","financialAccountId","amountMinor","receivedOn"],"additionalProperties":false},"NoticeInvestorExitBody":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"noticeOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"noticeDays":{"type":"integer","minimum":0,"maximum":3650},"frrDecision":{"type":"string","enum":["operator_buys","released_to_investor"]},"overrideValueMinor":{"type":"string","pattern":"^\\d+$"},"overrideReason":{"type":"string","maxLength":300},"note":{"type":"string","maxLength":500}},"required":["partyId","propertyId","noticeOn"],"additionalProperties":false},"DecideInvestorExitBody":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","cancel"]}},"required":["decision"],"additionalProperties":false},"SettleInvestorExitBody":{"type":"object","properties":{"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"entryDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["financialAccountId"],"additionalProperties":false},"CreateInvestorAssignmentBody":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]}},"required":["partyId"],"additionalProperties":false},"CreateInvestorPartyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200}},"required":["name"],"additionalProperties":false},"UpsertPayeeAccountBody":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"membershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"label":{"type":"string","minLength":1,"maxLength":120},"route":{"type":"string","enum":["bank_transfer","raast","cash_via_staff"]},"bankName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"accountTitle":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"accountNumber":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"iban":{"anyOf":[{"type":"string","maxLength":42},{"type":"null"}]},"payeePhone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}]},"cashCarrierMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"isDefault":{"type":"boolean"}},"required":["label","route"],"additionalProperties":false},"CreateOwnerPartyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"kind":{"type":"string","enum":["owner","landlord"]}},"required":["name","kind"],"additionalProperties":false},"LinkOwnerSeatBody":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["partyId","membershipId"],"additionalProperties":false},"UnassignOwnerHoldingBody":{"type":"object","properties":{"agreementId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"model":{"type":"string","enum":["managed","leased"]}},"required":["agreementId","model"],"additionalProperties":false},"LinkInvestorUserBody":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["partyId","membershipId"],"additionalProperties":false},"CaptureTrackRecordBody":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120},"from":{"type":"string"},"to":{"type":"string"},"badges":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/TrackRecordBadge"}}},"required":["label","from","to"],"additionalProperties":false},"TrackRecordBadge":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":120},"source":{"type":"string","minLength":1,"maxLength":120},"asOf":{"type":"string"}},"required":["label","source","asOf"],"additionalProperties":false},"SavePlanLineBody":{"type":"object","properties":{"funderPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"category":{"type":"string","enum":["lease_security_deposit","advance_rent","furniture_fixtures","appliances_electronics","interior_decor","linen_kitchenware_consumables","general_capex"]},"plannedMinor":{"type":"string","pattern":"^\\d{1,18}$"},"note":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"required":["funderPartyId","propertyId","category","plannedMinor"],"additionalProperties":false},"SaveDealBody":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"partyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"prospectName":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}]},"proposalId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"agreementId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"status":{"type":"string","enum":["prospect","proposed","accepted","executed","funded","setup","live","lost"]},"committedMinor":{"type":"string","pattern":"^\\d{1,18}$"},"expectedCloseOn":{"type":["string","null"]},"note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["title","status","committedMinor"],"additionalProperties":false},"AddTrancheBody":{"type":"object","properties":{"dueOn":{"type":"string"},"amountMinor":{"type":"string","pattern":"^\\d{1,18}$"},"label":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}},"required":["dueOn","amountMinor"],"additionalProperties":false},"MatchTrancheBody":{"type":"object","properties":{"trancheId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"contributionId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["trancheId","contributionId"],"additionalProperties":false},"SaveUnitLaunchBody":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"targetLiveOn":{"type":"string"},"furnishedOn":{"type":["string","null"]},"photographedOn":{"type":["string","null"]},"listedOn":{"type":["string","null"]},"liveOn":{"type":["string","null"]},"note":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}]}},"required":["listingId","targetLiveOn"],"additionalProperties":false},"SaveProposalBody":{"type":"object","properties":{"partyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"prospectName":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}]},"title":{"type":"string","minLength":1,"maxLength":200},"modelId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"scenarioId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"trackRecordSnapshotId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"capitalMinor":{"type":"string","pattern":"^\\d{1,18}$"},"unitPriceMinor":{"type":"string","pattern":"^\\d{1,18}$"},"noticeDays":{"type":"integer","minimum":0,"maximum":3650}},"required":["title","modelId","scenarioId","trackRecordSnapshotId","capitalMinor","unitPriceMinor","noticeDays"],"additionalProperties":false},"SendProposalBody":{"type":"object","properties":{"ttlDays":{"type":"integer","minimum":1,"maximum":365}},"additionalProperties":false},"DecideProposalBody":{"type":"object","properties":{"decision":{"type":"string","enum":["accepted","declined","withdrawn"]},"reason":{"type":"string","maxLength":500}},"required":["decision"],"additionalProperties":false},"LinkOwnerPartyBody":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyName":{"type":"string","minLength":1,"maxLength":160}},"required":["membershipId","partyName"],"additionalProperties":false},"RequestOwnerPayoutBody":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"periodMonth":{"type":"string","pattern":"^\\d{4}-\\d{2}-01$"},"reference":{"type":"string","maxLength":200},"memo":{"type":"string","maxLength":300}},"required":["partyId","financialAccountId","amountMinor","periodMonth"],"additionalProperties":false},"DecideOwnerPayoutBody":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","reject"]},"entryDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["decision"],"additionalProperties":false},"FileDamageClaimBody":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"claimedAmountMinor":{"type":"string","pattern":"^\\d+$"},"description":{"type":"string","minLength":1,"maxLength":1000},"filedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"externalReference":{"type":"string","maxLength":200}},"required":["bookingId","claimedAmountMinor","description"],"additionalProperties":false},"MarkDamageClaimPendingBody":{"type":"object","properties":{"externalReference":{"type":"string","maxLength":200}},"additionalProperties":false},"PayDamageClaimBody":{"type":"object","properties":{"recoveredAmountMinor":{"type":"string","pattern":"^\\d+$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"receivedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["recoveredAmountMinor","financialAccountId"],"additionalProperties":false},"DenyDamageClaimBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":1000},"decidedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["reason"],"additionalProperties":false},"RecordBookingChargeBody":{"type":"object","properties":{"kind":{"type":"string","enum":["cleaning","early_checkin","late_checkout","extra_guest","fine_party","fine_smoking","fine_other","damage_recovery","other"]},"fineKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"collectedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"label":{"type":"string","maxLength":120},"memo":{"type":"string","maxLength":300}},"required":["kind","financialAccountId"],"additionalProperties":false},"DeleteDuplicateBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["reason"],"additionalProperties":false},"VoidBookingChargeBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":300},"entryDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["reason"],"additionalProperties":false},"UpsertHouseRuleFineBody":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"name":{"type":"string","minLength":1,"maxLength":120},"amountMinor":{"type":"string","pattern":"^\\d+$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["key","name","amountMinor"],"additionalProperties":false},"UpsertStaffCompensationBody":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"staffLabel":{"type":"string","maxLength":120},"baseMinor":{"type":"string","pattern":"^\\d+$"},"allowancesMinor":{"type":"string","pattern":"^\\d+$"},"perCleaningMinor":{"type":"string","pattern":"^\\d+$"},"perBookingClosedMinor":{"type":"string","pattern":"^\\d+$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"paidByThirdParty":{"type":"boolean"},"note":{"type":"string","maxLength":300}},"required":["membershipId","baseMinor"],"additionalProperties":false},"UpsertAssetBody":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"subUnitLabel":{"type":"string","maxLength":80},"category":{"type":"string","enum":["lease_security_deposit","advance_rent","furniture_fixtures","appliances_electronics","interior_decor","linen_kitchenware_consumables","general_capex"]},"name":{"type":"string","minLength":1,"maxLength":160},"funderPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"costMinor":{"type":"string","pattern":"^\\d+$"},"acquiredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"condition":{"type":"string","enum":["new","good","fair","poor"]},"usefulLifeMonths":{"type":"integer","exclusiveMinimum":0,"maximum":600},"note":{"type":"string","maxLength":300},"paidFromAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["propertyId","category","name","costMinor","acquiredOn"],"additionalProperties":false},"RecordLeaseOutlayBody":{"type":"object","properties":{"kind":{"type":"string","enum":["deposit","advance_rent"]},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"paidOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["kind","financialAccountId"],"additionalProperties":false},"TerminateLeaseBody":{"type":"object","properties":{"terminatedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"depositRefundMinor":{"type":"string","pattern":"^\\d+$"},"depositWithheldMinor":{"type":"string","pattern":"^\\d+$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["terminatedOn","depositRefundMinor","depositWithheldMinor"],"additionalProperties":false},"CreatePoolModelBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":160},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"unitCount":{"type":"integer","minimum":1,"maximum":10000},"adrMinor":{"type":"string","pattern":"^\\d+$"},"nights":{"type":"integer","minimum":1,"maximum":31},"leaseMinor":{"type":"string","pattern":"^\\d+$"},"opexBp":{"type":"string","pattern":"^\\d+$"},"mgmtShareMilliPct":{"type":"string","pattern":"^\\d+$"},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["name","unitCount","adrMinor","nights","leaseMinor","opexBp","mgmtShareMilliPct","effectiveFrom"],"additionalProperties":false},"UpdatePoolModelBody":{"$ref":"#/components/schemas/CreatePoolModelBody"},"UpsertPoolModelScenarioBody":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_-]{0,39}$"},"label":{"type":"string","minLength":1,"maxLength":120},"occupancyBp":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"adrMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"leaseMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"opexBp":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]}},"required":["key","label"],"additionalProperties":false},"PrefillPoolModelBody":{"type":"object","properties":{"trailingDays":{"type":"integer","minimum":1,"maximum":730}},"additionalProperties":false},"PostMonthEndAccrualsBody":{"type":"object","properties":{"periodMonth":{"type":"string","pattern":"^\\d{4}-\\d{2}-01$"}},"required":["periodMonth"],"additionalProperties":false},"PostDepreciationBody":{"type":"object","properties":{"periodMonth":{"type":"string","pattern":"^\\d{4}-\\d{2}-01$"}},"required":["periodMonth"],"additionalProperties":false},"ClosePeriodBody":{"type":"object","properties":{"periodMonth":{"type":"string","pattern":"^\\d{4}-\\d{2}-01$"},"note":{"type":"string","maxLength":300}},"required":["periodMonth"],"additionalProperties":false},"ReopenPeriodBody":{"type":"object","properties":{"periodMonth":{"type":"string","pattern":"^\\d{4}-\\d{2}-01$"}},"required":["periodMonth"],"additionalProperties":false},"UpsertScheduledPayableBody":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":1,"maxLength":160},"kind":{"type":"string","enum":["rent","salary","utility","software","cam_provision","internet","supplies","other"]},"payeePartyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"categoryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"amountMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"cadence":{"type":"string","enum":["monthly","quarterly","semiannual"]},"dueDay":{"type":"integer","minimum":1,"maximum":28},"route":{"anyOf":[{"type":"string","enum":["bank_transfer","raast","cash_via_staff"]},{"type":"null"}]},"memo":{"type":"string","maxLength":300},"isActive":{"type":"boolean"},"accruesExpense":{"type":"boolean"}},"required":["name","kind","dueDay"],"additionalProperties":false},"SetPayableVerifyBody":{"type":"object","properties":{"verifyStatus":{"type":"string","enum":["verified","needs_verify"]}},"required":["verifyStatus"],"additionalProperties":false},"SettlePayableBody":{"type":"object","properties":{"amountMinor":{"type":"string","pattern":"^\\d+$"},"expenseId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reference":{"type":"string","maxLength":200},"skip":{"type":"boolean"}},"additionalProperties":false},"AccrueDuePayablesBody":{"type":"object","properties":{"asOf":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["asOf"],"additionalProperties":false},"PreparePayRunBody":{"type":"object","properties":{"month":{"type":"string","pattern":"^\\d{4}-\\d{2}$"},"note":{"type":"string","maxLength":500}},"required":["month"],"additionalProperties":false},"ApprovePayRunBody":{"type":"object","properties":{"entryDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"additionalProperties":false},"PayPayRunBody":{"type":"object","properties":{"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"entryDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["financialAccountId"],"additionalProperties":false},"CancelPayRunBody":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500}},"required":["reason"],"additionalProperties":false},"RemitWithholdingBody":{"type":"object","properties":{"amountMinor":{"type":"string","pattern":"^\\d+$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"paidOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"reference":{"type":"string","maxLength":200}},"required":["amountMinor","financialAccountId","paidOn"],"additionalProperties":false},"RecordStaffDeductionBody":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"staffLabel":{"type":"string","minLength":1,"maxLength":120},"kind":{"type":"string","enum":["advance_recovery","loan_recovery","fine","other"]},"label":{"type":"string","minLength":1,"maxLength":200},"amountMinor":{"type":"string","pattern":"^\\d+$"},"perRunMinor":{"type":"string","pattern":"^\\d+$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"paidOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"note":{"type":"string","maxLength":500}},"required":["membershipId","staffLabel","kind","label","amountMinor"],"additionalProperties":false},"UpsertPayrollTaxTableBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"effectiveTo":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"period":{"type":"string","enum":["monthly","annual"]},"bands":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/PayrollTaxBandView"}}},"required":["name","effectiveFrom","bands"],"additionalProperties":false},"PayrollTaxBandView":{"type":"object","properties":{"fromMinor":{"type":"string","pattern":"^\\d+$"},"toMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"rateBp":{"type":"integer","minimum":0,"maximum":10000},"plusFixedMinor":{"type":"string","pattern":"^\\d+$"}},"required":["fromMinor","toMinor","rateBp","plusFixedMinor"],"additionalProperties":false},"RecordFxRateBody":{"type":"object","properties":{"baseCurrency":{"type":"string","pattern":"^[A-Z]{3}$"},"quoteCurrency":{"type":"string","pattern":"^[A-Z]{3}$"},"rate":{"type":"string","pattern":"^\\d{1,9}(\\.\\d{1,8})?$"},"rateDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"source":{"type":"string","maxLength":120}},"required":["baseCurrency","quoteCurrency","rate","rateDate"],"additionalProperties":false},"RevaluateFxBody":{"type":"object","properties":{"month":{"type":"string","pattern":"^\\d{4}-\\d{2}$"}},"required":["month"],"additionalProperties":false},"RecordUnitTransferBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"sellerPartyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"buyerPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"units":{"type":"string","pattern":"^\\d{1,5}(\\.\\d{1,3})?$"},"considerationMinor":{"type":"string","pattern":"^\\d+$"},"route":{"type":"string","enum":["via_company","direct"]},"transferredOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"financialAccountId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"memo":{"type":"string","maxLength":500}},"required":["propertyId","buyerPartyId","units","considerationMinor","route","transferredOn"],"additionalProperties":false},"RequestAgentRequestUploadBody":{"type":"object","properties":{"contentType":{"type":"string","minLength":1,"maxLength":100,"description":"The image/video/PDF MIME type (allow-listed server-side)."},"byteSizeHint":{"description":"Declared byte size — validated against the cap; confirm re-checks.","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"SubmitAgentRequestBody":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"A short name for the automation being asked for."},"body":{"type":"string","minLength":1,"maxLength":5000,"description":"What it should do, in the requester’s words."},"replyEmail":{"description":"An address to reply at (may differ from the seat email).","type":"string","maxLength":320},"pagePath":{"type":"string","minLength":1,"maxLength":200,"description":"The in-app route key."},"pageUrl":{"type":"string","minLength":1,"maxLength":2000,"description":"The full URL as loaded."},"metadata":{"default":{},"description":"The capture envelope (viewport, UA, locale, tz).","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"attachmentKeys":{"default":[],"description":"Keys of files the requester attached (from presigns).","maxItems":6,"type":"array","items":{"type":"string"}}},"required":["title","body","pagePath","pageUrl"],"additionalProperties":false},"RequestFeedbackUploadBody":{"type":"object","properties":{"contentType":{"type":"string","minLength":1,"maxLength":100,"description":"The image/video/PDF MIME type (allow-listed server-side)."},"byteSizeHint":{"description":"Declared byte size — validated against the cap; confirm re-checks.","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"SubmitFeedbackBody":{"type":"object","properties":{"kind":{"type":"string","enum":["bug","improvement"]},"body":{"type":"string","minLength":1,"maxLength":5000,"description":"What went wrong / the suggestion."},"replyEmail":{"description":"An address to reply at (may differ from the seat email).","type":"string","maxLength":320},"pagePath":{"type":"string","minLength":1,"maxLength":200,"description":"The in-app route key."},"pageUrl":{"type":"string","minLength":1,"maxLength":2000,"description":"The full URL as loaded."},"metadata":{"default":{},"description":"The capture envelope (viewport, UA, locale, tz, roles).","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"screenshotKey":{"description":"The auto-captured page image key (from a presign), or null.","type":["string","null"]},"attachmentKeys":{"default":[],"description":"Keys of images the reporter attached (from presigns).","maxItems":6,"type":"array","items":{"type":"string"}}},"required":["kind","body","pagePath","pageUrl"],"additionalProperties":false},"PostSupportMessageBody":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":5000},"attachmentKeys":{"maxItems":6,"type":"array","items":{"type":"string"}}},"required":["body"],"additionalProperties":false},"UpdateGuestAppTenantBody":{"type":"object","properties":{"isEnabled":{"type":"boolean","description":"Master switch. Off 404s the whole guest surface, including every property deep link."},"displayName":{"anyOf":[{"type":"string","minLength":1,"maxLength":120},{"type":"null"}],"description":"Overrides the brand in the header. Null falls back to the site, then workspace."},"welcomeMessage":{"anyOf":[{"type":"string","minLength":1,"maxLength":2000},{"type":"null"}]},"termsAndConditions":{"anyOf":[{"type":"string","minLength":1,"maxLength":20000},{"type":"null"}]},"contactEmail":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}]},"contactPhone":{"anyOf":[{"type":"string","minLength":1,"maxLength":40},{"type":"null"}]},"socialUrls":{"maxItems":8,"type":"array","items":{"type":"string","maxLength":300,"pattern":"^https?:\\/\\/"}}},"required":["isEnabled","displayName","welcomeMessage","termsAndConditions","contactEmail","contactPhone","socialUrls"],"additionalProperties":false,"description":"Whole-object replace, every field."},"EnsureGuestAppConfigBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property to set up (idempotent)."}},"required":["propertyId"],"additionalProperties":false},"UpdateGuestAppConfigBody":{"type":"object","properties":{"isEnabled":{"type":"boolean","description":"Master switch — off 404s the whole public app."},"welcomeMessage":{"anyOf":[{"type":"string","minLength":1,"maxLength":2000},{"type":"null"}]},"wlanNetwork":{"anyOf":[{"type":"string","minLength":1,"maxLength":120},{"type":"null"}]},"wlanPassword":{"anyOf":[{"type":"string","minLength":1,"maxLength":120},{"type":"null"}]},"doorOpeningInfo":{"anyOf":[{"type":"string","minLength":1,"maxLength":5000},{"type":"null"}],"description":"INFORMATIONAL door-opening text only — never a lock code (codes ride the gated relay flow)."},"arrivalInfo":{"anyOf":[{"type":"string","minLength":1,"maxLength":5000},{"type":"null"}]},"checkinEnabled":{"type":"boolean"},"termsAndConditions":{"anyOf":[{"type":"string","minLength":1,"maxLength":20000},{"type":"null"}]},"messagingEnabled":{"type":"boolean"},"socialUrls":{"maxItems":8,"type":"array","items":{"type":"string","maxLength":300,"pattern":"^https?:\\/\\/"}}},"required":["isEnabled","welcomeMessage","wlanNetwork","wlanPassword","doorOpeningInfo","arrivalInfo","checkinEnabled","termsAndConditions","messagingEnabled","socialUrls"],"additionalProperties":false,"description":"Whole-object replace, every field."},"RequestGuestAppLogoUploadBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"contentType":{"type":"string","maxLength":100,"description":"image/png or image/jpeg. Narrower than the document-logo list on purpose: webp and avif cannot be rasterised into an app icon. SVG is refused everywhere — it is script-bearing."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["propertyId","contentType"],"additionalProperties":false},"SetGuestAppLogoBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"objectKey":{"type":"string","maxLength":500},"contentType":{"type":"string","maxLength":100,"description":"image/png or image/jpeg. Narrower than the document-logo list on purpose: webp and avif cannot be rasterised into an app icon. SVG is refused everywhere — it is script-bearing."}},"required":["propertyId","objectKey","contentType"],"additionalProperties":false},"ClearGuestAppLogoBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["propertyId"],"additionalProperties":false},"CreateGuestAppPageBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"section":{"type":"string","enum":["home","info"]},"title":{"type":"string","minLength":1,"maxLength":120},"slug":{"type":"string","minLength":2,"maxLength":64,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"icon":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"body":{"description":"Markdown; rendered guest-side with a safe renderer (never raw HTML).","anyOf":[{"type":"string","maxLength":20000},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":0,"maximum":9999},"isPublished":{"type":"boolean"},"parentPageId":{"description":"Info A–Z nesting: a live, parentless page of the same property+section.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["propertyId","section","title","slug"],"additionalProperties":false},"UpdateGuestAppPageBody":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120},"slug":{"type":"string","minLength":2,"maxLength":64,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"icon":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"body":{"description":"Markdown; rendered guest-side with a safe renderer (never raw HTML).","anyOf":[{"type":"string","maxLength":20000},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":0,"maximum":9999},"isPublished":{"type":"boolean"},"parentPageId":{"description":"Info A–Z nesting: a live, parentless page of the same property+section.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["title","slug"],"additionalProperties":false},"SetUnitWifiBody":{"type":"object","properties":{"wlanNetwork":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"wlanPassword":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]}},"required":["wlanNetwork","wlanPassword"],"additionalProperties":false,"description":"A unit's own Wi-Fi. Both null clears it."},"UpdatePropertyAccessBody":{"type":"object","properties":{"wlanNetwork":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"wlanPassword":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"doorOpeningInfo":{"description":"Informational door text only, never a lock code.","anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"arrivalInfo":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]}},"additionalProperties":false,"description":"Absent = unchanged; null = cleared."},"RotateWifiBody":{"type":"object","properties":{"listingIds":{"maxItems":500,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"propertyIds":{"maxItems":200,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"wlanPassword":{"type":"string","minLength":1,"maxLength":120},"wlanNetwork":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]}},"required":["listingIds","propertyIds","wlanPassword"],"additionalProperties":false},"EnsureSiteBody":{"type":"object","properties":{},"additionalProperties":false},"UpdateSiteBody":{"type":"object","properties":{"slug":{"type":"string","minLength":3,"maxLength":63,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"status":{"type":"string","enum":["draft","published","disabled"]},"name":{"type":"string","minLength":1,"maxLength":200},"tagline":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"introText":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"colorPrimary":{"anyOf":[{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},{"type":"null"}]},"colorAccent":{"anyOf":[{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},{"type":"null"}]},"colorSurface":{"anyOf":[{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},{"type":"null"}]},"colorInk":{"anyOf":[{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},{"type":"null"}]},"fontFamily":{"type":"string","enum":["sans","serif","grotesk","humanist"]},"heroStyle":{"type":"string","enum":["full_bleed","split","minimal"]},"template":{"type":"string","enum":["harbour","atlas","lantern","ledger","quiet"]},"heroPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"contactEmail":{"anyOf":[{"type":"string","maxLength":320,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"null"}]},"contactPhone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}]},"socialUrls":{"maxItems":8,"type":"array","items":{"type":"string","maxLength":300,"pattern":"^https?:\\/\\/"}},"searchWindowDays":{"type":"integer","minimum":1,"maximum":730},"showReviews":{"type":"boolean"}},"required":["slug","status","name","tagline","introText","colorPrimary","colorAccent","colorSurface","colorInk","fontFamily","heroStyle","template","heroPhotoId","contactEmail","contactPhone","socialUrls","searchWindowDays","showReviews"],"additionalProperties":false},"RequestSiteLogoUploadBody":{"type":"object","properties":{"contentType":{"type":"string","maxLength":100,"description":"image/png or image/jpeg. webp and avif cannot be rasterised into an app icon; SVG is refused everywhere (script-bearing)."},"byteSizeHint":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["contentType"],"additionalProperties":false},"SetSiteLogoBody":{"type":"object","properties":{"objectKey":{"type":"string","maxLength":500},"contentType":{"type":"string","maxLength":100,"description":"image/png or image/jpeg. webp and avif cannot be rasterised into an app icon; SVG is refused everywhere (script-bearing)."}},"required":["objectKey","contentType"],"additionalProperties":false},"UpdateSiteTrackingBody":{"type":"object","properties":{"ga4":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"gtm":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"metaPixel":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]}},"required":["ga4","gtm","metaPixel"],"additionalProperties":false},"SetSiteCustomDomainBody":{"type":"object","properties":{"domain":{"type":"string","minLength":4,"maxLength":253,"description":"The tenant’s own domain, e.g. \"urbanelan.com\". Lower-cased and trimmed; a scheme, a port or a path is refused rather than stripped. A subdomain of the platform’s own wildcard is refused — that address already exists."}},"required":["domain"],"additionalProperties":false},"AddSitePropertyBody":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"}},"required":["propertyId"],"additionalProperties":false},"UpdateSitePropertyBody":{"type":"object","properties":{"slug":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"introText":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"heroPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":0,"maximum":9999},"isPublished":{"type":"boolean"},"theSpace":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}]},"neighbourhood":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}]},"gettingAround":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}]},"guestAccess":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}]},"distances":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/PropertyDistance"}}},"required":["slug","introText","heroPhotoId","sortOrder","isPublished"],"additionalProperties":false},"PropertyDistance":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":80},"text":{"type":"string","minLength":1,"maxLength":80}},"required":["label","text"],"additionalProperties":false},"UpsertSiteRoomContentBody":{"type":"object","properties":{"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"displayName":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"tagline":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"body":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}]},"equipment":{"maxItems":40,"type":"array","items":{"type":"string","minLength":1,"maxLength":120}},"sleeping":{"maxItems":20,"type":"array","items":{"$ref":"#/components/schemas/SleepingArrangement"}},"heroPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":0,"maximum":9999},"sellOnline":{"type":"boolean"}},"required":["listingTypeId","displayName","tagline","body","equipment","sleeping","heroPhotoId","sortOrder","sellOnline"],"additionalProperties":false},"SleepingArrangement":{"type":"object","properties":{"room":{"type":"string","minLength":1,"maxLength":80},"beds":{"minItems":1,"maxItems":10,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}}},"required":["room","beds"],"additionalProperties":false},"UpsertSitePromoCodeBody":{"type":"object","properties":{"code":{"type":"string","minLength":2,"maxLength":32,"pattern":"^[A-Za-z0-9][A-Za-z0-9-]{1,31}$"},"label":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"kind":{"type":"string","enum":["percent","fixed"]},"pct":{"anyOf":[{"type":"string","pattern":"^\\d{1,3}(\\.\\d{1,2})?$"},{"type":"null"}]},"amountMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"startsOn":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},{"type":"null"}]},"endsOn":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},{"type":"null"}]},"minNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"minTotalMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"maxRedemptions":{"anyOf":[{"type":"integer","minimum":1,"maximum":1000000},{"type":"null"}]},"isActive":{"type":"boolean"}},"required":["code","label","kind","pct","amountMinor","startsOn","endsOn","minNights","minTotalMinor","maxRedemptions","isActive"],"additionalProperties":false},"CreateSitePageBody":{"type":"object","properties":{"path":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"kind":{"type":"string","enum":["content","legal","contact"]},"title":{"type":"string","minLength":1,"maxLength":200}},"required":["path","kind","title"],"additionalProperties":false},"UpdateSitePageBody":{"type":"object","properties":{"path":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"kind":{"type":"string","enum":["content","legal","contact"]},"title":{"type":"string","minLength":1,"maxLength":200},"seoTitle":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"seoDescription":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}]},"ogPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"showInNav":{"type":"boolean"},"sortOrder":{"type":"integer","minimum":0,"maximum":9999},"isPublished":{"type":"boolean"}},"required":["path","kind","title","seoTitle","seoDescription","ogPhotoId","showInNav","sortOrder","isPublished"],"additionalProperties":false},"CreateSiteCollectionBody":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120},"slug":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"}},"required":["title"],"additionalProperties":false},"UpdateSiteCollectionBody":{"type":"object","properties":{"slug":{"type":"string","minLength":2,"maxLength":63,"pattern":"^[a-z0-9]+(-[a-z0-9]+)*$"},"title":{"type":"string","minLength":1,"maxLength":120},"introText":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"seoDescription":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}]},"heroPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"filter":{},"sortOrder":{"type":"integer","minimum":0,"maximum":1000},"showInNav":{"type":"boolean"},"isPublished":{"type":"boolean"}},"required":["slug","title","introText","seoDescription","heroPhotoId","filter","sortOrder","showInNav","isPublished"],"additionalProperties":false},"CreateSiteBlockBody":{"type":"object","properties":{"pageId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["rich_text","feature_cards","faq","gallery","steps","cta","poi_grid"]},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["pageId","kind","payload"],"additionalProperties":false},"UpdateSiteBlockBody":{"type":"object","properties":{"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"sortOrder":{"type":"integer","minimum":0,"maximum":9999},"isPublished":{"type":"boolean"}},"required":["payload","sortOrder","isPublished"],"additionalProperties":false},"CreateTaxRuleBody":{"type":"object","properties":{"code":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","description":"Stable key — `vat`, `city_tax`. Matches the DB CHECK exactly."},"name":{"type":"string","minLength":1,"maxLength":80},"basis":{"type":"string","enum":["percent_of_base","per_night","per_person_per_night","per_stay"]},"rateBp":{"type":"integer","minimum":0,"maximum":10000},"amountMinor":{"type":"string","pattern":"^\\d+$","description":"Integer MINOR units as a string — never a float."},"currency":{"type":"string","minLength":3,"maxLength":3},"inclusive":{"default":false,"type":"boolean"},"appliesTo":{"default":[],"type":"array","items":{"type":"string","enum":["accommodation","cleaning","fees"]}},"sequence":{"default":10,"type":"integer","minimum":0,"maximum":1000},"compound":{"default":false,"type":"boolean"},"glAccountCode":{"type":"string","enum":["2420","2430"]},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date, YYYY-MM-DD."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["code","name","basis","glAccountCode","effectiveFrom"]},"SupersedeTaxRuleBody":{"type":"object","properties":{"code":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","description":"Stable key — `vat`, `city_tax`. Matches the DB CHECK exactly."},"name":{"type":"string","minLength":1,"maxLength":80},"basis":{"type":"string","enum":["percent_of_base","per_night","per_person_per_night","per_stay"]},"rateBp":{"type":"integer","minimum":0,"maximum":10000},"amountMinor":{"type":"string","pattern":"^\\d+$","description":"Integer MINOR units as a string — never a float."},"currency":{"type":"string","minLength":3,"maxLength":3},"inclusive":{"default":false,"type":"boolean"},"appliesTo":{"default":[],"type":"array","items":{"type":"string","enum":["accommodation","cleaning","fees"]}},"sequence":{"default":10,"type":"integer","minimum":0,"maximum":1000},"compound":{"default":false,"type":"boolean"},"glAccountCode":{"type":"string","enum":["2420","2430"]},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date, YYYY-MM-DD."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"supersedesId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["code","name","basis","glAccountCode","effectiveFrom","supersedesId"]},"RetireTaxRuleBody":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"effectiveTo":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date, YYYY-MM-DD."}},"required":["id","effectiveTo"]},"AssessBookingTaxBody":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"assessedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date, YYYY-MM-DD."}},"required":["bookingId"]},"PostBookingTaxBody":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["bookingId"]},"SetTenantSettingBody":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"value":{"anyOf":[{"type":"string","maxLength":200},{"type":"number"},{"type":"boolean"},{"type":"null"}]}},"required":["key","value"],"additionalProperties":false},"RecordPageViewsBody":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Opaque per-tab correlation key minted by the browser. NOT an identity and never authorized on."},"views":{"maxItems":50,"type":"array","items":{"$ref":"#/components/schemas/PageViewEntry"}},"vitals":{"maxItems":30,"type":"array","items":{"$ref":"#/components/schemas/WebVitalEntry"}}},"required":["sessionId","views"],"additionalProperties":false},"PageViewEntry":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":2000,"description":"The raw in-app pathname as loaded. Resolved SERVER-SIDE to a route template; the raw value is never stored."},"at":{"description":"When the view started, ISO-8601 (client clock; see the use-case for how it is trusted).","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"seq":{"type":"integer","minimum":0,"maximum":100000,"description":"The view's ordinal within its session — the sequence tie-break."},"dwellMs":{"description":"Foreground time in ms, when the browser managed to report it.","type":"integer","minimum":0,"maximum":86400000}},"required":["path","at","seq"],"additionalProperties":false},"WebVitalEntry":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":2000,"description":"The raw pathname it was measured on; resolved server-side to a route template."},"name":{"type":"string","enum":["CLS","FCP","INP","LCP","TTFB"]},"value":{"type":"number","minimum":0,"maximum":600000,"description":"Milliseconds, or the unitless layout-shift score for CLS."}},"required":["path","name","value"],"additionalProperties":false},"AcceptTermsBody":{"type":"object","properties":{"documents":{"minItems":1,"maxItems":2,"type":"array","items":{"type":"string","enum":["customer_terms","workspace_user_terms"]}}},"required":["documents"],"additionalProperties":false},"SetContentTranslationBody":{"type":"object","properties":{"entityType":{"type":"string","enum":["tenant_site","tenant_site_property","property","listing_type","site_room_content","site_page","site_block","site_collection","guest_app_config","guest_app_page"]},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"field":{"type":"string","minLength":1,"maxLength":40},"locale":{"type":"string","enum":["ar","de","es","fr","it","pt","ru","tr","ur","zh"]},"text":{"type":"string","minLength":1,"maxLength":20000}},"required":["entityType","entityId","field","locale","text"],"additionalProperties":false},"CreateApiKeyBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"scopes":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","pattern":"^[a-z_]+:[a-z_0-9]+$"}},"expiresInDays":{"anyOf":[{"type":"integer","minimum":1,"maximum":730},{"type":"null"}]}},"required":["name","scopes","expiresInDays"],"additionalProperties":false},"WebhookEndpointBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"url":{"type":"string","minLength":9,"maxLength":2000},"eventTypes":{"minItems":1,"maxItems":400,"type":"array","items":{"type":"string","pattern":"^[a-z_]+(\\.[a-z_]+)+$"}},"omitPersonal":{"type":"boolean"},"active":{"type":"boolean"}},"required":["name","url","eventTypes","omitPersonal","active"],"additionalProperties":false},"SetAccountMappingsBody":{"type":"object","properties":{"target":{"type":"string","enum":["xero","quickbooks"]},"mappings":{"maxItems":500,"type":"array","items":{"type":"object","properties":{"accountCode":{"type":"string","pattern":"^\\d{4}$"},"externalCode":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]},"taxRate":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}]}},"required":["accountCode","externalCode","taxRate"],"additionalProperties":false}}},"required":["target","mappings"],"additionalProperties":false},"CreateAccountingExportBody":{"type":"object","properties":{"target":{"type":"string","enum":["xero","quickbooks"]},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The day after the last day of the period."},"dateFormat":{"type":"string","enum":["dmy","mdy","ymd"]},"defaultTaxRate":{"type":"string","minLength":1,"maxLength":100}},"required":["target","from","to","dateFormat","defaultTaxRate"],"additionalProperties":false},"PushSubscribeBody":{"type":"object","properties":{"endpoint":{"type":"string","maxLength":2000,"format":"uri"},"p256dh":{"type":"string","minLength":80,"maxLength":100},"auth":{"type":"string","minLength":16,"maxLength":32},"deviceLabel":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"categories":{"maxItems":6,"type":"array","items":{"type":"string","enum":["bookings","guests","housekeeping","finance","channels","system"]}}},"required":["endpoint","p256dh","auth","deviceLabel","categories"],"additionalProperties":false},"PushDeviceUpdateBody":{"type":"object","properties":{"deviceLabel":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"categories":{"maxItems":6,"type":"array","items":{"type":"string","enum":["bookings","guests","housekeeping","finance","channels","system"]}}},"required":["deviceLabel","categories"],"additionalProperties":false},"AgentRuleList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentRule"}}},"required":["items"],"additionalProperties":false},"AgentRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string"},"title":{"type":["string","null"]},"triggerKey":{"anyOf":[{"type":"string","enum":["booking-confirmed","before-check-in","during-stay","before-check-out","after-check-out"]},{"type":"null"}]},"audience":{"anyOf":[{"type":"string","enum":["guest","fixed-recipients"]},{"type":"null"}]},"messages":{"type":"array","items":{"$ref":"#/components/schemas/AgentRuleMessage"},"description":"The messages hanging off a tenant-authored automation, in timeline order. Always empty for a built-in kind, whose single body is code."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"NULL ⇒ this rule is the workspace default for its kind (every property)."},"propertyName":{"type":["string","null"]},"propertyArchived":{"description":"F-34 — true when this override targets a property that has since been archived (the rule is not auto-disabled or removed; existing bookings on that property still process normally). NULL for the workspace-default row, where the question does not apply.","type":["boolean","null"]},"enabled":{"type":"boolean"},"channels":{"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}},"sendAtLocal":{"description":"Local civil time HH:MM for a scheduled rule. Civil rather than an instant so '08:00 daily' stays 08:00 across a DST shift.","type":["string","null"]},"leadMinutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Minutes before check-in for a pre-arrival rule (the door code: 30)."},"recipients":{"type":"array","items":{"type":"string"},"description":"Extra fixed addresses for the reception digests — a front desk inbox that is not a seat. Seats are resolved live from membership."},"variants":{"anyOf":[{"type":"array","items":{"type":"string","enum":["minimal","detailed"]}},{"type":"null"}],"description":"Which renderings of the daily ops report to email (0242). NULL ⇒ both, which is what every rule written before this field existed means. Applies to the EMAIL leg only: the WhatsApp leg is always the minimal summary, because a Meta UTILITY template cannot carry the detailed body."},"conditions":{"description":"Which bookings this rule actually fires for. An empty object filters nothing, which is what every rule written before 0305 means.","$ref":"#/components/schemas/AgentConditions"}},"required":["id","kind","title","triggerKey","audience","messages","propertyId","propertyName","propertyArchived","enabled","channels","sendAtLocal","leadMinutes","recipients","variants","conditions"],"additionalProperties":false},"AgentRuleMessage":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offsetMinutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Minutes from the rule's trigger anchor. Always >= 0 — the DIRECTION is the trigger's ('before check-in' vs 'after check-out'), never the message's."},"templateId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"templateName":{"type":"string"},"body":{"type":"string"},"channels":{"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}},"enabled":{"type":"boolean"},"conditions":{"$ref":"#/components/schemas/AgentConditions"}},"required":["id","position","offsetMinutes","templateId","templateName","body","channels","enabled","conditions"],"additionalProperties":false},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"A stable machine token (not_found | validation_failed | property_code_conflict | listing_type_key_conflict | listing_code_conflict | already_archived | property_has_live_listings | listing_type_has_listings | listing_has_bookings | unauthenticated | internal_error).","example":"not_found"},"message":{"type":"string","description":"A generic, non-leaking human-readable message."},"detail":{"description":"The specific machine token when `code` is a category (e.g. `validation_failed`) — the same stable, PII-free token already present in `message`, surfaced as its own field so a caller can map it to precise copy without parsing the message. Absent for the fixed 404/500 bodies.","example":"period_closed","type":"string"}},"required":["code","message"],"additionalProperties":false,"description":"The error detail."}},"required":["error"],"additionalProperties":false,"description":"The consistent error body for every 4xx/5xx."},"AgentRuleUpserted":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["ids"],"additionalProperties":false},"AgentAuthoringCatalog":{"type":"object","properties":{"triggers":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["booking-confirmed","before-check-in","during-stay","before-check-out","after-check-out"]},"label":{"type":"string"},"timelineOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"anchor":{"type":"string","enum":["confirmation","check-in","check-out"]},"offset":{"type":"string","enum":["before","after"]},"offsetLabel":{"type":"string"},"audiences":{"type":"array","items":{"type":"string","enum":["guest","fixed-recipients"]}},"channels":{"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}}},"required":["key","label","timelineOrder","anchor","offset","offsetLabel","audiences","channels"],"additionalProperties":false}},"audiences":{"type":"array","items":{"type":"object","properties":{"audience":{"type":"string","enum":["guest","fixed-recipients"]},"label":{"type":"string"},"description":{"type":"string"},"usesRecipients":{"type":"boolean"}},"required":["audience","label","description","usesRecipients"],"additionalProperties":false}},"packs":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"requires":{"type":"array","items":{"type":"string"}},"messageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"rules":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"triggerKey":{"type":"string","enum":["booking-confirmed","before-check-in","during-stay","before-check-out","after-check-out"]},"audience":{"type":"string","enum":["guest","fixed-recipients"]},"messages":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"offsetMinutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"body":{"type":"string"},"channels":{"type":"array","items":{"type":"string","enum":["email","whatsapp","sms","inapp"]}}},"required":["name","offsetMinutes","body","channels"],"additionalProperties":false}}},"required":["title","triggerKey","audience","messages"],"additionalProperties":false}}},"required":["key","name","description","requires","messageCount","rules"],"additionalProperties":false}},"maxOffsetMinutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["triggers","audiences","packs","maxOffsetMinutes"],"additionalProperties":false},"AgentAuthoredRuleCreated":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string"}},"required":["id","kind"],"additionalProperties":false},"AgentAuthoredRuleId":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"AgentStarterPackInstalled":{"type":"object","properties":{"ruleIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["ruleIds"],"additionalProperties":false},"AgentRunList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentRun"}}},"required":["items"],"additionalProperties":false},"AgentRun":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"ruleId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string"},"firedAt":{"type":"string"},"status":{"type":"string","enum":["delivered","partial","skipped","held","failed","sending"],"description":"'held' is not a failure: the door-code rule declines when the dual gate (payment ✓ ∧ ID ✓) is not clear, re-evaluates next tick, and surfaces the reason on /today. 'sending' is the claim committed before a send and marked after it; a worker that stopped mid-send leaves one that the next tick releases after 15 minutes."},"summary":{"type":"string"},"targetLabel":{"type":["string","null"]},"error":{"type":["string","null"]},"resendable":{"type":"boolean","description":"Offered a Resend: a delivered run about one booking, not the door code or a digest, whose rule is still on."}},"required":["id","ruleId","kind","firedAt","status","summary","targetLabel","error","resendable"],"additionalProperties":false},"AgentRunResend":{"type":"object","properties":{"resendId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["resendId"],"additionalProperties":false},"AuthoredRuleTestSend":{"type":"object","properties":{"testId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"to":{"type":"string","description":"The requesting operator's own email address."}},"required":["testId","to"],"additionalProperties":false},"ApprovalTaskList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ApprovalTask"}}},"required":["items"],"additionalProperties":false},"ApprovalTask":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","description":"The gated flow, e.g. 'quote_share.release'."},"subjectType":{"type":"string"},"subjectId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["pending","approved","rejected","cancelled"]},"requestedAt":{"type":"string"},"requestedByMembershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The MAKER seat. A seat id rather than a name: person names live on the global platform_user table, which the tenant-plane app role holds no grant on (ADR B)."},"requestNote":{"type":["string","null"]},"decidedAt":{"type":["string","null"]},"decidedByMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"decisionNote":{"type":["string","null"]},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Kind-specific context for the queue UI. Never a credential — see migration 0228."},"decidableByViewer":{"type":"boolean","description":"True ⇔ the asking seat may decide this task (pending, and the seat is an active member — since 2026-08-16 the requester may decide their own). Computed server-side so the UI never re-derives the rule."}},"required":["id","kind","subjectType","subjectId","status","requestedAt","requestedByMembershipId","requestNote","decidedAt","decidedByMembershipId","decisionNote","payload","decidableByViewer"],"additionalProperties":false},"ApprovalDecision":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["pending","approved","rejected","cancelled"]}},"required":["id","status"],"additionalProperties":false},"ApprovalPolicy":{"type":"object","properties":{"quoteShareApprovalRequired":{"type":"boolean","description":"True ⇔ creating a quotation link parks an approval task that must be released before the link goes live. Default false."},"activeSeatCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Active seats in the workspace — surfaced so the settings page can say what turning the gate on means for a solo workspace (single-approver: the requester may release their own, given approval:decide)."}},"required":["quoteShareApprovalRequired","activeSeatCount"],"additionalProperties":false},"NotificationListResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/NotificationView"}},"unreadCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The BADGE count under the effective config — not items.length."},"nextCursor":{"type":["string","null"]}},"required":["items","unreadCount","nextCursor"],"additionalProperties":false},"NotificationView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","description":"The catalog key (the domain event type). Not user-shown."},"category":{"type":"string","enum":["bookings","guests","housekeeping","finance","channels","system"]},"severity":{"type":"string","enum":["critical","action","info"]},"title":{"type":"string"},"body":{"type":["string","null"]},"href":{"type":"string","description":"Server-composed same-origin app path."},"entityType":{"type":"string"},"entityId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"occurredAt":{"type":"string","description":"When the EVENT happened — not when the row was written."},"readAt":{"type":["string","null"]}},"required":["id","kind","category","severity","title","body","href","entityType","entityId","occurredAt","readAt"],"additionalProperties":false},"AskDocsResponse":{"type":"object","properties":{"answer":{"type":"string","description":"The grounded answer, or a statement that the docs do not cover it."},"citations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The help-centre page path."},"title":{"type":"string"},"url":{"type":"string","description":"The public docs.staynhost.com URL."}},"required":["id","title","url"],"additionalProperties":false},"description":"Pages the answer rests on. Always a subset of what was retrieved."},"declined":{"type":"boolean","description":"True when the help centre does not cover the question."},"screen":{"description":"The app route the cited page documents, when it has one.","type":["string","null"]}},"required":["answer","citations","declined","screen"],"additionalProperties":false},"UnreadCountResponse":{"type":"object","properties":{"unreadCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["unreadCount"],"additionalProperties":false},"MarkNotificationReadResponse":{"type":"object","properties":{"marked":{"type":"boolean"}},"required":["marked"],"additionalProperties":false},"MarkAllNotificationsReadResponse":{"type":"object","properties":{"marked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["marked"],"additionalProperties":false},"NotificationPreferencesResponse":{"type":"object","properties":{"effective":{"type":"object","properties":{"activeSeverities":{"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"badgeSeverities":{"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"mutedKinds":{"type":"array","items":{"type":"string","maxLength":100}}},"required":["activeSeverities","badgeSeverities","mutedKinds"],"additionalProperties":false},"seat":{"anyOf":[{"type":"object","properties":{"activeSeverities":{"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"badgeSeverities":{"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"mutedKinds":{"type":"array","items":{"type":"string","maxLength":100}}},"required":["activeSeverities","badgeSeverities","mutedKinds"],"additionalProperties":false},{"type":"null"}],"description":"The seat's own override, or null if inherited."},"workspace":{"anyOf":[{"type":"object","properties":{"activeSeverities":{"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"badgeSeverities":{"type":"array","items":{"type":"string","enum":["critical","action","info"]}},"mutedKinds":{"type":"array","items":{"type":"string","maxLength":100}}},"required":["activeSeverities","badgeSeverities","mutedKinds"],"additionalProperties":false},{"type":"null"}],"description":"The workspace default, or null."},"canConfigureWorkspace":{"type":"boolean","description":"Whether this seat holds notification:configure."}},"required":["effective","seat","workspace","canConfigureWorkspace"],"additionalProperties":false},"SetNotificationPreferenceResponse":{"type":"object","properties":{"saved":{"type":"boolean","const":true},"scope":{"type":"string","enum":["seat","tenant"]}},"required":["saved","scope"],"additionalProperties":false},"ListPropertiesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyView"},"description":"The page of properties."},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The cursor for the next page, or null at the end of the list."}},"required":["items","nextCursor"],"additionalProperties":false},"PropertyView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"tenantId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The owning tenant id (response-only)."},"name":{"type":"string","description":"The property name."},"code":{"type":"string","description":"The tenant-unique property code (editable post-create)."},"checkInTime":{"description":"Check-in time (HH:MM) or null.","type":["string","null"]},"checkOutTime":{"description":"Check-out time (HH:MM) or null.","type":["string","null"]},"propertyType":{"type":"string","description":"The property display type.","example":"apartment"},"channelSyncMode":{"type":"string","description":"C2 — 'unit' (per listing) or 'pool' (room classes)."},"location":{"description":"The structured location (all fields optional).","$ref":"#/components/schemas/PropertyLocationView"},"parentPropertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The display/org hierarchy parent, or null for a root."},"managerMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The informational manager membership id, or null when unassigned."},"reception":{"description":"The structured reception contact (all fields optional).","$ref":"#/components/schemas/PropertyReceptionView"},"tags":{"type":"array","items":{"$ref":"#/components/schemas/PropertyTagView"},"description":"The property's tags (descriptive pills)."},"childPropertyCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Direct-children count (a real derived query).","example":24},"descendantListingCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Listings across the whole subtree (a real recursive query).","example":203},"leadPhotoUrl":{"description":"The property's lead photo as a short-lived presigned GET url (the gallery-card hero image); absent when the property has no ready lead photo (the card falls back to a monogram placeholder). Response-only — a client can never set it.","example":"https://bucket.s3.amazonaws.com/t/…/p/…/lead.jpg?X-Amz-Signature=…","type":"string","format":"uri"},"archived":{"type":"boolean","description":"True when the property is soft-deleted."}},"required":["id","tenantId","name","code","checkInTime","checkOutTime","propertyType","channelSyncMode","location","parentPropertyId","managerMembershipId","reception","tags","childPropertyCount","descendantListingCount","archived"],"additionalProperties":false,"description":"A property as returned to a client."},"PropertyLocationView":{"type":"object","properties":{"addressLine":{"description":"Freeform street line (display only).","type":"string"},"city":{"description":"City tier.","example":"Kreuzberg","type":"string"},"region":{"description":"State/province/region.","example":"Berlin","type":"string"},"area":{"description":"District within the city.","example":"Clifton","type":"string"},"countryCode":{"description":"ISO-3166-1 alpha-2 country code.","example":"DE","type":"string"},"latitude":{"description":"WGS84 latitude.","example":52.520008,"type":"number"},"longitude":{"description":"WGS84 longitude.","example":13.404954,"type":"number"}},"additionalProperties":false,"description":"The structured location of a property."},"PropertyReceptionView":{"type":"object","properties":{"email":{"description":"Reception email.","example":"front@x.com","type":"string"},"phone":{"description":"Reception phone (normalized).","example":"+923001234567","type":"string"},"whatsapp":{"description":"Reception WhatsApp (normalized).","example":"+923009999999","type":"string"}},"additionalProperties":false,"description":"The structured reception contact of a property."},"PropertyTagView":{"type":"object","properties":{"slug":{"type":"string","description":"The normalized tag key.","example":"sea-view"},"label":{"type":"string","description":"The display label.","example":"Sea view"},"kind":{"type":"string","enum":["tag","amenity"],"description":"A descriptive tag or a filterable amenity."}},"required":["slug","label","kind"],"additionalProperties":false},"AssignableManagersResponse":{"type":"object","properties":{"managers":{"type":"array","items":{"$ref":"#/components/schemas/AssignableManagerView"},"description":"The tenant's active memberships."}},"required":["managers"],"additionalProperties":false},"AssignableManagerView":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The membership id (the manager assignment value)."},"displayName":{"type":"string","description":"The member display name.","example":"Ayesha Khan"},"email":{"type":"string","description":"The member email.","example":"ayesha@tenant.test"}},"required":["membershipId","displayName","email"],"additionalProperties":false},"QuickAddPropertyResult":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyCode":{"type":"string"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}},"required":["propertyId","propertyCode","listingTypeId","listingIds"],"additionalProperties":false,"description":"The ids the quick add created."},"DeleteResult":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The id of the permanently deleted row.","example":"11111111-1111-4111-8111-111111111111"}},"required":["id"],"additionalProperties":false,"description":"The id of a permanently deleted row."},"ListPropertyPhotosResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyPhotoListItem"}}},"required":["items"],"additionalProperties":false},"PropertyPhotoListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"altText":{"type":["string","null"]},"url":{"description":"The short-lived presigned GET url for the THUMB derivative (minted from the opaque key), or null when no derivative exists yet — the client renders a placeholder rather than the full-size original.","type":["string","null"]},"contentType":{"type":"string","description":"The stored MIME type. The gallery holds VIDEO as well as stills (0246) and neither the opaque key nor the presigned url reveals which — a client that guesses renders every video as a broken image."}},"required":["id","position","altText","url","contentType"],"additionalProperties":false},"RequestPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The server-minted photo id."},"uploadUrl":{"type":"string","description":"The short-lived presigned PUT URL (browser → S3 direct)."},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"},"description":"The headers the browser MUST send on the PUT (the pinned content-type)."}},"required":["photoId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["photoId","uploadStatus","byteSize"],"additionalProperties":false},"WhatsAppConnectionView":{"type":"object","properties":{"configured":{"type":"boolean"},"phoneNumberId":{"type":["string","null"]},"wabaId":{"type":["string","null"]},"displayPhone":{"type":["string","null"]},"dailyTemplate":{"type":["string","null"]},"templateLang":{"type":["string","null"]},"guestTemplate":{"type":["string","null"]},"isActive":{"type":"boolean"},"accessTokenMasked":{"type":"string"},"appSecretMasked":{"type":"string"},"webhookVerifyTokenMasked":{"type":"string"},"webhookPath":{"description":"The per-connection webhook URL to paste into Meta; null until configured.","type":["string","null"]}},"required":["configured","phoneNumberId","wabaId","displayPhone","dailyTemplate","templateLang","guestTemplate","isActive","accessTokenMasked","appSecretMasked","webhookVerifyTokenMasked","webhookPath"],"additionalProperties":false},"PropertyContentView":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"description":{"description":"Guest-facing description or null.","type":["string","null"]},"importantInformation":{"description":"Important information or null.","type":["string","null"]},"paymentInstructions":{"description":"This property’s bank details for quotations, or null (use workspace).","type":["string","null"]},"logoPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The gallery photo currently elected as the logo, or null (also null when the elected photo was since removed)."},"petsPolicy":{"anyOf":[{"type":"string","enum":["allowed","by_arrangements","not_allowed"]},{"type":"null"}],"description":"Pets policy or null."},"smokingPolicy":{"anyOf":[{"type":"string","enum":["no_smoking","smoking_allowed","designated_areas"]},{"type":"null"}],"description":"Smoking policy or null."},"parkingType":{"anyOf":[{"type":"string","enum":["on_site","nearby","none"]},{"type":"null"}],"description":"Parking type or null."},"wifiCoverage":{"anyOf":[{"type":"string","enum":["entire_property","public_areas","none"]},{"type":"null"}],"description":"Wi-Fi coverage or null."}},"required":["propertyId","description","importantInformation","paymentInstructions","logoPhotoId","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false,"description":"A property's content & policies facet."},"ListingContentView":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id."},"description":{"description":"Guest-facing description or null.","type":["string","null"]}},"required":["listingId","description"],"additionalProperties":false,"description":"A listing's content facet."},"PropertyRefundPolicyView":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"policyHeading":{"type":"string","description":"The heading printed above the refund bullets on this property’s quotations."},"policyNotes":{"description":"Free-text addendum printed under the bullets, or null.","type":["string","null"]},"refundTiers":{"type":"array","items":{"$ref":"#/components/schemas/RefundTier"},"description":"The ladder, longest lead time first. Never empty — a property with no rows of its own projects the product default ladder."}},"required":["propertyId","policyHeading","policyNotes","refundTiers"],"additionalProperties":false,"description":"A property's cancellation & refund policy as printed on its quotations."},"PropertyQuotationView":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property id."},"termsText":{"description":"Terms & conditions, one bullet per line, or null.","type":["string","null"]},"footerText":{"description":"The sign-off block, one line per line, or null (a generated thanks).","type":["string","null"]}},"required":["propertyId","termsText","footerText"],"additionalProperties":false,"description":"A property's quotation boilerplate (terms & footer)."},"CleaningRulesView":{"type":"object","properties":{"propertyId":{"type":"string"},"stayoverCleanEveryDays":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"stayoverMinNights":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deepCleanEveryTurnovers":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["propertyId","stayoverCleanEveryDays","stayoverMinNights","deepCleanEveryTurnovers"],"additionalProperties":false,"description":"A property's cleaning rules (0441)."},"ListListingTypesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ListingTypeView"},"description":"The page of listing_types."},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The cursor for the next page, or null at the end of the list."}},"required":["items","nextCursor"],"additionalProperties":false},"ListingTypeView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing_type id."},"tenantId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The owning tenant id (response-only)."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The owning property, or null for a legacy tenant-wide type."},"key":{"type":"string","description":"The immutable listing-type key.","example":"1BED"},"name":{"type":"string","description":"The listing-type name.","example":"One Bedroom"},"defaultSqft":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}],"description":"The default square-footage, or null when unset.","example":550},"attributes":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"description":"The attribute label (e.g. \"Type\", \"View\").","example":"View"},"value":{"type":"string","minLength":1,"description":"The attribute value (e.g. \"Sea\").","example":"Sea"}},"required":["label","value"],"additionalProperties":false}},{"type":"null"}],"description":"The ordered {label,value} attribute rows, or null when none."},"archived":{"type":"boolean","description":"True when the listing_type is soft-deleted."}},"required":["id","tenantId","propertyId","key","name","defaultSqft","attributes","archived"],"additionalProperties":false,"description":"A listing_type as returned to a client."},"ListListingsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ListingView"},"description":"The page of listings."},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The cursor for the next page, or null at the end of the list."}},"required":["items","nextCursor"],"additionalProperties":false},"ListingView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing id."},"tenantId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The owning tenant id (response-only)."},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The parent property id."},"listingCode":{"type":"string","description":"The property-unique listing code (editable post-create).","example":"628"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing type id."},"lockMode":{"type":"string","description":"The lock mode.","example":"static"},"readinessStatus":{"type":"string","description":"The derived, system-managed readiness state.","example":"vacant"},"isActive":{"type":"boolean","description":"True when the listing is active."},"checkInTime":{"description":"The listing's own check-in override (HH:MM) or null.","type":["string","null"]},"checkOutTime":{"description":"The listing's own check-out override (HH:MM) or null.","type":["string","null"]},"effectiveCheckInTime":{"type":"string","description":"The resolved effective check-in (listing ?? property ?? tenant ?? 14:00).","example":"14:00"},"effectiveCheckOutTime":{"type":"string","description":"The resolved effective check-out (listing ?? property ?? tenant ?? 12:00).","example":"12:00"},"archived":{"type":"boolean","description":"True when the listing is soft-deleted."},"parentListingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The containing (parent) listing id, or null if this is a root."},"childOccupancyPolicy":{"type":"string","description":"How this listing's own children interact ('coexist' | 'exclusive')."},"bedrooms":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Number of bedrooms.","example":2},"beds":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Number of beds.","example":3},"bathrooms":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Number of bathrooms.","example":1},"sizeValue":{"description":"Unit size magnitude in `sizeUnit`, or null.","example":90,"type":["number","null"]},"sizeUnit":{"description":"Unit-size measurement system (`sqm`|`sqft`), or null.","example":"sqm","type":["string","null"]},"amenities":{"type":"array","items":{"type":"string"},"description":"The canonical amenity keys offered.","example":["wifi","kitchen"]},"leadPhotoUrl":{"description":"The lead photo's short-lived presigned GET url (gallery card + table thumbnail); absent when no ready lead photo.","type":"string"},"propertyName":{"description":"The parent property's name (list responses only, archived parents included).","type":"string"},"listingTypeName":{"description":"The listing type's name (list responses only).","type":"string"}},"required":["id","tenantId","propertyId","listingCode","listingTypeId","lockMode","readinessStatus","isActive","checkInTime","checkOutTime","effectiveCheckInTime","effectiveCheckOutTime","archived","parentListingId","childOccupancyPolicy","bedrooms","beds","bathrooms","sizeValue","sizeUnit","amenities"],"additionalProperties":false,"description":"A listing as returned to a client."},"ListingAvailabilityResponse":{"type":"object","properties":{"nights":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"The number of nights in the requested window.","example":3},"availability":{"type":"array","items":{"$ref":"#/components/schemas/ListingTypeAvailabilityView"},"description":"The per-listing-type free-counts."}},"required":["nights","availability"],"additionalProperties":false},"ListingTypeAvailabilityView":{"type":"object","properties":{"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing type id."},"freeCount":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Listings of this type free for the whole night-set.","example":3},"freeListingIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"The ids of those free listings, the set a caller may offer as an optional unit pin. Exactly `freeCount` long; ordered by listing code."}},"required":["listingTypeId","freeCount","freeListingIds"],"additionalProperties":false},"ListingOccupancyView":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"occAdults":{"anyOf":[{"type":"integer","minimum":0,"maximum":20},{"type":"null"}]},"occChildren":{"anyOf":[{"type":"integer","minimum":0,"maximum":20},{"type":"null"}]},"occInfants":{"anyOf":[{"type":"integer","minimum":0,"maximum":20},{"type":"null"}]},"defaultOccupancy":{"anyOf":[{"type":"integer","minimum":0,"maximum":20},{"type":"null"}]},"typeOccAdults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"typeOccChildren":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"typeOccInfants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"typeDefaultOccupancy":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"resolvedOccAdults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"resolvedOccChildren":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"resolvedOccInfants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"resolvedDefaultOccupancy":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["listingId","occAdults","occChildren","occInfants","defaultOccupancy","typeOccAdults","typeOccChildren","typeOccInfants","typeDefaultOccupancy","resolvedOccAdults","resolvedOccChildren","resolvedOccInfants","resolvedDefaultOccupancy"],"additionalProperties":false},"RotateIcalTokenResponse":{"type":"object","properties":{"icalPath":{"type":"string","description":"The new origin-relative iCal feed path. The previous URL is invalid from this moment."}},"required":["icalPath"],"additionalProperties":false},"ListListingPhotosResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ListingPhotoListItem"}}},"required":["items"],"additionalProperties":false},"ListingPhotoListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"altText":{"type":["string","null"]},"url":{"description":"The short-lived presigned GET url (minted from the opaque key), or null when there is no derivative to serve yet — a thumbnail serves a derivative or nothing, never the raw original (#1669).","type":["string","null"]},"contentType":{"type":"string","description":"The stored MIME type. The gallery holds VIDEO as well as stills (0246) and neither the opaque key nor the presigned url reveals which — a client that guesses renders every video as a broken image."},"categoryKey":{"description":"The gallery bucket this photo sits in; null = uncategorized. The client groups on the KEY, never on the label — a label is display text an operator can retype, and grouping on it would split one bucket in two the moment somebody fixed a capital letter.","type":["string","null"]}},"required":["id","position","altText","url","contentType","categoryKey"],"additionalProperties":false},"RequestListingPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The server-minted photo id."},"uploadUrl":{"type":"string","description":"The short-lived presigned PUT URL (browser → S3 direct)."},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"},"description":"The headers the browser MUST send on the PUT (the pinned content-type)."}},"required":["photoId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmListingPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["photoId","uploadStatus","byteSize"],"additionalProperties":false},"BackfillPhotoDerivativesResponse":{"type":"object","properties":{"derived":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Photos this call derived at least one size for."},"failed":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Photos this call could not derive — a video, an unreadable object, or an encoder refusal. They stay original-only and remain counted in `remaining`."},"remaining":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Photos still carrying no derivatives. `0` means the library is fully derived."},"failures":{"type":"array","items":{"type":"object","properties":{"photoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"vertical":{"type":"string","enum":["listing","listing_type","property"]},"ownerId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"contentType":{"type":"string"},"stage":{"type":"string","enum":["unsupported-media","read","encode","write","replace","record"]},"size":{"type":"string","enum":["thumb","card","full"]},"message":{"type":"string"},"detectedFormat":{"type":"string"}},"required":["photoId","vertical","ownerId","contentType","stage","message"],"additionalProperties":false},"description":"Why the photos in `failed` failed, truncated to the first few. `stage` is the diagnosis: `encode` is the picture itself, `write` is the derivative bucket, `read` is the stored object, `record` is the bookkeeping write, `unsupported-media` is a video and is correct. `vertical` + `ownerId` say where to find the photo; on an `encode` failure `detectedFormat` reads the real format from the bytes, which is the only thing that can contradict the browser-supplied `contentType`."}},"required":["derived","failed","remaining","failures"],"additionalProperties":false},"ReconcilePhotoDerivativesResponse":{"type":"object","properties":{"checked":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Photos examined by this call."},"verified":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Photos whose every recorded size was really present — untouched."},"corrected":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Photos whose record was narrowed because it named objects that are not in the store. The backfill re-derives them on its next run."},"missingObjects":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Recorded sizes found absent across this batch — the number of image URLs that were resolving to nothing."},"undetermined":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Recorded sizes this call could not decide about — the store or the probe answered neither present nor absent, so the record was left standing. A run with a large value here has proved nothing."},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"Pass back as `cursor` to continue. `null` means the library has been swept end to end."}},"required":["checked","verified","corrected","missingObjects","undetermined","nextCursor"],"additionalProperties":false},"ListListingPhotoCategoriesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ListingPhotoCategoryListItem"}}},"required":["items"],"additionalProperties":false},"ListingPhotoCategoryListItem":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$","description":"A gallery bucket key — a built-in (`living_room`) or one of the tenant's registered custom keys.","example":"main_hero_shots"},"label":{"type":"string","description":"The section heading the operator typed."},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Display order among the tenant's own buckets."}},"required":["key","label","position"],"additionalProperties":false},"ListListingTypePhotosResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ListingTypePhotoListItem"}}},"required":["items"],"additionalProperties":false},"ListingTypePhotoListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"altText":{"type":["string","null"]},"url":{"type":"string","description":"The short-lived presigned GET url (minted from the opaque key)."},"contentType":{"type":"string","description":"The stored MIME type. The gallery holds VIDEO as well as stills (0246) and neither the opaque key nor the presigned url reveals which — a client that guesses renders every video as a broken image."},"categoryKey":{"description":"The gallery bucket this photo sits in; null = uncategorized. Grouped on the KEY, never the label — a label is display text an operator can retype.","type":["string","null"]}},"required":["id","position","altText","url","contentType","categoryKey"],"additionalProperties":false},"RequestListingTypePhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The server-minted photo id."},"uploadUrl":{"type":"string","description":"The short-lived presigned PUT URL (browser → S3 direct)."},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"},"description":"The headers the browser MUST send on the PUT (the pinned content-type)."}},"required":["photoId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmListingTypePhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["photoId","uploadStatus","byteSize"],"additionalProperties":false},"PushListingTypePhotosResponse":{"type":"object","properties":{"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"photoCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many photos each unit now holds."},"listingCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many units were written. 0 is a success — the type has no units."}},"required":["listingTypeId","photoCount","listingCount"],"additionalProperties":false},"ListListingChannelLinksResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ListingChannelLinkListItem"}}},"required":["items"],"additionalProperties":false},"ListingChannelLinkListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channel":{"type":"string","enum":["airbnb","booking_com","vrbo","expedia","agoda","tripadvisor","google","direct","other"]},"url":{"type":"string"},"label":{"type":["string","null"]},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","channel","url","label","position"],"additionalProperties":false},"ListInquiriesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InquiryView"}},"serverNow":{"type":"string","description":"Server wall-clock at read time (ISO-8601) — the countdown skew anchor."},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The cursor for the next page, or null at the end of the list."}},"required":["items","serverNow","nextCursor"],"additionalProperties":false},"InquiryView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The inquiry id."},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The requested listing type (null when not chosen yet)."},"listingTypeName":{"description":"The listing-type display name.","type":["string","null"]},"unitCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"0186 — how many units a GROUP inquiry covers; 0 or 1 means a single-unit inquiry."},"units":{"type":"array","items":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeName":{"type":["string","null"]},"propertyName":{"type":["string","null"]}},"required":["listingId","listingCode","propertyId","listingTypeName","propertyName"],"additionalProperties":false},"description":"WHICH units a group inquiry covers, ordered by listing code; empty for a single unit."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The optional property scope."},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The optionally-pinned exact listing (unit); null = auto-pick at hold time."},"unitListingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The EFFECTIVE unit (pinned listing, else the active lock’s held unit); null until resolved."},"unitListingCode":{"description":"The effective unit’s display code (null until a unit is resolved).","type":["string","null"]},"unitPropertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The effective unit’s owning property (for the listing-detail link)."},"propertyName":{"description":"The resolved property’s name — the pinned property, else the assigned unit’s. Null while an inquiry names neither.","type":["string","null"]},"channel":{"type":"string","description":"The inquiry channel."},"source":{"description":"The marketing acquisition source (0022; null pre-0022).","type":["string","null"]},"note":{"description":"The operator note (0022).","type":["string","null"]},"checkIn":{"description":"Check-in date (YYYY-MM-DD). NULL when the ask names no stay yet (0286 — a WhatsApp or OTA intake row). Paired with checkOut: both set or both null.","type":["string","null"]},"checkOut":{"description":"Check-out date (YYYY-MM-DD; exclusive). NULL when the ask names no stay yet (0286). Paired with checkIn.","type":["string","null"]},"quotedAmountMinor":{"description":"The quoted whole-stay amount in MINOR units (integer string; null until quoted).","type":["string","null"]},"quotedCurrency":{"description":"The quote currency (ISO-4217).","type":["string","null"]},"advanceAmountMinor":{"description":"The advance due now (0022; minor units; null = the full quote).","type":["string","null"]},"onPropertyAmountMinor":{"description":"The at-the-property portion of the quote (0022; minor units; advance + on-property = total).","type":["string","null"]},"promoCodeId":{"description":"The direct-booking-site promo campaign this quote redeemed (0295), or null. Snapshotted: editing the campaign never restates a quote already given.","type":["string","null"]},"promoCode":{"description":"The redeemed campaign’s CODE text, for display; null when no code was used.","type":["string","null"]},"promoDiscountMinor":{"description":"What the promo code took off, in minor units. ⚠️ quotedAmountMinor is ALREADY NET of this — it is shown so the arithmetic can be read back, never so a surface subtracts it again.","type":["string","null"]},"complimentaryReason":{"description":"WHY this stay was given away rather than sold (0343), or null for an ordinary paid quote. Non-null implies quotedAmountMinor is exactly \"0\" on purpose, and that the funnel’s next action is “confirm the complimentary stay” rather than “request the advance”.","type":["string","null"]},"complimentaryValueMinor":{"description":"The LIST value of a complimentary stay in minor units — what it would have sold for. ⚠️ NOT REVENUE AND NEVER TO BE SUMMED AS ANY: a comp posts no ledger journal, and this figure exists only to answer “how much did we give away”. A surface that adds it to a revenue total books income nobody was charged.","type":["string","null"]},"complimentaryNote":{"description":"Free text the operator recorded with a complimentary stay, or null.","type":["string","null"]},"adults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Adults (ages 13+)."},"children":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Children (ages 2–12)."},"infants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Infants (under 2)."},"pets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Pets."},"status":{"type":"string","description":"The §1.1 funnel status."},"referenceCode":{"type":"string","description":"The human-facing 8-char reservation reference (0034)."},"waitlistMatchAt":{"description":"WAITLIST phase 2: when the match sweep last found a unit free for this waitlisted stay (ISO); null = none. Advisory — the re-quote re-probes live.","type":["string","null"]},"createdAt":{"type":"string","description":"Creation instant (ISO-8601)."},"guestProofAt":{"description":"When a guest's OWN payment proof landed via the public quotation link (ISO), or null — set only while that payment is still UNVERIFIED, so verifying it clears the field. Non-null means self-serve money is waiting on a human. NOTE: this description previously said the public path 'deliberately leaves status alone'; the owner reversed that on 2026-08-07 — a guest upload now advances the funnel and takes the 2-hour hold. The field stayed load-bearing after the reversal, because when the hold CANNOT be taken the inquiry is left exactly where it was and the status alone cannot distinguish a paid stay from an unpaid one.","type":["string","null"]},"unreadMessages":{"type":"boolean","description":"0286 — does the CALLING SEAT have an unread message on this ask's thread? Per-seat, like the inbox badge: one operator opening a thread never clears the dot for the team. False for a caller with no active seat."},"bookingReferenceCode":{"description":"The human-facing 8-char reference of the RESERVATION this ask converted into, or null while it has not converted. Set only in `converted_to_booking`, by the two use-cases that write `booking_group.inquiry_id` (the paid convert and the complimentary confirm).","type":["string","null"]},"bookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The id `/bookings/{id}` resolves for the converted reservation, or null. Paired with `bookingReferenceCode`: the code is what a surface shows, this is what it links to. It is the booked apartment's id, not the deal's. It is null in the degenerate case where every apartment of a converted deal has been soft-deleted, in which case render the code as plain text."},"lock":{"anyOf":[{"$ref":"#/components/schemas/InquiryLockView"},{"type":"null"}],"description":"The ACTIVE 2h hold, if any."},"guest":{"anyOf":[{"$ref":"#/components/schemas/InquiryGuestView"},{"type":"null"}],"description":"The captured guest contact (0022)."},"events":{"type":"array","items":{"$ref":"#/components/schemas/InquiryEventView"},"description":"The funnel-transition audit trail, oldest-first — REAL per-step instants. Empty [] on list reads; populated on the detail read."}},"required":["id","listingTypeId","listingTypeName","unitCount","units","propertyId","listingId","unitListingId","unitListingCode","unitPropertyId","propertyName","channel","source","note","checkIn","checkOut","quotedAmountMinor","quotedCurrency","advanceAmountMinor","onPropertyAmountMinor","promoCodeId","promoCode","promoDiscountMinor","complimentaryReason","complimentaryValueMinor","complimentaryNote","adults","children","infants","pets","status","referenceCode","waitlistMatchAt","createdAt","guestProofAt","unreadMessages","bookingReferenceCode","bookingId","lock","guest","events"],"additionalProperties":false},"InquiryLockView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The lock id."},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The held listing."},"status":{"type":"string","description":"The lock lifecycle status."},"expiresAt":{"type":"string","description":"The ABSOLUTE expiry instant (ISO-8601) — the client computes remaining time."}},"required":["id","listingId","status","expiresAt"],"additionalProperties":false},"InquiryGuestView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"fullName":{"type":"string","description":"The guest's display name."},"phone":{"description":"Contact phone.","type":["string","null"]},"email":{"description":"Contact email.","type":["string","null"]},"whatsapp":{"description":"WhatsApp number.","type":["string","null"]},"socialUrls":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Social media profile URLs."}},"required":["id","fullName","phone","email","whatsapp","socialUrls"],"additionalProperties":false},"InquiryEventView":{"type":"object","properties":{"action":{"type":"string","description":"The funnel-transition audit action (e.g. inquiry.quoted)."},"at":{"type":"string","description":"The REAL instant the transition occurred (ISO-8601)."},"actorType":{"type":"string","description":"The kind of actor: 'user' for a person, 'system' for an automation or a rule."},"actorLabel":{"description":"The acting human's address of record, or the ruleId for a system actor. Never a raw db id.","type":["string","null"]},"actorName":{"description":"The acting person's display name beside that label — resolved at READ time from the identity plane (owner ask 2026-09-07). Null for an automation, for an impersonated row, and for any caller with no identity handle.","type":["string","null"]}},"required":["action","at","actorType","actorLabel","actorName"],"additionalProperties":false},"GetInquiryResponse":{"type":"object","properties":{"inquiry":{"$ref":"#/components/schemas/InquiryView"},"serverNow":{"type":"string","description":"Server wall-clock at read time (ISO-8601) — the countdown skew anchor."}},"required":["inquiry","serverNow"],"additionalProperties":false},"ListInquiryPromoCodesResponse":{"type":"object","properties":{"promoCodes":{"type":"array","items":{"$ref":"#/components/schemas/InquiryPromoCode"}}},"required":["promoCodes"],"additionalProperties":false},"InquiryPromoCode":{"type":"object","properties":{"id":{"type":"string","description":"The campaign id."},"code":{"type":"string","description":"The code as stored — UPPERCASE."},"label":{"description":"What a guest is told they are getting, in the operator’s words.","type":["string","null"]},"kind":{"type":"string","enum":["percent","fixed"],"description":"percent | fixed."},"pct":{"description":"percent only — 0–100 with 2 decimals, as a string.","type":["string","null"]},"amountMinor":{"description":"fixed only — minor units.","type":["string","null"]},"startsOn":{"description":"First day the code works; null = now.","type":["string","null"]},"endsOn":{"description":"Last day the code works (INCLUSIVE); null = never expires.","type":["string","null"]},"minNights":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Minimum nights, or null."},"minTotalMinor":{"description":"Minimum stay total in minor units, or null.","type":["string","null"]},"maxRedemptions":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Redemption cap, or null for unlimited."},"redemptions":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Confirmed bookings that already carry this code."}},"required":["id","code","label","kind","pct","amountMinor","startsOn","endsOn","minNights","minTotalMinor","maxRedemptions","redemptions"],"additionalProperties":false,"description":"A booking-site promo campaign an operator may apply."},"QuotePreviewResponse":{"type":"object","properties":{"currency":{"type":"string","minLength":3,"maxLength":3},"legs":{"type":"array","items":{"$ref":"#/components/schemas/QuotePreviewLeg"}},"totalMinor":{"type":"string"},"unpricedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["currency","legs","totalMinor","unpricedNights"],"additionalProperties":false},"QuotePreviewLeg":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"nights":{"type":"array","items":{"$ref":"#/components/schemas/QuotePreviewNight"}},"subtotalMinor":{"type":"string"},"unpricedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["listingId","nights","subtotalMinor","unpricedNights"],"additionalProperties":false},"QuotePreviewNight":{"type":"object","properties":{"night":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"rateMinor":{"type":["string","null"]},"source":{"type":"string","enum":["override","weekend","base","rule","unpriced"]},"ruleNames":{"type":"array","items":{"type":"string"}}},"required":["night","rateMinor","source"],"additionalProperties":false},"CancelLockedInquiryResponse":{"type":"object","properties":{"inquiry":{"$ref":"#/components/schemas/InquiryView"},"nightsReleased":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Held nights handed back to inventory by this cancel."},"paymentsRejected":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Proof payments moved to rejected (the claim, refused on the record)."}},"required":["inquiry","nightsReleased","paymentsRejected"],"additionalProperties":false},"BookingView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"inquiryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The originating inquiry."},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booked listing (unit)."},"listingCode":{"description":"The listing display code.","type":["string","null"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property."},"propertyName":{"description":"The property display name.","type":["string","null"]},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing type."},"listingTypeName":{"description":"The type display name.","type":["string","null"]},"channel":{"type":"string","description":"The settlement channel."},"source":{"type":"string","description":"The booking-source provenance category."},"checkIn":{"type":"string","description":"Check-in date (YYYY-MM-DD)."},"checkOut":{"type":"string","description":"The BOOKED check-out date (YYYY-MM-DD; exclusive)."},"departedOn":{"description":"The day an EARLY check-out happened (YYYY-MM-DD, workspace-local), or null when the guest left on `checkOut` or has not left yet. The stay ended here; `checkOut` stays the booked date.","type":["string","null"]},"status":{"type":"string","description":"The booking lifecycle status of THIS leg."},"dealStatus":{"type":"string","description":"The DEAL's status: one answer for the whole stay, derived from its least-advanced live unit. Equal to `status` for a single-listing booking; the field to render. `status` is what the lifecycle actions act on."},"totalAmountMinor":{"type":"string","description":"The whole-stay total in MINOR units (integer string)."},"currency":{"type":"string","description":"The currency (ISO-4217)."},"paidAmountMinor":{"type":"string","description":"The verified cash received so far in MINOR units (the advance). GROSS: see `refundedAmountMinor`."},"refundedAmountMinor":{"type":"string","description":"Cash RETURNED to the guest on account of this booking, in MINOR units: the refund flow plus the cancellation and early-checkout settlements (which return money without minting a refund row). `paidAmountMinor` is gross, so a balance is `total - allowance - released - (paid - refunded)`."},"allowanceAmountMinor":{"type":"string","description":"Cash given as an ALLOWANCE (0394), in MINOR units: compensation returned with the quoted total deliberately left standing, so the sale is not restated and ADR keeps the real price. It reduces what the guest is asked for, so a balance is `total - allowance - released - (paid - refunded)`. Without it a stay paid in full and then compensated reports the guest as owing back the money they were just given."},"releasedAmountMinor":{"type":"string","description":"Cash a SETTLEMENT paid back for nights given up (an early check-out or a cancellation), in MINOR units. It is inside `refundedAmountMinor` as well, and it is no longer owed, so a balance is `total - allowance - released - (paid - refunded)`: zero on a stay paid in full and settled at departure. An operator refund is not a release: on a stay that ran, the price stands."},"extraChargesMinor":{"type":"string","description":"Cash COLLECTED beyond the room rate, in MINOR units: additional cleaning, early check-in, late check-out, extra guest, house-rule fines, recovered damage. Voided charges are excluded. NOT part of the balance, since an extra is collected and owed in the same instant."},"adults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Adults (ages 13+)."},"children":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Children (ages 2–12)."},"infants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Infants (under 2)."},"pets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Pets."},"referenceCode":{"type":"string","description":"The human-facing 8-char booking reference of THIS leg (guest confirmation, 0034)."},"dealReferenceCode":{"type":"string","description":"The DEAL's 8-char reference: one code for the whole stay, and the one to render. Equal to `referenceCode` for a single-listing booking."},"inquiryReferenceCode":{"description":"The human-facing 8-char reference of the INQUIRY this stay came from, or null when it never was one. Paired with `inquiryId`: that is what a surface links to, this is what it shows. Null for every booking minted outside the funnel: a walk-in, a group booking, an iCal import, a channel revision.","type":["string","null"]},"channelReservationUrl":{"description":"The Airbnb reservation deep link, for imported bookings from a `Reserved` iCal event (airbnb.com only); null otherwise (0052).","type":["string","null"]},"bookingGroupId":{"description":"0187: the multi-listing group this stay belongs to; null for a standalone booking.","type":["string","null"]},"groupSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many bookings share the group (1 = standalone)."},"groupTotalAmountMinor":{"description":"The GROUP's total in minor units: what the guest owes for the whole deal, not this leg's share.","type":["string","null"]},"groupPaidAmountMinor":{"description":"Cash received for the WHOLE group in minor units; null when standalone. A balance computed on the leg alone would misreport a fully-paid group as owing.","type":["string","null"]},"groupRefundedAmountMinor":{"description":"Cash RETURNED for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupAllowanceAmountMinor":{"description":"Allowances GIVEN for the WHOLE group in minor units (0394); null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupReleasedAmountMinor":{"description":"Nights RELEASED at a settlement for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupExtraChargesMinor":{"description":"Extras COLLECTED for the WHOLE group in minor units; null when standalone.","type":["string","null"]},"channelPhoneLast4":{"description":"The guest phone's last 4 digits from the Airbnb iCal DESCRIPTION, all the feed ever exposes; null otherwise (0052).","type":["string","null"]},"channelExternalId":{"description":"The reference the stay ARRIVED under: an Airbnb reservation id, or the confirmation code from an imported spreadsheet row. Null on a natively-created booking. NOT `referenceCode`, which is our own system-generated code.","type":["string","null"]},"channelGrossMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the stay's value before the channel's cut, in `currency` minor units, as the channel reported it. Null when it did not say."},"channelCommissionMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the channel's commission or host fee in `currency` minor units. Null when the channel did not report it; never estimated."},"channelPayoutMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: what the channel will pay out (the channel receivable) in `currency` minor units. Set only when the channel collected the money; null when the property collects."},"createdAt":{"type":"string","description":"Creation instant (ISO-8601)."},"guest":{"anyOf":[{"$ref":"#/components/schemas/BookingGuestView"},{"type":"null"}],"description":"The guest contact, if captured."}},"required":["id","inquiryId","listingId","listingCode","propertyId","propertyName","listingTypeId","listingTypeName","channel","source","checkIn","checkOut","departedOn","status","dealStatus","totalAmountMinor","currency","paidAmountMinor","refundedAmountMinor","allowanceAmountMinor","releasedAmountMinor","extraChargesMinor","adults","children","infants","pets","referenceCode","dealReferenceCode","inquiryReferenceCode","channelReservationUrl","bookingGroupId","groupSize","groupTotalAmountMinor","groupPaidAmountMinor","groupRefundedAmountMinor","groupAllowanceAmountMinor","groupReleasedAmountMinor","groupExtraChargesMinor","channelPhoneLast4","channelExternalId","channelGrossMinor","channelCommissionMinor","channelPayoutMinor","createdAt","guest"],"additionalProperties":false},"BookingGuestView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"fullName":{"type":"string","description":"The guest's display name."},"phone":{"description":"Contact phone.","type":["string","null"]},"email":{"description":"Contact email.","type":["string","null"]},"whatsapp":{"description":"WhatsApp number.","type":["string","null"]}},"required":["id","fullName","phone","email","whatsapp"],"additionalProperties":false},"ListBookingsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BookingDealView"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"Pass as `cursor` to read the next page in the same order; null when this page ends the list."},"workingPulse":{"description":"Present on the first page of `partition=working`: the tenant-wide KPI figures.","$ref":"#/components/schemas/BookingWorkingPulse"}},"required":["items","nextCursor"],"additionalProperties":false},"BookingDealView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"inquiryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The originating inquiry."},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booked listing (unit)."},"listingCode":{"description":"The listing display code.","type":["string","null"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property."},"propertyName":{"description":"The property display name.","type":["string","null"]},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing type."},"listingTypeName":{"description":"The type display name.","type":["string","null"]},"channel":{"type":"string","description":"The settlement channel."},"source":{"type":"string","description":"The booking-source provenance category."},"checkIn":{"type":"string","description":"Check-in date (YYYY-MM-DD)."},"checkOut":{"type":"string","description":"The BOOKED check-out date (YYYY-MM-DD; exclusive)."},"departedOn":{"description":"The day an EARLY check-out happened (YYYY-MM-DD, workspace-local), or null when the guest left on `checkOut` or has not left yet. The stay ended here; `checkOut` stays the booked date.","type":["string","null"]},"status":{"type":"string","description":"The booking lifecycle status of THIS leg."},"dealStatus":{"type":"string","description":"The DEAL's status: one answer for the whole stay, derived from its least-advanced live unit. Equal to `status` for a single-listing booking; the field to render. `status` is what the lifecycle actions act on."},"totalAmountMinor":{"type":"string","description":"The whole-stay total in MINOR units (integer string)."},"currency":{"type":"string","description":"The currency (ISO-4217)."},"paidAmountMinor":{"type":"string","description":"The verified cash received so far in MINOR units (the advance). GROSS: see `refundedAmountMinor`."},"refundedAmountMinor":{"type":"string","description":"Cash RETURNED to the guest on account of this booking, in MINOR units: the refund flow plus the cancellation and early-checkout settlements (which return money without minting a refund row). `paidAmountMinor` is gross, so a balance is `total - allowance - released - (paid - refunded)`."},"allowanceAmountMinor":{"type":"string","description":"Cash given as an ALLOWANCE (0394), in MINOR units: compensation returned with the quoted total deliberately left standing, so the sale is not restated and ADR keeps the real price. It reduces what the guest is asked for, so a balance is `total - allowance - released - (paid - refunded)`. Without it a stay paid in full and then compensated reports the guest as owing back the money they were just given."},"releasedAmountMinor":{"type":"string","description":"Cash a SETTLEMENT paid back for nights given up (an early check-out or a cancellation), in MINOR units. It is inside `refundedAmountMinor` as well, and it is no longer owed, so a balance is `total - allowance - released - (paid - refunded)`: zero on a stay paid in full and settled at departure. An operator refund is not a release: on a stay that ran, the price stands."},"extraChargesMinor":{"type":"string","description":"Cash COLLECTED beyond the room rate, in MINOR units: additional cleaning, early check-in, late check-out, extra guest, house-rule fines, recovered damage. Voided charges are excluded. NOT part of the balance, since an extra is collected and owed in the same instant."},"adults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Adults (ages 13+)."},"children":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Children (ages 2–12)."},"infants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Infants (under 2)."},"pets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Pets."},"referenceCode":{"type":"string","description":"The human-facing 8-char booking reference of THIS leg (guest confirmation, 0034)."},"dealReferenceCode":{"type":"string","description":"The DEAL's 8-char reference: one code for the whole stay, and the one to render. Equal to `referenceCode` for a single-listing booking."},"inquiryReferenceCode":{"description":"The human-facing 8-char reference of the INQUIRY this stay came from, or null when it never was one. Paired with `inquiryId`: that is what a surface links to, this is what it shows. Null for every booking minted outside the funnel: a walk-in, a group booking, an iCal import, a channel revision.","type":["string","null"]},"channelReservationUrl":{"description":"The Airbnb reservation deep link, for imported bookings from a `Reserved` iCal event (airbnb.com only); null otherwise (0052).","type":["string","null"]},"bookingGroupId":{"description":"0187: the multi-listing group this stay belongs to; null for a standalone booking.","type":["string","null"]},"groupSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many bookings share the group (1 = standalone)."},"groupTotalAmountMinor":{"description":"The GROUP's total in minor units: what the guest owes for the whole deal, not this leg's share.","type":["string","null"]},"groupPaidAmountMinor":{"description":"Cash received for the WHOLE group in minor units; null when standalone. A balance computed on the leg alone would misreport a fully-paid group as owing.","type":["string","null"]},"groupRefundedAmountMinor":{"description":"Cash RETURNED for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupAllowanceAmountMinor":{"description":"Allowances GIVEN for the WHOLE group in minor units (0394); null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupReleasedAmountMinor":{"description":"Nights RELEASED at a settlement for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupExtraChargesMinor":{"description":"Extras COLLECTED for the WHOLE group in minor units; null when standalone.","type":["string","null"]},"channelPhoneLast4":{"description":"The guest phone's last 4 digits from the Airbnb iCal DESCRIPTION, all the feed ever exposes; null otherwise (0052).","type":["string","null"]},"channelExternalId":{"description":"The reference the stay ARRIVED under: an Airbnb reservation id, or the confirmation code from an imported spreadsheet row. Null on a natively-created booking. NOT `referenceCode`, which is our own system-generated code.","type":["string","null"]},"channelGrossMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the stay's value before the channel's cut, in `currency` minor units, as the channel reported it. Null when it did not say."},"channelCommissionMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the channel's commission or host fee in `currency` minor units. Null when the channel did not report it; never estimated."},"channelPayoutMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: what the channel will pay out (the channel receivable) in `currency` minor units. Set only when the channel collected the money; null when the property collects."},"createdAt":{"type":"string","description":"Creation instant (ISO-8601)."},"guest":{"anyOf":[{"$ref":"#/components/schemas/BookingGuestView"},{"type":"null"}],"description":"The guest contact, if captured."},"groupLegs":{"type":"array","items":{"$ref":"#/components/schemas/BookingDealLegView"},"description":"Every live unit of this deal, lowest listing code first — one entry for a single-listing booking, and EMPTY when the caller asked for unit rows rather than deals (the row is then itself one unit, nothing was folded). The unit cell renders these and the search matches against them, so an operator who can SEE a code on a row can also find it by typing it."}},"required":["id","inquiryId","listingId","listingCode","propertyId","propertyName","listingTypeId","listingTypeName","channel","source","checkIn","checkOut","departedOn","status","dealStatus","totalAmountMinor","currency","paidAmountMinor","refundedAmountMinor","allowanceAmountMinor","releasedAmountMinor","extraChargesMinor","adults","children","infants","pets","referenceCode","dealReferenceCode","inquiryReferenceCode","channelReservationUrl","bookingGroupId","groupSize","groupTotalAmountMinor","groupPaidAmountMinor","groupRefundedAmountMinor","groupAllowanceAmountMinor","groupReleasedAmountMinor","groupExtraChargesMinor","channelPhoneLast4","channelExternalId","channelGrossMinor","channelCommissionMinor","channelPayoutMinor","createdAt","guest","groupLegs"],"additionalProperties":false},"BookingDealLegView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The unit booking id — openable at /bookings/{id}."},"listingCode":{"description":"The listing display code.","type":["string","null"]},"propertyName":{"description":"The property display name.","type":["string","null"]},"listingTypeName":{"description":"The type display name.","type":["string","null"]}},"required":["id","listingCode","propertyName","listingTypeName"],"additionalProperties":false},"BookingWorkingPulse":{"type":"object","properties":{"active":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Working-set deals that are not cancelled or no-show."},"inHouse":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Deals whose guest is checked in and not yet out."},"verificationPending":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"checkoutsToday":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"checkInsToday":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"fullyPaid":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Active deals whose net verified cash covers the total."},"outstandingMinor":{"type":"string","description":"Sum of the unpaid balances of active base-currency deals, minor units as a string."}},"required":["active","inHouse","verificationPending","checkoutsToday","checkInsToday","fullyPaid","outstandingMinor"],"additionalProperties":false},"GroupBookingView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking-group id."},"guestId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The group booker."},"source":{"type":"string","description":"The shared booking-source provenance."},"currency":{"type":"string","description":"The currency (ISO-4217)."},"groupTotalMinor":{"type":"string","description":"The whole-group settled total in MINOR units (the sum of the legs)."},"bookings":{"type":"array","items":{"$ref":"#/components/schemas/BookingView"},"description":"The confirmed leg bookings, all bound to this group."}},"required":["id","guestId","source","currency","groupTotalMinor","bookings"],"additionalProperties":false},"BookingDetailView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"inquiryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The originating inquiry."},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booked listing (unit)."},"listingCode":{"description":"The listing display code.","type":["string","null"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property."},"propertyName":{"description":"The property display name.","type":["string","null"]},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing type."},"listingTypeName":{"description":"The type display name.","type":["string","null"]},"channel":{"type":"string","description":"The settlement channel."},"source":{"type":"string","description":"The booking-source provenance category."},"checkIn":{"type":"string","description":"Check-in date (YYYY-MM-DD)."},"checkOut":{"type":"string","description":"The BOOKED check-out date (YYYY-MM-DD; exclusive)."},"departedOn":{"description":"The day an EARLY check-out happened (YYYY-MM-DD, workspace-local), or null when the guest left on `checkOut` or has not left yet. The stay ended here; `checkOut` stays the booked date.","type":["string","null"]},"status":{"type":"string","description":"The booking lifecycle status of THIS leg."},"dealStatus":{"type":"string","description":"The DEAL's status: one answer for the whole stay, derived from its least-advanced live unit. Equal to `status` for a single-listing booking; the field to render. `status` is what the lifecycle actions act on."},"totalAmountMinor":{"type":"string","description":"The whole-stay total in MINOR units (integer string)."},"currency":{"type":"string","description":"The currency (ISO-4217)."},"paidAmountMinor":{"type":"string","description":"The verified cash received so far in MINOR units (the advance). GROSS: see `refundedAmountMinor`."},"refundedAmountMinor":{"type":"string","description":"Cash RETURNED to the guest on account of this booking, in MINOR units: the refund flow plus the cancellation and early-checkout settlements (which return money without minting a refund row). `paidAmountMinor` is gross, so a balance is `total - allowance - released - (paid - refunded)`."},"allowanceAmountMinor":{"type":"string","description":"Cash given as an ALLOWANCE (0394), in MINOR units: compensation returned with the quoted total deliberately left standing, so the sale is not restated and ADR keeps the real price. It reduces what the guest is asked for, so a balance is `total - allowance - released - (paid - refunded)`. Without it a stay paid in full and then compensated reports the guest as owing back the money they were just given."},"releasedAmountMinor":{"type":"string","description":"Cash a SETTLEMENT paid back for nights given up (an early check-out or a cancellation), in MINOR units. It is inside `refundedAmountMinor` as well, and it is no longer owed, so a balance is `total - allowance - released - (paid - refunded)`: zero on a stay paid in full and settled at departure. An operator refund is not a release: on a stay that ran, the price stands."},"extraChargesMinor":{"type":"string","description":"Cash COLLECTED beyond the room rate, in MINOR units: additional cleaning, early check-in, late check-out, extra guest, house-rule fines, recovered damage. Voided charges are excluded. NOT part of the balance, since an extra is collected and owed in the same instant."},"adults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Adults (ages 13+)."},"children":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Children (ages 2–12)."},"infants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Infants (under 2)."},"pets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Pets."},"referenceCode":{"type":"string","description":"The human-facing 8-char booking reference of THIS leg (guest confirmation, 0034)."},"dealReferenceCode":{"type":"string","description":"The DEAL's 8-char reference: one code for the whole stay, and the one to render. Equal to `referenceCode` for a single-listing booking."},"inquiryReferenceCode":{"description":"The human-facing 8-char reference of the INQUIRY this stay came from, or null when it never was one. Paired with `inquiryId`: that is what a surface links to, this is what it shows. Null for every booking minted outside the funnel: a walk-in, a group booking, an iCal import, a channel revision.","type":["string","null"]},"channelReservationUrl":{"description":"The Airbnb reservation deep link, for imported bookings from a `Reserved` iCal event (airbnb.com only); null otherwise (0052).","type":["string","null"]},"bookingGroupId":{"description":"0187: the multi-listing group this stay belongs to; null for a standalone booking.","type":["string","null"]},"groupSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many bookings share the group (1 = standalone)."},"groupTotalAmountMinor":{"description":"The GROUP's total in minor units: what the guest owes for the whole deal, not this leg's share.","type":["string","null"]},"groupPaidAmountMinor":{"description":"Cash received for the WHOLE group in minor units; null when standalone. A balance computed on the leg alone would misreport a fully-paid group as owing.","type":["string","null"]},"groupRefundedAmountMinor":{"description":"Cash RETURNED for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupAllowanceAmountMinor":{"description":"Allowances GIVEN for the WHOLE group in minor units (0394); null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupReleasedAmountMinor":{"description":"Nights RELEASED at a settlement for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupExtraChargesMinor":{"description":"Extras COLLECTED for the WHOLE group in minor units; null when standalone.","type":["string","null"]},"channelPhoneLast4":{"description":"The guest phone's last 4 digits from the Airbnb iCal DESCRIPTION, all the feed ever exposes; null otherwise (0052).","type":["string","null"]},"channelExternalId":{"description":"The reference the stay ARRIVED under: an Airbnb reservation id, or the confirmation code from an imported spreadsheet row. Null on a natively-created booking. NOT `referenceCode`, which is our own system-generated code.","type":["string","null"]},"channelGrossMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the stay's value before the channel's cut, in `currency` minor units, as the channel reported it. Null when it did not say."},"channelCommissionMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the channel's commission or host fee in `currency` minor units. Null when the channel did not report it; never estimated."},"channelPayoutMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: what the channel will pay out (the channel receivable) in `currency` minor units. Set only when the channel collected the money; null when the property collects."},"createdAt":{"type":"string","description":"Creation instant (ISO-8601)."},"guest":{"anyOf":[{"$ref":"#/components/schemas/BookingGuestView"},{"type":"null"}],"description":"The guest contact, if captured."},"registeredGuests":{"type":"integer","minimum":0,"maximum":9007199254740991,"description":"Guests entered on the booking's live guest-app check-in. A voided check-in counts nobody; none at all is 0."},"expectedGuests":{"anyOf":[{"type":"integer","minimum":1,"maximum":9007199254740991},{"type":"null"}],"description":"The party the booking was made for (adults plus children). Null when the booking records no party, as some channel bookings do."}},"required":["id","inquiryId","listingId","listingCode","propertyId","propertyName","listingTypeId","listingTypeName","channel","source","checkIn","checkOut","departedOn","status","dealStatus","totalAmountMinor","currency","paidAmountMinor","refundedAmountMinor","allowanceAmountMinor","releasedAmountMinor","extraChargesMinor","adults","children","infants","pets","referenceCode","dealReferenceCode","inquiryReferenceCode","channelReservationUrl","bookingGroupId","groupSize","groupTotalAmountMinor","groupPaidAmountMinor","groupRefundedAmountMinor","groupAllowanceAmountMinor","groupReleasedAmountMinor","groupExtraChargesMinor","channelPhoneLast4","channelExternalId","channelGrossMinor","channelCommissionMinor","channelPayoutMinor","createdAt","guest","registeredGuests","expectedGuests"],"additionalProperties":false},"BookingConditionResponse":{"type":"object","properties":{"bookingId":{"type":"string"},"media":{"type":"array","items":{"$ref":"#/components/schemas/ConditionMediaView"}},"phases":{"type":"array","items":{"$ref":"#/components/schemas/ConditionPhaseState"}},"housekeepingReadyBeforeCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"inheritedHandover":{"$ref":"#/components/schemas/InheritedHandoverView"}},"required":["bookingId","media","phases","housekeepingReadyBeforeCount"],"additionalProperties":false},"ConditionMediaView":{"type":"object","properties":{"id":{"type":"string"},"phase":{"type":"string","enum":["pre_check_in","post_check_out"]},"contentType":{"type":"string"},"byteSize":{"type":["string","null"]},"uploadStatus":{"type":"string"},"capturedAt":{"type":["string","null"]},"capturedAtSource":{"type":"string","enum":["exif","video_metadata","file_modified","unknown"]},"uploadedAt":{"type":"string"},"originalFilename":{"type":["string","null"]},"caption":{"type":["string","null"]},"cleaningTaskId":{"type":["string","null"]},"inspectionId":{"type":["string","null"]},"damageReportId":{"type":["string","null"]}},"required":["id","phase","contentType","byteSize","uploadStatus","capturedAt","capturedAtSource","uploadedAt","originalFilename","caption","cleaningTaskId","inspectionId","damageReportId"],"additionalProperties":false},"ConditionPhaseState":{"type":"object","properties":{"phase":{"type":"string","enum":["pre_check_in","post_check_out"]},"required":{"type":"boolean","description":"Is the workspace setting armed for this phase?"},"satisfied":{"type":"boolean","description":"Does the stay hold ready evidence for it?"},"blocking":{"type":"boolean","description":"Would this phase’s transition be refused right now (required ∧ ¬satisfied)?"}},"required":["phase","required","satisfied","blocking"],"additionalProperties":false},"InheritedHandoverView":{"type":"object","properties":{"cleaningTaskId":{"type":"string"},"completedAt":{"type":"string"},"photos":{"type":"array","items":{"$ref":"#/components/schemas/InheritedHandoverPhoto"}},"intact":{"type":"boolean"},"brokenBy":{"anyOf":[{"type":"string","enum":["no_after_photo","blocked_between","readiness_changed"]},{"type":"null"}],"description":"Why the chain from that clean to this arrival is not intact."}},"required":["cleaningTaskId","completedAt","photos","intact","brokenBy"],"additionalProperties":false},"InheritedHandoverPhoto":{"type":"object","properties":{"id":{"type":"string"},"contentType":{"type":"string"}},"required":["id","contentType"],"additionalProperties":false},"RequestConditionMediaUploadResponse":{"type":"object","properties":{"mediaId":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["mediaId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmConditionMediaUploadResponse":{"type":"object","properties":{"mediaId":{"type":"string"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["mediaId","uploadStatus","byteSize"],"additionalProperties":false},"MintConditionMediaViewUrlResponse":{"type":"object","properties":{"mediaId":{"type":"string"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["mediaId","url","expiresInSeconds"],"additionalProperties":false},"MintInheritedHandoverViewUrlResponse":{"type":"object","properties":{"photoId":{"type":"string"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},"required":["photoId","url","expiresInSeconds"],"additionalProperties":false},"AnnotateConditionMediaResponse":{"type":"object","properties":{"mediaId":{"type":"string"},"updated":{"type":"boolean","const":true}},"required":["mediaId","updated"],"additionalProperties":false},"RemoveConditionMediaResponse":{"type":"object","properties":{"mediaId":{"type":"string"},"removed":{"type":"boolean","const":true}},"required":["mediaId","removed"],"additionalProperties":false},"DamageReportView":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"inspectionId":{"type":["string","null"]},"listingId":{"type":"string"},"kind":{"type":"string"},"description":{"type":"string"},"estimatedCost":{"description":"MINOR units, decimal string — an ESTIMATE, never a posting.","type":["string","null"]},"currency":{"type":["string","null"]},"escalatedAt":{"type":["string","null"]},"resolvedAt":{"type":["string","null"]},"outcome":{"type":["string","null"]},"listingCode":{"type":["string","null"]},"propertyId":{"type":["string","null"]},"bookingReference":{"type":["string","null"]}},"required":["id","bookingId","inspectionId","listingId","kind","description","estimatedCost","currency","escalatedAt","resolvedAt","outcome","listingCode","propertyId","bookingReference"],"additionalProperties":false},"CancelBookingResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booking id."},"inquiryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The originating inquiry."},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The booked listing (unit)."},"listingCode":{"description":"The listing display code.","type":["string","null"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The property."},"propertyName":{"description":"The property display name.","type":["string","null"]},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The listing type."},"listingTypeName":{"description":"The type display name.","type":["string","null"]},"channel":{"type":"string","description":"The settlement channel."},"source":{"type":"string","description":"The booking-source provenance category."},"checkIn":{"type":"string","description":"Check-in date (YYYY-MM-DD)."},"checkOut":{"type":"string","description":"The BOOKED check-out date (YYYY-MM-DD; exclusive)."},"departedOn":{"description":"The day an EARLY check-out happened (YYYY-MM-DD, workspace-local), or null when the guest left on `checkOut` or has not left yet. The stay ended here; `checkOut` stays the booked date.","type":["string","null"]},"status":{"type":"string","description":"The booking lifecycle status of THIS leg."},"dealStatus":{"type":"string","description":"The DEAL's status: one answer for the whole stay, derived from its least-advanced live unit. Equal to `status` for a single-listing booking; the field to render. `status` is what the lifecycle actions act on."},"totalAmountMinor":{"type":"string","description":"The whole-stay total in MINOR units (integer string)."},"currency":{"type":"string","description":"The currency (ISO-4217)."},"paidAmountMinor":{"type":"string","description":"The verified cash received so far in MINOR units (the advance). GROSS: see `refundedAmountMinor`."},"refundedAmountMinor":{"type":"string","description":"Cash RETURNED to the guest on account of this booking, in MINOR units: the refund flow plus the cancellation and early-checkout settlements (which return money without minting a refund row). `paidAmountMinor` is gross, so a balance is `total - allowance - released - (paid - refunded)`."},"allowanceAmountMinor":{"type":"string","description":"Cash given as an ALLOWANCE (0394), in MINOR units: compensation returned with the quoted total deliberately left standing, so the sale is not restated and ADR keeps the real price. It reduces what the guest is asked for, so a balance is `total - allowance - released - (paid - refunded)`. Without it a stay paid in full and then compensated reports the guest as owing back the money they were just given."},"releasedAmountMinor":{"type":"string","description":"Cash a SETTLEMENT paid back for nights given up (an early check-out or a cancellation), in MINOR units. It is inside `refundedAmountMinor` as well, and it is no longer owed, so a balance is `total - allowance - released - (paid - refunded)`: zero on a stay paid in full and settled at departure. An operator refund is not a release: on a stay that ran, the price stands."},"extraChargesMinor":{"type":"string","description":"Cash COLLECTED beyond the room rate, in MINOR units: additional cleaning, early check-in, late check-out, extra guest, house-rule fines, recovered damage. Voided charges are excluded. NOT part of the balance, since an extra is collected and owed in the same instant."},"adults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Adults (ages 13+)."},"children":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Children (ages 2–12)."},"infants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Infants (under 2)."},"pets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Pets."},"referenceCode":{"type":"string","description":"The human-facing 8-char booking reference of THIS leg (guest confirmation, 0034)."},"dealReferenceCode":{"type":"string","description":"The DEAL's 8-char reference: one code for the whole stay, and the one to render. Equal to `referenceCode` for a single-listing booking."},"inquiryReferenceCode":{"description":"The human-facing 8-char reference of the INQUIRY this stay came from, or null when it never was one. Paired with `inquiryId`: that is what a surface links to, this is what it shows. Null for every booking minted outside the funnel: a walk-in, a group booking, an iCal import, a channel revision.","type":["string","null"]},"channelReservationUrl":{"description":"The Airbnb reservation deep link, for imported bookings from a `Reserved` iCal event (airbnb.com only); null otherwise (0052).","type":["string","null"]},"bookingGroupId":{"description":"0187: the multi-listing group this stay belongs to; null for a standalone booking.","type":["string","null"]},"groupSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many bookings share the group (1 = standalone)."},"groupTotalAmountMinor":{"description":"The GROUP's total in minor units: what the guest owes for the whole deal, not this leg's share.","type":["string","null"]},"groupPaidAmountMinor":{"description":"Cash received for the WHOLE group in minor units; null when standalone. A balance computed on the leg alone would misreport a fully-paid group as owing.","type":["string","null"]},"groupRefundedAmountMinor":{"description":"Cash RETURNED for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupAllowanceAmountMinor":{"description":"Allowances GIVEN for the WHOLE group in minor units (0394); null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupReleasedAmountMinor":{"description":"Nights RELEASED at a settlement for the WHOLE group in minor units; null when standalone. Same reason as `groupPaidAmountMinor`.","type":["string","null"]},"groupExtraChargesMinor":{"description":"Extras COLLECTED for the WHOLE group in minor units; null when standalone.","type":["string","null"]},"channelPhoneLast4":{"description":"The guest phone's last 4 digits from the Airbnb iCal DESCRIPTION, all the feed ever exposes; null otherwise (0052).","type":["string","null"]},"channelExternalId":{"description":"The reference the stay ARRIVED under: an Airbnb reservation id, or the confirmation code from an imported spreadsheet row. Null on a natively-created booking. NOT `referenceCode`, which is our own system-generated code.","type":["string","null"]},"channelGrossMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the stay's value before the channel's cut, in `currency` minor units, as the channel reported it. Null when it did not say."},"channelCommissionMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: the channel's commission or host fee in `currency` minor units. Null when the channel did not report it; never estimated."},"channelPayoutMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"0439: what the channel will pay out (the channel receivable) in `currency` minor units. Set only when the channel collected the money; null when the property collects."},"createdAt":{"type":"string","description":"Creation instant (ISO-8601)."},"guest":{"anyOf":[{"$ref":"#/components/schemas/BookingGuestView"},{"type":"null"}],"description":"The guest contact, if captured."},"settlementOutcome":{"type":"string","enum":["not_requested","posted","already_processed","model_not_applicable","nothing_to_settle"],"description":"What happened to a requested cancellation-money settlement. `not_requested` — none was asked for. `posted` — a settlement journal went through. `already_processed` — this cancellation was already settled (a retried request). `model_not_applicable` — this booking is managed/investor money; it has no deferred-revenue pool to settle here, use the refund request/approve flow instead. `nothing_to_settle` — the deferred pool was already zero or negative, so there was nothing left to keep, refund, or forfeit."}},"required":["id","inquiryId","listingId","listingCode","propertyId","propertyName","listingTypeId","listingTypeName","channel","source","checkIn","checkOut","departedOn","status","dealStatus","totalAmountMinor","currency","paidAmountMinor","refundedAmountMinor","allowanceAmountMinor","releasedAmountMinor","extraChargesMinor","adults","children","infants","pets","referenceCode","dealReferenceCode","inquiryReferenceCode","channelReservationUrl","bookingGroupId","groupSize","groupTotalAmountMinor","groupPaidAmountMinor","groupRefundedAmountMinor","groupAllowanceAmountMinor","groupReleasedAmountMinor","groupExtraChargesMinor","channelPhoneLast4","channelExternalId","channelGrossMinor","channelCommissionMinor","channelPayoutMinor","createdAt","guest","settlementOutcome"],"additionalProperties":false},"RefundView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"currency":{"type":"string","minLength":3,"maxLength":3},"reason":{"type":"string"},"status":{"type":"string","enum":["requested","paid","rejected"]},"kind":{"type":"string","enum":["price_adjustment","allowance"],"description":"Which bookkeeping this refund was (0394): a price adjustment (the stay cost less) or an allowance (the price stands; this is compensation)."},"requestedBy":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The maker membership (refund:request)."},"decidedBy":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The checker membership, once decided."},"decidedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["id","bookingId","paymentId","amountMinor","currency","reason","status","kind","requestedBy","decidedBy","decidedAt","createdAt"],"additionalProperties":false},"ListRefundsResponse":{"type":"object","properties":{"refunds":{"type":"array","items":{"$ref":"#/components/schemas/RefundView"}},"paidMinor":{"type":"string","pattern":"^\\d+$","description":"Σ verified payments on the booking (minor units)."},"committedMinor":{"type":"string","pattern":"^\\d+$","description":"Σ requested + paid refunds (minor units) — the reserved capacity."},"openLiabilityMinor":{"type":"string","pattern":"^\\d+$","description":"The booking's open inflow liability (2000/2100/2160, minor units) — what a refund may actually debit. Smaller than the cash paid once nights have been recognised as revenue."},"ledgerCapacityMinor":{"type":"string","pattern":"^\\d+$","description":"What the LEDGER can fund a refund from (minor units): the open liability PLUS operator revenue already recognised for this booking and not yet given back (4000/4001 net of 4910). A stay whose nights have all passed holds no liability and is funded entirely from the second term. Always 0 on a managed/investor booking, which recognises no operator revenue at all."},"overpaidMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}],"description":"Cash held beyond the quoted total, net of committed refunds (minor units). NULL on a cancelled/no-show booking, where the whole advance is potentially owed back and the bound does not apply. Clamped at 0."},"availableMinor":{"type":"string","pattern":"^\\d+$","description":"The binding ceiling a PRICE-ADJUSTMENT request must not exceed (minor units) — the smallest of the bounds that apply. Clamped at 0."},"allowanceAvailableMinor":{"type":"string","pattern":"^\\d+$","description":"The ceiling an ALLOWANCE request must not exceed (minor units, 0394): the cash bound and the ledger bound, and deliberately NOT the overpayment one. On a stay paid exactly in full this is the only non-zero ceiling there is. Clamped at 0."},"allowancePaidMinor":{"type":"string","pattern":"^\\d+$","description":"Σ allowances already PAID on this booking (minor units, 0394) — compensation given with the quoted total left standing. It reduces what the guest is asked for, so the booking's balance is total − this − (paid − refunded)."}},"required":["refunds","paidMinor","committedMinor","openLiabilityMinor","ledgerCapacityMinor","overpaidMinor","availableMinor","allowanceAvailableMinor","allowancePaidMinor"],"additionalProperties":false},"BookingHistoryResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BookingHistoryEntry"}}},"required":["items"],"additionalProperties":false},"BookingHistoryEntry":{"type":"object","properties":{"occurredAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"action":{"type":"string"},"entityType":{"type":"string"},"actorType":{"type":"string"},"actorLabel":{"type":["string","null"]},"actorName":{"type":["string","null"]},"diff":{}},"required":["occurredAt","action","entityType","actorType","actorLabel","actorName","diff"],"additionalProperties":false},"BookingVersionResponse":{"type":"object","properties":{"version":{"description":"An opaque token (the newest audit row in the booking story); it moves on any recorded change.","type":["string","null"]},"byCaller":{"type":"boolean","description":"Whether that newest change was the caller’s own."}},"required":["version","byCaller"],"additionalProperties":false},"GuestCashPaymentView":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"receiptNumber":{"type":"string"},"status":{"type":"string","enum":["verified","pending_verification"]},"requiresSecondApproval":{"type":"boolean"}},"required":["paymentId","receiptNumber","status","requiresSecondApproval"],"additionalProperties":false},"ApproveGuestCashResult":{"type":"object","properties":{"journalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["journalEntryId"],"additionalProperties":false},"GuestCashReportResponse":{"type":"object","properties":{"rows":{"type":"array","items":{"$ref":"#/components/schemas/GuestCashReportRow"}},"totals":{"type":"object","properties":{"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"verifiedMinor":{"type":"string","pattern":"^\\d+$","description":"Σ verified guest-cash (minor units)."},"pendingMinor":{"type":"string","pattern":"^\\d+$","description":"Σ pending-verification guest-cash (minor units)."}},"required":["count","verifiedMinor","pendingMinor"],"additionalProperties":false}},"required":["rows","totals"],"additionalProperties":false},"GuestCashReportRow":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"receiptNumber":{"type":"string"},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"guestName":{"type":["string","null"]},"listingCode":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"senderName":{"type":["string","null"]},"note":{"type":["string","null"]},"amountMinor":{"type":"string","pattern":"^\\d+$"},"currency":{"type":"string","minLength":3,"maxLength":3},"status":{"type":"string","enum":["verified","pending_verification"]},"recordedByName":{"type":["string","null"]},"verifiedByName":{"type":["string","null"]},"paidAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["paymentId","receiptNumber","bookingId","guestName","listingCode","propertyName","senderName","note","amountMinor","currency","status","recordedByName","verifiedByName","paidAt","createdAt"],"additionalProperties":false},"PaymentAttachmentUploadResponse":{"type":"object","properties":{"objectKey":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["objectKey","uploadUrl","requiredHeaders"],"additionalProperties":false},"AttachPaymentScreenshotResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"SplitPaymentTransfersResponse":{"type":"object","properties":{"paymentIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"totalMinor":{"type":"string"}},"required":["paymentIds","totalMinor"],"additionalProperties":false},"StrandedPaymentsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/StrandedPaymentRow"}}},"required":["items"],"additionalProperties":false},"StrandedPaymentRow":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"method":{"type":"string"},"inquiryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"inquiryReference":{"type":"string"},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingReference":{"type":"string"},"legCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"quotedAmountMinor":{"type":["string","null"]},"advanceAmountMinor":{"description":"What the inquiry row says now — the figure the pre-fix convert overwrote.","type":["string","null"]},"onPropertyAmountMinor":{"type":["string","null"]},"agreedAdvanceMinor":{"description":"What the quote asked for, recovered from the conversion audit row.","type":["string","null"]},"agreedOnPropertyMinor":{"type":["string","null"]},"blockedReason":{"description":"Null when repairable; otherwise the machine reason it is not (e.g. a group).","type":["string","null"]}},"required":["paymentId","amountMinor","currency","method","inquiryId","inquiryReference","bookingId","bookingReference","legCount","quotedAmountMinor","advanceAmountMinor","onPropertyAmountMinor","agreedAdvanceMinor","agreedOnPropertyMinor","blockedReason"],"additionalProperties":false},"RepairStrandedPaymentResponse":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"journalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"verifiedAmountMinor":{"type":"string"},"advanceAmountMinor":{"type":["string","null"]},"onPropertyAmountMinor":{"type":["string","null"]},"advanceRestored":{"type":"boolean","description":"True when the agreed advance was recovered from the conversion audit row and put back."}},"required":["paymentId","bookingId","journalEntryId","verifiedAmountMinor","advanceAmountMinor","onPropertyAmountMinor","advanceRestored"],"additionalProperties":false},"PaymentAttachmentViewUrlResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","url","expiresInSeconds"],"additionalProperties":false},"PaymentsWithAttachmentsResponse":{"type":"object","properties":{"payments":{"type":"array","items":{"$ref":"#/components/schemas/PaymentWithAttachmentsView"}},"refunds":{"type":"array","items":{"$ref":"#/components/schemas/RefundWithAttachmentsView"},"description":"The booking's refunds, newest first, each with the proofs that NAME it (0393). Always empty for an inquiry: `refund.booking_id` is NOT NULL and there is no inquiry_id, because a refund reverses a verified payment against a stay."}},"required":["payments","refunds"],"additionalProperties":false},"PaymentWithAttachmentsView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"method":{"type":"string"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"currency":{"type":"string","minLength":3,"maxLength":3},"status":{"type":"string"},"txnRef":{"type":["string","null"]},"senderName":{"type":["string","null"]},"paidAt":{"type":["string","null"]},"createdAt":{"type":"string"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/PaymentAttachmentView"}}},"required":["id","method","amountMinor","currency","status","txnRef","senderName","paidAt","createdAt","attachments"],"additionalProperties":false},"PaymentAttachmentView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["guest_proof","operator_receipt","refund_proof","extension_proof"]},"contentType":{"type":"string"},"uploadedAt":{"type":"string","description":"When the screenshot was attached (ISO-8601)."},"uploadedByKind":{"type":"string","enum":["staff","guest"],"description":"staff = a signed-in operator (see `uploadedBy`); guest = the public quotation link."},"uploadedBy":{"description":"The operator who attached it. Null for a guest upload, or when the name is unknown.","type":["string","null"]}},"required":["id","kind","contentType","uploadedAt","uploadedByKind","uploadedBy"],"additionalProperties":false},"RefundWithAttachmentsView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"currency":{"type":"string","minLength":3,"maxLength":3},"status":{"type":"string","description":"requested | paid | rejected. Only `paid` moved money."},"reason":{"type":"string","description":"The maker's mandatory reason - a refund is never silent."},"createdAt":{"type":"string"},"decidedAt":{"description":"When it was paid or rejected; null while it still awaits a decision.","type":["string","null"]},"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The payment this refund reverses - the row it sits under in the tab."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/PaymentAttachmentView"}}},"required":["id","amountMinor","currency","status","reason","createdAt","decidedAt","paymentId","attachments"],"additionalProperties":false},"ListVerificationsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/VerificationQueueItem"}},"phases":{"$ref":"#/components/schemas/VerificationPhaseCounts"}},"required":["items","phases"],"additionalProperties":false},"VerificationQueueItem":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"bookingReference":{"type":"string"},"bookingStatus":{"type":"string"},"checkIn":{"type":"string"},"checkOut":{"type":"string"},"guestName":{"type":["string","null"]},"status":{"type":"string"},"idKind":{"type":["string","null"]},"nationality":{"type":["string","null"]},"docNumberMasked":{"type":["string","null"]},"docNumber":{"type":["string","null"]},"docsReady":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"verifiedAt":{"type":["string","null"]},"revokedAt":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["id","bookingId","bookingReference","bookingStatus","checkIn","checkOut","guestName","status","idKind","nationality","docNumberMasked","docNumber","docsReady","verifiedAt","revokedAt","note"],"additionalProperties":false},"VerificationPhaseCounts":{"type":"object","properties":{"awaiting":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"review":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"verified":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"closed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["awaiting","review","verified","closed"],"additionalProperties":false},"VerificationDetailResponse":{"type":"object","properties":{"verification":{"$ref":"#/components/schemas/VerificationView"},"booking":{"type":"object","properties":{"id":{"type":"string"},"reference":{"type":"string"},"status":{"type":"string"},"checkIn":{"type":"string"},"checkOut":{"type":"string"},"guestName":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"listingCode":{"type":["string","null"]}},"required":["id","reference","status","checkIn","checkOut","guestName","propertyName","listingCode"],"additionalProperties":false},"trail":{"type":"array","items":{"$ref":"#/components/schemas/VerificationTrailEntry"}},"priorVerified":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"bookingReference":{"type":["string","null"]},"idKind":{"type":["string","null"]},"docNumberMasked":{"type":["string","null"]},"verifiedAt":{"type":["string","null"]}},"required":["id","bookingId","bookingReference","idKind","docNumberMasked","verifiedAt"],"additionalProperties":false}},"carriedFrom":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"bookingReference":{"type":["string","null"]}},"required":["id","bookingReference"],"additionalProperties":false},{"type":"null"}]}},"required":["verification","booking","trail","priorVerified","carriedFrom"],"additionalProperties":false},"VerificationView":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"guestId":{"type":["string","null"]},"status":{"type":"string"},"idKind":{"type":["string","null"]},"nationality":{"type":["string","null"]},"docNumberMasked":{"description":"The masked identity number (last 4) — kept for compact displays.","type":["string","null"]},"docNumber":{"description":"The FULL identity number (owner 2026-07-07) — operator view surfaces only; never in audit/events.","type":["string","null"]},"verifiedAt":{"type":["string","null"]},"revokedAt":{"type":["string","null"]},"revokedReason":{"type":["string","null"]},"note":{"type":["string","null"]},"guestName":{"description":"Who this check covers (owner 2026-07-07) — null = the booking primary guest.","type":["string","null"]},"documents":{"type":"array","items":{"$ref":"#/components/schemas/VerificationDocumentView"}}},"required":["id","bookingId","guestId","status","idKind","nationality","docNumberMasked","docNumber","verifiedAt","revokedAt","revokedReason","note","guestName","documents"],"additionalProperties":false},"VerificationDocumentView":{"type":"object","properties":{"id":{"type":"string"},"docKind":{"type":"string","enum":["cnic_front","cnic_back","passport","passport_back","mrc","national_id_front","national_id_back"]},"uploadStatus":{"type":"string"},"contentType":{"type":"string"}},"required":["id","docKind","uploadStatus","contentType"],"additionalProperties":false},"VerificationTrailEntry":{"type":"object","properties":{"action":{"type":"string"},"actorType":{"type":"string"},"actorLabel":{"type":"string"},"actorName":{"type":["string","null"]},"occurredAt":{"type":"string"}},"required":["action","actorType","actorLabel","actorName","occurredAt"],"additionalProperties":false},"VerificationShareResponse":{"type":"object","properties":{"token":{"type":"string","description":"The share token; the link is /id/{token}."},"url":{"type":"string","description":"The absolute link to send the guest. Composed SERVER-side so it can carry the tenant's own verified booking-site domain when they have one, falling back to the platform origin."},"expiresAt":{"type":"string","description":"When the link stops working, ISO-8601."},"submittedAt":{"description":"When the guest submitted, or null if they have not yet.","type":["string","null"]}},"required":["token","url","expiresAt","submittedAt"],"additionalProperties":false},"BankAccountListResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BankAccountView"}}},"required":["items"],"additionalProperties":false},"BankAccountView":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","minLength":1,"maxLength":120,"description":"The operator's own name for the account. NEVER shown to a guest."},"bankName":{"type":"string","minLength":1,"maxLength":120,"description":"e.g. HBL, Meezan."},"accountTitle":{"type":"string","minLength":1,"maxLength":160,"description":"The name the account is held in."},"accountNumber":{"type":"string","minLength":1,"maxLength":64},"iban":{"type":["string","null"]},"swift":{"type":["string","null"]},"branch":{"type":["string","null"]},"notes":{"type":["string","null"]},"details":{"type":"string"},"propertyIds":{"type":"array","items":{"type":"string"},"description":"The properties assigned to this account, ordered by property name."},"propertyNames":{"type":"array","items":{"type":"string"},"description":"Index-aligned with `propertyIds` — element i names property i."}},"required":["id","label","bankName","accountTitle","accountNumber","iban","swift","branch","notes","details","propertyIds","propertyNames"],"additionalProperties":false},"ArchiveBankAccountResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"GetVerificationResponse":{"type":"object","properties":{"verifications":{"type":"array","items":{"$ref":"#/components/schemas/VerificationView"}}},"required":["verifications"],"additionalProperties":false},"RequestVerificationDocUploadResponse":{"type":"object","properties":{"documentId":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["documentId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmVerificationDocUploadResponse":{"type":"object","properties":{"documentId":{"type":"string"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"verificationStatus":{"type":"string"}},"required":["documentId","uploadStatus","byteSize","verificationStatus"],"additionalProperties":false},"MintVerificationDocViewUrlResponse":{"type":"object","properties":{"documentId":{"type":"string"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["documentId","url","expiresInSeconds"],"additionalProperties":false},"DeleteVerificationResponse":{"type":"object","properties":{"deletedId":{"type":"string"},"liveChecksRemaining":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["deletedId","liveChecksRemaining"],"additionalProperties":false},"WaiveVerificationResponse":{"type":"object","properties":{"bookingStatus":{"type":"string"}},"required":["bookingStatus"],"additionalProperties":false},"CalendarResponse":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"properties":{"type":"array","items":{"$ref":"#/components/schemas/CalendarPropertyView"}},"listings":{"type":"array","items":{"$ref":"#/components/schemas/CalendarListingView"}},"bookings":{"type":"array","items":{"$ref":"#/components/schemas/CalendarBookingView"}},"holds":{"type":"array","items":{"$ref":"#/components/schemas/CalendarHoldView"}},"blocks":{"type":"array","items":{"$ref":"#/components/schemas/ListingBlockView"}},"cleanings":{"type":"array","items":{"$ref":"#/components/schemas/CalendarCleaningView"}},"seatScoped":{"type":"boolean"}},"required":["from","to","properties","listings","bookings","holds","blocks","cleanings","seatScoped"],"additionalProperties":false},"CalendarPropertyView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"code":{"type":"string"}},"required":["id","name","code"],"additionalProperties":false},"CalendarListingView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeName":{"type":"string"},"isActive":{"type":"boolean"},"prepDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"parentListingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The containing (parent) listing, or null for a root — the calendar nesting edge."},"childOccupancyPolicy":{"type":"string","enum":["coexist","exclusive"],"description":"How this listing's direct children interact (coexist = independent; exclusive = one at a time)."},"prepSpans":{"type":"array","items":{"$ref":"#/components/schemas/CalendarPrepSpan"}},"checkInTime":{"type":"string","description":"Effective check-in clock time (HH:MM)."},"checkOutTime":{"type":"string","description":"Effective checkout clock time (HH:MM)."},"nightlyRateMinor":{"description":"The resolved nightly base rate (listing ?? type ?? property), bigint minor units as a string — the per-day rate strip. Absent = unpriced.","type":"string"},"rateCurrency":{"description":"ISO-4217 currency of nightlyRateMinor (the resolving rung’s paired currency).","type":"string"},"weekendRateMinor":{"description":"What a FRIDAY, SATURDAY or SUNDAY night costs — the base rate with the resolved weekend percentage applied, rounded server-side. ABSENT when there is no weekend pricing (or it resolves to the same amount); the client uses it for weekend cells when present.","type":"string"},"dateRates":{"description":"Per-DATE nightly overrides in the window (sparse — only SET nights). Each wins over the base rate for that night; the client resolves override ?? nightlyRateMinor per cell.","type":"array","items":{"type":"object","properties":{"night":{"type":"string","description":"The night (date-only ISO)."},"rateMinor":{"type":"string","description":"The per-date nightly rate (minor units)."},"currency":{"description":"ISO-4217 currency.","type":"string"}},"required":["night","rateMinor"],"additionalProperties":false}},"ruleRates":{"description":"Nights a PRICE RULE moves, priced one night at a time (0431). Sparse: only nights a rule changed. The client resolves dateRate ?? ruleRate ?? weekend/base per cell.","type":"array","items":{"type":"object","properties":{"night":{"type":"string","description":"The night (date-only ISO)."},"rateMinor":{"type":"string","description":"The rule-adjusted price (minor units)."},"rules":{"type":"array","items":{"type":"string"},"description":"The rules that applied, by name."}},"required":["night","rateMinor","rules"],"additionalProperties":false}},"stopSellNights":{"description":"Channel-closed (stop-sell) nights in the window — the OTA cannot sell them; direct bookings remain possible. Sparse: only closed nights appear.","type":"array","items":{"type":"string"}},"channelRates":{"description":"0148 — the listing's per-channel pricing lanes (each in its own currency; never converted). Drives the calendar's price-source switcher.","type":"array","items":{"type":"object","properties":{"channelKey":{"type":"string","description":"The lane token ('airbnb', …)."},"rateMinor":{"type":"string","description":"The lane base nightly rate (minor units)."},"currency":{"type":"string","description":"The lane's OWN ISO-4217 currency."}},"required":["channelKey","rateMinor","currency"],"additionalProperties":false}},"channelDateRates":{"description":"0148 — the lanes' sparse per-date overrides in the window; a cell resolves override ?? lane base for the chosen lane.","type":"array","items":{"type":"object","properties":{"channelKey":{"type":"string"},"night":{"type":"string","description":"The night (date-only ISO)."},"rateMinor":{"type":"string","description":"The per-date lane rate (minor units)."}},"required":["channelKey","night","rateMinor"],"additionalProperties":false}},"leadPhotoUrl":{"description":"A short-lived presigned GET url for the unit's lead photo (absent when none).","type":"string"},"icalPath":{"description":"The per-listing iCal feed path (the token in the path IS the feed auth) — projected in only for listing:manage holders.","type":"string"}},"required":["id","propertyId","listingCode","listingTypeId","listingTypeName","isActive","prepDays","parentListingId","childOccupancyPolicy","prepSpans","checkInTime","checkOutTime"],"additionalProperties":false},"CalendarPrepSpan":{"type":"object","properties":{"start":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"end":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["start","end"],"additionalProperties":false},"CalendarBookingView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Where the stay ends: the early-departure day when the guest left early, else the booked check-out."},"bookedCheckOut":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}],"description":"The booked check-out, set only when the guest left early (checkOut is then the departure day)."},"status":{"type":"string"},"guestName":{"type":["string","null"]},"guestPhone":{"type":["string","null"]},"channel":{"type":"string"},"source":{"type":"string"},"adults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"children":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"infants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalAmountMinor":{"type":"string"},"currency":{"type":"string"},"paidAmountMinor":{"type":"string"},"channelReservationUrl":{"type":["string","null"]},"channelPhoneLast4":{"type":["string","null"]}},"required":["id","listingId","checkIn","checkOut","bookedCheckOut","status","guestName","guestPhone","channel","source","adults","children","infants","pets","totalAmountMinor","currency","paidAmountMinor","channelReservationUrl","channelPhoneLast4"],"additionalProperties":false},"CalendarHoldView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"inquiryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"nightFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"nightTo":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"guestName":{"type":["string","null"]},"guestPhone":{"type":["string","null"]},"adults":{"type":"integer","minimum":0,"maximum":9007199254740991},"children":{"type":"integer","minimum":0,"maximum":9007199254740991},"infants":{"type":"integer","minimum":0,"maximum":9007199254740991},"pets":{"type":"integer","minimum":0,"maximum":9007199254740991},"channel":{"type":["string","null"]},"source":{"type":["string","null"]},"status":{"type":["string","null"]},"quotedAmountMinor":{"type":["string","null"]},"advanceAmountMinor":{"type":["string","null"]},"currency":{"type":["string","null"]}},"required":["id","listingId","inquiryId","nightFrom","nightTo","expiresAt","guestName","guestPhone","adults","children","infants","pets","channel","source","status","quotedAmountMinor","advanceAmountMinor","currency"],"additionalProperties":false},"ListingBlockView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"kind":{"type":"string","enum":["maintenance","owner_use","renovation","other"]},"note":{"type":["string","null"]},"startTime":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]},"endTime":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}]}},"required":["id","listingId","startDate","endDate","kind","note","startTime","endTime"],"additionalProperties":false},"CalendarCleaningView":{"type":"object","properties":{"id":{"type":"string"},"listingId":{"type":"string"},"status":{"type":"string"},"assignedTo":{"type":["string","null"]},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"startTime":{"type":["string","null"]},"endTime":{"type":["string","null"]}},"required":["id","listingId","status","assignedTo","startDate","endDate","startTime","endTime"],"additionalProperties":false},"ListingBlockResponse":{"type":"object","properties":{"block":{"$ref":"#/components/schemas/ListingBlockView"}},"required":["block"],"additionalProperties":false},"ListCleaningTasksResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CleaningTaskView"}},"scopeAll":{"type":"boolean","description":"True = the whole tenant queue (dispatcher); false = own tasks only."},"pulse":{"$ref":"#/components/schemas/TurnoverPulse"}},"required":["items","scopeAll","pulse"],"additionalProperties":false},"CleaningTaskView":{"type":"object","properties":{"id":{"type":"string"},"listingId":{"type":"string"},"bookingId":{"type":["string","null"]},"assignmentSeq":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string","enum":["unassigned","assigned","in_progress","completed","reassigned","aborted"]},"priority":{"type":"string","enum":["normal","urgent"]},"isSameDayTurnover":{"type":"boolean"},"assignedTo":{"type":"string"},"assignedBy":{"type":["string","null"]},"assignedByType":{"type":"string"},"assignedAt":{"type":"string"},"startedAt":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"completedBy":{"type":["string","null"]},"abortedAt":{"type":["string","null"]},"abortedReason":{"type":["string","null"]},"beforeEvidenceSkipReason":{"description":"Why the clean STARTED without a before-cleaning photo/video (0396). Null when one was filed.","type":["string","null"]},"afterEvidenceSkipReason":{"description":"Why the clean was MARKED CLEANED without an after-cleaning photo/video (0396). Null when one was filed.","type":["string","null"]},"deadlineAt":{"type":["string","null"]},"deadlineMissedAt":{"type":["string","null"]},"note":{"type":["string","null"]},"kind":{"type":"string","enum":["turnover","stayover","deep"],"description":"0441: a turnover, or a stayover / deep clean a property cleaning rule planned."},"photos":{"type":"array","items":{"$ref":"#/components/schemas/CleaningPhotoView"}},"listingCode":{"type":["string","null"]},"propertyId":{"type":["string","null"]},"bookingReference":{"type":["string","null"]}},"required":["id","listingId","bookingId","assignmentSeq","status","priority","isSameDayTurnover","assignedTo","assignedBy","assignedByType","assignedAt","startedAt","completedAt","completedBy","abortedAt","abortedReason","beforeEvidenceSkipReason","afterEvidenceSkipReason","deadlineAt","deadlineMissedAt","note","kind","photos","listingCode","propertyId","bookingReference"],"additionalProperties":false},"CleaningPhotoView":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["before","after"]},"uploadStatus":{"type":"string"},"contentType":{"type":"string"}},"required":["id","kind","uploadStatus","contentType"],"additionalProperties":false},"TurnoverPulse":{"type":"object","properties":{"dirty":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"inCleaning":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"urgent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"awaitingInspection":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"NULL = the caller holds no inspection:record — withheld, not zero."},"openDamage":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"NULL = the caller holds no inspection:record — withheld, not zero."}},"required":["dirty","inCleaning","urgent","awaitingInspection","openDamage"],"additionalProperties":false},"RequestCleaningPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["photoId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmCleaningPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","uploadStatus","byteSize"],"additionalProperties":false},"MintCleaningPhotoViewUrlResponse":{"type":"object","properties":{"photoId":{"type":"string"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","url","expiresInSeconds"],"additionalProperties":false},"RemovePhotoResponse":{"type":"object","properties":{"photoId":{"type":"string"},"removed":{"type":"boolean","const":true}},"required":["photoId","removed"],"additionalProperties":false},"ListInspectionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InspectionView"}}},"required":["items"],"additionalProperties":false},"InspectionView":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"listingId":{"type":"string"},"round":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string","enum":["pending_inspection","clear","damage_found","extra_cleaning_required","item_missing","escalated","resolved"]},"inspectedBy":{"type":["string","null"]},"inspectedAt":{"type":["string","null"]},"notes":{"type":["string","null"]},"listingCode":{"type":["string","null"]},"propertyId":{"type":["string","null"]},"bookingReference":{"type":["string","null"]}},"required":["id","bookingId","listingId","round","status","inspectedBy","inspectedAt","notes","listingCode","propertyId","bookingReference"],"additionalProperties":false},"RecordInspectionFindingResponse":{"type":"object","properties":{"inspection":{"$ref":"#/components/schemas/InspectionView"},"damageReport":{"anyOf":[{"$ref":"#/components/schemas/DamageReportView"},{"type":"null"}]}},"required":["inspection","damageReport"],"additionalProperties":false},"RequestDamagePhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["photoId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmDamagePhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","uploadStatus","byteSize"],"additionalProperties":false},"MintDamagePhotoViewUrlResponse":{"type":"object","properties":{"photoId":{"type":"string"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","url","expiresInSeconds"],"additionalProperties":false},"RequestInspectionPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["photoId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmInspectionPhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","uploadStatus","byteSize"],"additionalProperties":false},"MintInspectionPhotoViewUrlResponse":{"type":"object","properties":{"photoId":{"type":"string"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","url","expiresInSeconds"],"additionalProperties":false},"MaintenanceBoard":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MaintenanceTicketView"}},"seesAll":{"type":"boolean"},"me":{"type":"string"},"places":{"type":"array","items":{"type":"object","properties":{"propertyId":{"type":"string"},"propertyName":{"type":"string"},"units":{"type":"array","items":{"type":"object","properties":{"listingId":{"type":"string"},"code":{"type":"string"}},"required":["listingId","code"],"additionalProperties":false}}},"required":["propertyId","propertyName","units"],"additionalProperties":false}}},"required":["items","seesAll","me","places"],"additionalProperties":false},"MaintenanceTicketView":{"type":"object","properties":{"id":{"type":"string"},"propertyId":{"type":"string"},"propertyName":{"type":["string","null"]},"listingId":{"type":["string","null"]},"listingCode":{"type":["string","null"]},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["open","in_progress","on_hold","resolved","cancelled"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"assignedTo":{"type":["string","null"]},"reportedBy":{"type":"string"},"resolutionNote":{"type":["string","null"]},"resolvedAt":{"type":["string","null"]},"resolvedBy":{"type":["string","null"]},"expenseId":{"type":["string","null"]},"expense":{"anyOf":[{"$ref":"#/components/schemas/MaintenanceLinkedExpense"},{"type":"null"}]},"bookingId":{"type":["string","null"]},"booking":{"anyOf":[{"$ref":"#/components/schemas/MaintenanceLinkedBooking"},{"type":"null"}]},"photoCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","propertyId","propertyName","listingId","listingCode","title","description","status","priority","assignedTo","reportedBy","resolutionNote","resolvedAt","resolvedBy","expenseId","expense","bookingId","booking","photoCount","createdAt","updatedAt"],"additionalProperties":false},"MaintenanceLinkedExpense":{"type":"object","properties":{"id":{"type":"string"},"incurredOn":{"type":"string"},"amountMinor":{"type":"string","description":"Minor units as a decimal string."},"currency":{"type":"string"},"vendor":{"type":["string","null"]},"memo":{"type":["string","null"]}},"required":["id","incurredOn","amountMinor","currency","vendor","memo"],"additionalProperties":false},"MaintenanceLinkedBooking":{"type":"object","properties":{"id":{"type":"string"},"referenceCode":{"type":"string"},"checkIn":{"type":"string"},"checkOut":{"type":"string"},"listingCode":{"type":["string","null"]}},"required":["id","referenceCode","checkIn","checkOut","listingCode"],"additionalProperties":false},"MaintenanceTicketDetail":{"type":"object","properties":{"ticket":{"$ref":"#/components/schemas/MaintenanceTicketView"},"photos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"contentType":{"type":"string"},"url":{"type":"string"},"removable":{"type":"boolean"}},"required":["id","contentType","url","removable"],"additionalProperties":false}},"linkOptions":{"anyOf":[{"type":"object","properties":{"expenses":{"type":"array","items":{"$ref":"#/components/schemas/MaintenanceLinkedExpense"}},"bookings":{"type":"array","items":{"$ref":"#/components/schemas/MaintenanceLinkedBooking"}}},"required":["expenses","bookings"],"additionalProperties":false},{"type":"null"}]}},"required":["ticket","photos","linkOptions"],"additionalProperties":false},"ResolveMaintenanceTicketResponse":{"type":"object","properties":{"ticket":{"$ref":"#/components/schemas/MaintenanceTicketView"},"unitMadeReady":{"type":"boolean"}},"required":["ticket","unitMadeReady"],"additionalProperties":false},"RequestMaintenancePhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["photoId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmMaintenancePhotoUploadResponse":{"type":"object","properties":{"photoId":{"type":"string"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","uploadStatus","byteSize"],"additionalProperties":false},"MintMaintenancePhotoViewUrlResponse":{"type":"object","properties":{"photoId":{"type":"string"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["photoId","url","expiresInSeconds"],"additionalProperties":false},"ListingLockCodesResponse":{"type":"object","properties":{"listingId":{"type":"string"},"codes":{"type":"array","items":{"$ref":"#/components/schemas/ListingLockCodeStatusView"}}},"required":["listingId","codes"],"additionalProperties":false},"ListingLockCodeStatusView":{"type":"object","properties":{"audience":{"type":"string"},"isSet":{"type":"boolean"},"maskedCode":{"type":["string","null"]},"updatedAt":{"type":["string","null"]}},"required":["audience","isSet","maskedCode","updatedAt"],"additionalProperties":false},"BookingLockCodesResponse":{"type":"object","properties":{"bookingId":{"type":"string"},"lockMode":{"type":"string"},"audiences":{"type":"array","items":{"$ref":"#/components/schemas/BookingAudienceGateView"}},"relays":{"type":"array","items":{"$ref":"#/components/schemas/LockCodeRelayView"}},"stayCodes":{"type":"array","items":{"$ref":"#/components/schemas/StayLockCodeStatusView"}}},"required":["bookingId","lockMode","audiences","relays","stayCodes"],"additionalProperties":false},"BookingAudienceGateView":{"type":"object","properties":{"audience":{"type":"string"},"gateOk":{"type":"boolean"},"gateReason":{"type":["string","null"]},"codeSet":{"type":"boolean"},"relayStatus":{"type":["string","null"]}},"required":["audience","gateOk","gateReason","codeSet","relayStatus"],"additionalProperties":false},"LockCodeRelayView":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"listingId":{"type":"string"},"audience":{"type":"string"},"status":{"type":"string"},"scheduledFor":{"type":["string","null"]},"armedAt":{"type":["string","null"]},"heldReason":{"type":["string","null"]},"relayedToPocAt":{"type":["string","null"]},"handedToGuestAt":{"type":["string","null"]},"armedByRule":{"type":["string","null"]},"relayedToPoc":{"anyOf":[{"$ref":"#/components/schemas/LockCodeRelayActor"},{"type":"null"}]},"handedToGuest":{"anyOf":[{"$ref":"#/components/schemas/LockCodeRelayActor"},{"type":"null"}]},"listingCode":{"type":["string","null"]},"bookingReference":{"type":["string","null"]}},"required":["id","bookingId","listingId","audience","status","scheduledFor","armedAt","heldReason","relayedToPocAt","handedToGuestAt","armedByRule","relayedToPoc","handedToGuest","listingCode","bookingReference"],"additionalProperties":false},"LockCodeRelayActor":{"type":"object","properties":{"actorLabel":{"type":"string"},"actorName":{"type":["string","null"]}},"required":["actorLabel","actorName"],"additionalProperties":false},"StayLockCodeStatusView":{"type":"object","properties":{"deviceName":{"type":["string","null"]},"role":{"type":"string"},"status":{"type":"string"},"validFrom":{"type":"string"},"validTo":{"type":"string"},"lastError":{"type":["string","null"]}},"required":["deviceName","role","status","validFrom","validTo","lastError"],"additionalProperties":false},"RevealLockCodeResponse":{"type":"object","properties":{"audience":{"type":"string"},"code":{"type":"string"},"relay":{"$ref":"#/components/schemas/LockCodeRelayView"}},"required":["audience","code","relay"],"additionalProperties":false},"HandLockCodeToGuestResponse":{"type":"object","properties":{"relay":{"$ref":"#/components/schemas/LockCodeRelayView"}},"required":["relay"],"additionalProperties":false},"ListReadyRelaysResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/LockCodeRelayView"}}},"required":["items"],"additionalProperties":false},"LockConnectionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/LockConnectionView"}}},"required":["items"],"additionalProperties":false},"LockConnectionView":{"type":"object","properties":{"id":{"type":"string"},"vendor":{"type":"string"},"label":{"type":"string"},"status":{"type":"string"},"lastError":{"type":["string","null"]},"lastSyncedAt":{"type":["string","null"]},"deviceCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","vendor","label","status","lastError","lastSyncedAt","deviceCount"],"additionalProperties":false},"DisconnectLockVendorResponse":{"type":"object","properties":{"disconnected":{"type":"boolean","const":true}},"required":["disconnected"],"additionalProperties":false},"VendorLocksResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/VendorLockView"}}},"required":["items"],"additionalProperties":false},"VendorLockView":{"type":"object","properties":{"externalId":{"type":"string"},"name":{"type":"string"},"batteryPct":{"type":["number","null"]}},"required":["externalId","name","batteryPct"],"additionalProperties":false},"ListingSmartLockResponse":{"type":"object","properties":{"listingId":{"type":"string"},"lockMode":{"type":"string"},"devices":{"type":"array","items":{"$ref":"#/components/schemas/LockDeviceView"}}},"required":["listingId","lockMode","devices"],"additionalProperties":false},"LockDeviceView":{"type":"object","properties":{"role":{"type":"string"},"connectionId":{"type":"string"},"connectionLabel":{"type":"string"},"vendor":{"type":"string"},"externalLockId":{"type":"string"},"deviceName":{"type":["string","null"]},"codeLength":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"batteryPct":{"type":["number","null"]},"batteryCheckedAt":{"type":["string","null"]}},"required":["role","connectionId","connectionLabel","vendor","externalLockId","deviceName","codeLength","batteryPct","batteryCheckedAt"],"additionalProperties":false},"ListGuestsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/GuestListView"}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"],"additionalProperties":false},"GuestListView":{"type":"object","properties":{"id":{"type":"string"},"fullName":{"type":"string"},"phone":{"type":["string","null"]},"email":{"type":["string","null"]},"whatsapp":{"type":["string","null"]},"nationality":{"type":["string","null"]},"source":{"type":["string","null"]},"isRepeat":{"type":"boolean"},"flags":{"$ref":"#/components/schemas/GuestFlagsView"},"stays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lifetimeValue":{"type":"string"},"averageNights":{"type":["number","null"]},"firstStayAt":{"type":["string","null"]},"averageRevenuePerStay":{"type":["string","null"]},"currency":{"type":["string","null"]},"idStatus":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["id","fullName","phone","email","whatsapp","nationality","source","isRepeat","flags","stays","lifetimeValue","averageNights","firstStayAt","averageRevenuePerStay","currency","idStatus","note"],"additionalProperties":false},"GuestFlagsView":{"type":"object","properties":{"vip":{"type":"boolean"},"watchlist":{"type":"boolean"},"longStay":{"type":"boolean"},"blacklisted":{"type":"boolean"},"blacklistReason":{"type":["string","null"]},"blacklistRemovalReason":{"type":["string","null"]}},"required":["vip","watchlist","longStay","blacklisted","blacklistReason","blacklistRemovalReason"],"additionalProperties":false},"GuestDetailResponse":{"type":"object","properties":{"id":{"type":"string"},"fullName":{"type":"string"},"phone":{"type":["string","null"]},"email":{"type":["string","null"]},"whatsapp":{"type":["string","null"]},"nationality":{"type":["string","null"]},"source":{"type":["string","null"]},"isRepeat":{"type":"boolean"},"flags":{"$ref":"#/components/schemas/GuestFlagsView"},"stays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lifetimeValue":{"type":"string"},"averageNights":{"type":["number","null"]},"firstStayAt":{"type":["string","null"]},"averageRevenuePerStay":{"type":["string","null"]},"currency":{"type":["string","null"]},"idStatus":{"type":["string","null"]},"note":{"type":["string","null"]},"stayHistory":{"type":"array","items":{"$ref":"#/components/schemas/GuestStayView"}},"staysByMonth":{"type":"array","items":{"$ref":"#/components/schemas/GuestStayMonthView"}},"firstBooking":{"anyOf":[{"$ref":"#/components/schemas/GuestFirstBookingView"},{"type":"null"}]},"verifications":{"type":"array","items":{"$ref":"#/components/schemas/GuestVerificationView"}},"reviews":{"type":"array","items":{"$ref":"#/components/schemas/GuestReviewView"}},"flagHistory":{"type":"array","items":{"$ref":"#/components/schemas/GuestFlagEventView"}}},"required":["id","fullName","phone","email","whatsapp","nationality","source","isRepeat","flags","stays","lifetimeValue","averageNights","firstStayAt","averageRevenuePerStay","currency","idStatus","note","stayHistory","staysByMonth","firstBooking","verifications","reviews","flagHistory"],"additionalProperties":false},"GuestStayView":{"type":"object","properties":{"bookingId":{"type":"string"},"referenceCode":{"type":"string"},"listingCode":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"checkIn":{"type":"string"},"checkOut":{"type":"string"},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string"},"channel":{"type":"string"},"upcoming":{"type":"boolean"}},"required":["bookingId","referenceCode","listingCode","propertyName","checkIn","checkOut","nights","status","channel","upcoming"],"additionalProperties":false},"GuestStayMonthView":{"type":"object","properties":{"month":{"type":"string"},"stays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"upcoming":{"type":"boolean"}},"required":["month","stays","upcoming"],"additionalProperties":false},"GuestFirstBookingView":{"type":"object","properties":{"bookingId":{"type":"string"},"referenceCode":{"type":"string"},"source":{"type":"string"},"checkIn":{"type":"string"},"status":{"type":"string"}},"required":["bookingId","referenceCode","source","checkIn","status"],"additionalProperties":false},"GuestVerificationView":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"bookingId":{"type":"string"},"referenceCode":{"type":"string"}},"required":["id","status","bookingId","referenceCode"],"additionalProperties":false},"GuestReviewView":{"type":"object","properties":{"id":{"type":"string"},"platform":{"type":"string"},"status":{"type":"string"},"rating":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"bookingId":{"type":"string"},"referenceCode":{"type":"string"}},"required":["id","platform","status","rating","bookingId","referenceCode"],"additionalProperties":false},"GuestFlagEventView":{"type":"object","properties":{"action":{"type":"string"},"flag":{"type":"string"},"on":{"type":"boolean"},"reason":{"type":["string","null"]},"actorType":{"type":"string"},"actorLabel":{"type":"string"},"actorName":{"type":["string","null"]},"occurredAt":{"type":"string"}},"required":["action","flag","on","reason","actorType","actorLabel","actorName","occurredAt"],"additionalProperties":false},"GuestDuplicatesResponse":{"type":"object","properties":{"groups":{"type":"array","items":{"$ref":"#/components/schemas/DuplicateGroup"}}},"required":["groups"],"additionalProperties":false},"DuplicateGroup":{"type":"object","properties":{"matchOn":{"type":"string","description":"Which field matched — `phone` / `whatsapp` / `email`."},"matchValue":{"type":"string","description":"The normalized shared value."},"guests":{"type":"array","items":{"$ref":"#/components/schemas/DuplicateGuestSummary"},"description":"The guests in this duplicate set."}},"required":["matchOn","matchValue","guests"],"additionalProperties":false},"DuplicateGuestSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The guest id."},"fullName":{"type":"string","description":"The guest name."},"phone":{"description":"The guest phone (as stored), or null.","type":["string","null"]},"email":{"description":"The guest email (as stored), or null.","type":["string","null"]}},"required":["id","fullName","phone","email"],"additionalProperties":false},"GuestMatchResponse":{"type":"object","properties":{"matches":{"type":"array","items":{"$ref":"#/components/schemas/GuestMatchView"}}},"required":["matches"],"additionalProperties":false},"GuestMatchView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"fullName":{"type":"string"},"phone":{"type":["string","null"]},"repeat":{"type":"boolean"},"verified":{"type":"boolean"},"vip":{"type":"boolean"},"flagged":{"type":"boolean"},"blacklisted":{"type":"boolean"},"blacklistReason":{"type":["string","null"]}},"required":["id","fullName","phone","repeat","verified","vip","flagged","blacklisted","blacklistReason"],"additionalProperties":false},"MergeGuestResponse":{"type":"object","properties":{"canonical":{"$ref":"#/components/schemas/GuestDetailResponse"},"reassigned":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"description":"Per-table count of records reassigned onto the canonical, summed across the whole set."},"mergedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many duplicates were absorbed. The UI reports THIS rather than counting successful requests itself — that client-side tally is what previously hid a partial merge."}},"required":["canonical","reassigned","mergedCount"],"additionalProperties":false},"ListReviewsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ReviewView"}},"kpis":{"$ref":"#/components/schemas/ReviewKpis"}},"required":["items","kpis"],"additionalProperties":false},"ReviewView":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"referenceCode":{"type":["string","null"]},"guestName":{"type":["string","null"]},"platform":{"type":"string"},"status":{"type":"string"},"rating":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"reviewText":{"type":["string","null"]},"requestedAt":{"type":["string","null"]},"receivedAt":{"type":["string","null"]},"provider":{"description":"C8 — the sync provider; null = a manually recorded review.","type":["string","null"]},"isHidden":{"type":"boolean","description":"Airbnb double-blind: veiled until the host reviews back."},"replyText":{"type":["string","null"]},"repliedAt":{"type":["string","null"]},"hostReviewed":{"type":"boolean"},"hostReviewedAt":{"type":["string","null"]}},"required":["id","bookingId","referenceCode","guestName","platform","status","rating","reviewText","requestedAt","receivedAt","provider","isHidden","replyText","repliedAt","hostReviewed","hostReviewedAt"],"additionalProperties":false},"ReviewKpis":{"type":"object","properties":{"avgRating":{"type":["number","null"]},"requestsSent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"received":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"responseRatePct":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"distribution":{"type":"object","properties":{"1":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"2":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"3":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"4":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"5":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["1","2","3","4","5"],"additionalProperties":false}},"required":["avgRating","requestsSent","received","responseRatePct","distribution"],"additionalProperties":false},"ListExtensionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ExtensionView"}},"kpis":{"$ref":"#/components/schemas/ExtensionKpis"}},"required":["items","kpis"],"additionalProperties":false},"ExtensionView":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"referenceCode":{"type":["string","null"]},"guestName":{"type":["string","null"]},"addedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"newCheckOut":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"paymentStatus":{"type":"string"},"status":{"type":"string"}},"required":["id","bookingId","referenceCode","guestName","addedNights","newCheckOut","amount","currency","paymentStatus","status"],"additionalProperties":false},"ExtensionKpis":{"type":"object","properties":{"activeRequests":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"approved":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"extraRevenue":{"type":"string"},"currency":{"type":["string","null"]}},"required":["activeRequests","approved","extraRevenue","currency"],"additionalProperties":false},"ExtensionOptionsResponse":{"type":"object","properties":{"addedNights":{"type":"array","items":{"type":"string"}},"sameUnitFree":{"type":"boolean"},"currentCheckOut":{"type":"string"},"guestId":{"type":["string","null"]},"guestName":{"type":["string","null"]},"currency":{"type":"string"},"channel":{"type":"string"},"source":{"type":"string"},"adults":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"children":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"infants":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pets":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"alternatives":{"type":"array","items":{"$ref":"#/components/schemas/FreeListingOption"}}},"required":["addedNights","sameUnitFree","currentCheckOut","guestId","guestName","currency","channel","source","adults","children","infants","pets","alternatives"],"additionalProperties":false},"FreeListingOption":{"type":"object","properties":{"listingId":{"type":"string"},"listingCode":{"type":"string"},"propertyId":{"type":"string"},"propertyName":{"type":"string"},"propertyCode":{"type":"string"},"listingTypeId":{"type":["string","null"]},"listingTypeName":{"type":["string","null"]}},"required":["listingId","listingCode","propertyId","propertyName","propertyCode","listingTypeId","listingTypeName"],"additionalProperties":false},"ListChannelStatusResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ChannelPropertyStatusView"}}},"required":["items"],"additionalProperties":false},"ChannelPropertyStatusView":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"mode":{"type":"string","enum":["unit","pool"]},"activeListings":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"mappedUnits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string","enum":["not_provisioned","partial","active","error"]},"modeLocked":{"type":"boolean","description":"True once channel sync is provisioned for this property — `mode` can no longer be changed (disconnect first)."},"lastError":{"type":["string","null"]},"lastSyncAt":{"type":["string","null"]},"distributionCurrency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"effectiveDistributionCurrency":{"type":"string","minLength":3,"maxLength":3},"paused":{"type":"boolean","description":"0439: hibernating, connected but offering its channels nothing to sell."},"units":{"type":"array","items":{"$ref":"#/components/schemas/ChannelUnitStatusView"}},"roomClasses":{"type":"array","items":{"$ref":"#/components/schemas/ChannelRoomClassStatusView"}}},"required":["propertyId","propertyName","mode","activeListings","mappedUnits","status","modeLocked","lastError","lastSyncAt","distributionCurrency","effectiveDistributionCurrency","paused","units","roomClasses"],"additionalProperties":false},"ChannelUnitStatusView":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"mapped":{"type":"boolean"},"status":{"type":["string","null"]},"lastSyncAt":{"type":["string","null"]},"roomTypeMapId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The mapped lane to steer pricing authority on; null when the unit is unmapped."},"rateAuthority":{"anyOf":[{"type":"string","enum":["internal","external"]},{"type":"null"}],"description":"Who owns this unit’s nightly price on the channel. external = a third-party pricing tool prices it on the OTA, so we push availability and stay rules but no rate. Null when unmapped."}},"required":["listingId","listingCode","mapped","status","lastSyncAt","roomTypeMapId","rateAuthority"],"additionalProperties":false},"ChannelRoomClassStatusView":{"type":"object","properties":{"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"unitCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"mapped":{"type":"boolean"},"pushedCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["listingTypeId","name","unitCount","mapped","pushedCount"],"additionalProperties":false},"ChannelLiveStatusResponse":{"type":"object","properties":{"provider":{"type":"string"},"checkedAt":{"type":"string"},"providerPropertiesSeen":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"truncated":{"type":"boolean"},"maps":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMapLiveStatusView"}}},"required":["provider","checkedAt","providerPropertiesSeen","truncated","maps"],"additionalProperties":false},"ChannelMapLiveStatusView":{"type":"object","properties":{"channelPropertyMapId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"externalPropertyId":{"type":"string"},"liveness":{"type":"string","enum":["present","missing","unknown"],"description":"present = the provider still lists it; missing = a COMPLETE sweep proved it gone; unknown = the sweep was truncated, so absence proves nothing. Never collapse 'unknown' into either of the others."},"liveTitle":{"type":["string","null"]},"providerInactive":{"type":"boolean"},"messagingApp":{"description":"Is the Messages & Reviews app installed AND active on this container? null = could not determine (never render as \"off\").","type":["boolean","null"]}},"required":["channelPropertyMapId","propertyId","listingId","externalPropertyId","liveness","liveTitle","providerInactive","messagingApp"],"additionalProperties":false},"EnableMessagingAppResponse":{"type":"object","properties":{"installed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"alreadyInstalled":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"blocked":{"type":"array","items":{"type":"object","properties":{"externalPropertyId":{"type":"string"},"byApp":{"type":"string"}},"required":["externalPropertyId","byApp"],"additionalProperties":false}},"failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["installed","alreadyInstalled","blocked","failures"],"additionalProperties":false},"DisableMessagingAppResponse":{"type":"object","properties":{"uninstalled":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"alreadyOff":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["uninstalled","alreadyOff","failures"],"additionalProperties":false},"EnableChannelSyncResult":{"type":"object","properties":{"provider":{"type":"string"},"mode":{"type":"string","enum":["unit","pool"]},"provisioned":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"alreadyMapped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reconciled":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"C9 — already-mapped room types whose capacity facts were re-pushed."},"markupPlansFailed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"0439: marked-up channels' own rate plans the provider refused here; the next markup save retries them."}},"required":["provider","mode","provisioned","alreadyMapped","reconciled","markupPlansFailed"],"additionalProperties":false},"GoogleReadinessResponse":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"ready":{"type":"boolean"},"blockerCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bookingLinks":{"type":"array","items":{"type":"object","properties":{"roomName":{"type":"string"},"url":{"type":"string"}},"required":["roomName","url"],"additionalProperties":false}},"items":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"ok":{"type":"boolean"},"locus":{"type":"string","enum":["workspace","channel_settings"]},"hint":{"type":"string"}},"required":["key","label","ok","locus","hint"],"additionalProperties":false}}},"required":["propertyId","propertyName","ready","blockerCount","bookingLinks","items"],"additionalProperties":false},"HostedConnectSessionResponse":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"DisableChannelSyncResponse":{"type":"object","properties":{"provider":{"type":"string"},"disabled":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Provider properties torn down + maps retired."}},"required":["provider","disabled"],"additionalProperties":false},"ChannelExtrasResponse":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"externalPropertyId":{"type":"string"},"scoreOverall":{"type":["number","null"]},"scoreCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"holdback":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["externalPropertyId","scoreOverall","scoreCount","holdback"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"SetChannelHoldbackResponse":{"type":"object","properties":{"holdback":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["holdback"],"additionalProperties":false},"SetDistributionCurrencyResponse":{"type":"object","properties":{"currency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]}},"required":["currency"],"additionalProperties":false},"UnitChannelsResponse":{"type":"object","properties":{"channels":{"type":"array","items":{"type":"object","properties":{"channelExternalId":{"type":"string"},"channelType":{"type":"string"},"title":{"type":"string"}},"required":["channelExternalId","channelType","title"],"additionalProperties":false}}},"required":["channels"],"additionalProperties":false},"UnitBookingPolicyResponse":{"type":"object","properties":{"policy":{"anyOf":[{"type":"string","enum":["instant","instant_well_reviewed","request_to_book"]},{"type":"null"}],"description":"Who may book without host approval; null when the OTA reports none."},"unmappedProviderValue":{"description":"A provider category we do not model — named rather than swallowed.","type":["string","null"]},"welcomeMessage":{"type":["string","null"]},"otaListingId":{"type":["string","null"]},"channelType":{"type":["string","null"]},"published":{"type":"boolean"},"known":{"type":"boolean","description":"False when there is nothing to report (unmapped, no channel, silent)."}},"required":["policy","unmappedProviderValue","welcomeMessage","otaListingId","channelType","published","known"],"additionalProperties":false},"SetSpanAvailabilityResponse":{"type":"object","properties":{"mode":{"type":"string","enum":["open","close"]},"lane":{"type":"string","enum":["stop_sell","rules"]},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"rulesTouched":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["mode","lane","nights","rulesTouched"],"additionalProperties":false},"SyncChannelUnitResponse":{"type":"object","properties":{"queued":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["queued"],"additionalProperties":false},"ChangeSyncModeResponse":{"type":"object","properties":{"provider":{"type":"string"},"mode":{"type":"string","enum":["unit","pool"]},"tornDown":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Provider properties torn down to make the change; 0 when nothing was provisioned."},"provisioned":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Provider properties re-provisioned in the NEW shape."},"reconnectRequired":{"type":"boolean","description":"A live setup was rebuilt underneath, so the Airbnb connection was detached and must be re-made."}},"required":["provider","mode","tornDown","provisioned","reconnectRequired"],"additionalProperties":false},"PushChannelContentResponse":{"type":"object","properties":{"properties":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"contentPushed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"roomTypesPushed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"photosPushed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"policiesAttached":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"facilitiesTagged":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"taxesPushed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"warnings":{"type":"array","items":{"type":"string"}}},"required":["properties","contentPushed","roomTypesPushed","photosPushed","policiesAttached","facilitiesTagged","taxesPushed","warnings"],"additionalProperties":false},"ListQuarantinedRevisionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ChannelRevisionView"}},"counts":{"type":"object","properties":{"open":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"applied":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"acked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"received":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"all":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["open","applied","acked","received","all"],"additionalProperties":false}},"required":["items","counts"],"additionalProperties":false},"ChannelRevisionView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"revisionExternalId":{"type":"string"},"bookingExternalId":{"type":"string"},"otaReservationCode":{"type":["string","null"]},"channel":{"anyOf":[{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo"]},{"type":"null"}],"description":"The OTA the revision came from (0439); null when it is not one we model."},"reason":{"type":["string","null"]},"receivedAt":{"type":"string"},"appliedBookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"status":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","revisionExternalId","bookingExternalId","otaReservationCode","channel","reason","receivedAt","appliedBookingId","status","updatedAt"],"additionalProperties":false},"RetryRevisionResponse":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"],"additionalProperties":false},"ListChannelSettingsResponse":{"type":"object","properties":{"channels":{"type":"array","items":{"$ref":"#/components/schemas/ChannelSettingView"}}},"required":["channels"],"additionalProperties":false},"ChannelSettingView":{"type":"object","properties":{"channel":{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo","google"]},"paymentCollector":{"anyOf":[{"type":"string","enum":["channel","property"]},{"type":"null"}],"description":"Who collects when a booking does not say: the workspace choice, else the channel default. Null for Google, whose stays arrive as direct bookings."},"paymentCollectorIsDefault":{"type":"boolean"},"markupBp":{"type":"integer","minimum":0,"maximum":10000},"markupAddMinor":{"type":"string","pattern":"^\\d+$","description":"The flat markup in `markupCurrency` minor units (bigint-safe string)."},"markupCurrency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]}},"required":["channel","paymentCollector","paymentCollectorIsDefault","markupBp","markupAddMinor","markupCurrency"],"additionalProperties":false},"ListChannelMarkupsResponse":{"type":"object","properties":{"markups":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMarkupView"}},"currencies":{"type":"array","items":{"type":"string","minLength":3,"maxLength":3},"description":"The currencies the live rate plans sell in: the ones a flat add can ride into."}},"required":["markups","currencies"],"additionalProperties":false},"ChannelMarkupView":{"type":"object","properties":{"channel":{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo","google"]},"markupBp":{"type":"integer","minimum":0,"maximum":10000},"markupAddMinor":{"type":"string","pattern":"^\\d+$"},"markupCurrency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]}},"required":["channel","markupBp","markupAddMinor","markupCurrency"],"additionalProperties":false},"SetChannelMarkupResponse":{"type":"object","properties":{"setting":{"$ref":"#/components/schemas/ChannelSettingView"},"plansCreated":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"plansFailed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"provisioned":{"type":"boolean","description":"False when the channel manager is not configured, so no rate plan was made."}},"required":["setting","plansCreated","plansFailed","provisioned"],"additionalProperties":false},"ChannelPricePreviewResponse":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"currency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"ownPlanChannels":{"type":"array","items":{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo","google"]}},"externallyPriced":{"type":"boolean","description":"An outside pricing tool prices this unit on its channels, so no price is sent."},"nights":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"basePlanMinor":{"type":["string","null"]},"channels":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":["string","null"]}}},"required":["date","basePlanMinor","channels"],"additionalProperties":false}}},"required":["listingId","currency","ownPlanChannels","externallyPriced","nights"],"additionalProperties":false},"SyncChannelsNowResponse":{"type":"object","properties":{"properties":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availabilityPushes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"restrictionPushes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"remaining":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Connected properties with changes still queued for the next worker sweep."}},"required":["properties","availabilityPushes","restrictionPushes","failures","remaining"],"additionalProperties":false},"ResendAllChannelsResponse":{"type":"object","properties":{"properties":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["properties","days"],"additionalProperties":false},"ChannelHibernationResponse":{"type":"object","properties":{"changed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["changed"],"additionalProperties":false},"ListingBaseRateView":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The listing (null when queried by type/property)."},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The listing type (if any)."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The property (null for a legacy tenant-wide type)."},"listingRateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"The UNIT-level override (minor units), or null."},"listingTypeRateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"The TYPE-level rate (minor units), or null."},"propertyRateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"The PROPERTY default (minor units), or null."},"effectiveRateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"The resolved nightly rate (listing ?? type ?? property), or null = unpriced."},"effectiveSource":{"type":"string","enum":["listing","listing_type","property","unpriced"],"description":"Which hierarchy level supplied the effective rate."},"listingRateCurrency":{"description":"The UNIT override's own currency, or null when unset — levels can hold MIXED currencies (e.g. a USD unit override over a PKR type rate); labels derive per level.","type":["string","null"]},"listingTypeRateCurrency":{"description":"The TYPE rate's own currency, or null when unset.","type":["string","null"]},"propertyRateCurrency":{"description":"The PROPERTY default's own currency, or null when unset.","type":["string","null"]},"currency":{"description":"The EFFECTIVE RATE’s currency, or null when unpriced.","type":["string","null"]},"baseCurrency":{"type":"string","description":"The TENANT base currency — always present, and the currency a write will be stamped with. Money-input LABELS derive from this: `currency` is null exactly when nothing is priced yet."},"listingLabel":{"description":"The unit's `listing_code` — what the dialog names as the SUBJECT of the rate it is setting. Null when the queried grain is not a listing.","type":["string","null"]},"listingTypeName":{"description":"The listing type's name, or null when not part of the queried grain.","type":["string","null"]},"propertyName":{"description":"The property's name, or null when not part of the queried grain.","type":["string","null"]},"listingWeekendAdjustBp":{"anyOf":[{"type":"integer","minimum":-10000,"maximum":50000},{"type":"null"}],"description":"The UNIT-level WEEKEND percentage in basis points (2000 = +20%), or null when unset."},"listingTypeWeekendAdjustBp":{"anyOf":[{"type":"integer","minimum":-10000,"maximum":50000},{"type":"null"}],"description":"The TYPE-level WEEKEND percentage (basis points), or null."},"propertyWeekendAdjustBp":{"anyOf":[{"type":"integer","minimum":-10000,"maximum":50000},{"type":"null"}],"description":"The PROPERTY-level WEEKEND percentage (basis points), or null."},"effectiveWeekendAdjustBp":{"anyOf":[{"type":"integer","minimum":-10000,"maximum":50000},{"type":"null"}],"description":"The resolved WEEKEND percentage (listing ?? type ?? property), or null = no weekend pricing."},"effectiveWeekendSource":{"type":"string","enum":["listing","listing_type","property","none"],"description":"Which hierarchy level supplied the weekend percentage."},"effectiveWeekendRateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}],"description":"What a Friday/Saturday/Sunday night costs: the effective rate with the effective percentage applied, rounded half-up. Server-computed; null exactly when the rate is."}},"required":["listingId","listingTypeId","propertyId","listingRateMinor","listingTypeRateMinor","propertyRateMinor","effectiveRateMinor","effectiveSource","listingRateCurrency","listingTypeRateCurrency","propertyRateCurrency","currency","baseCurrency","listingLabel","listingTypeName","propertyName","listingWeekendAdjustBp","listingTypeWeekendAdjustBp","propertyWeekendAdjustBp","effectiveWeekendAdjustBp","effectiveWeekendSource","effectiveWeekendRateMinor"],"additionalProperties":false},"SetBaseRateResponse":{"type":"object","properties":{"scope":{"type":"string","enum":["property","listing_type","listing"]},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"rateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}]}},"required":["scope","entityId","rateMinor"],"additionalProperties":false},"FxQuoteView":{"type":"object","properties":{"baseCurrency":{"type":"string","description":"The `from` currency, normalized."},"quoteCurrency":{"type":"string","description":"The `to` currency, normalized."},"rate":{"description":"The multiplier as a DECIMAL STRING (never a JSON number — the money rule): 1 base buys `rate` of quote. NULL = no rate is available, which is an ABSENT rate and never a guessed one.","type":["string","null"]},"rateDate":{"description":"The provider's own observation date (YYYY-MM-DD), or null.","type":["string","null"]},"source":{"description":"The provenance token to name on screen, or null.","type":["string","null"]}},"required":["baseCurrency","quoteCurrency","rate","rateDate","source"],"additionalProperties":false},"SetWeekendAdjustResponse":{"type":"object","properties":{"scope":{"type":"string","enum":["property","listing_type","listing"]},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"adjustBp":{"anyOf":[{"type":"integer","minimum":-10000,"maximum":50000},{"type":"null"}]}},"required":["scope","entityId","adjustBp"],"additionalProperties":false},"SetDateRateResponse":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"The count of nights written or cleared."},"rateMinor":{"anyOf":[{"type":"string","pattern":"^\\d{1,15}$"},{"type":"null"}]}},"required":["listingId","from","to","nights","rateMinor"],"additionalProperties":false},"AdjustDateRateResponse":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"adjustBp":{"type":"integer","minimum":-10000,"maximum":50000},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Nights actually re-priced."},"skippedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Nights with no price to take a percentage of — skipped, never written as 0."}},"required":["listingId","from","to","adjustBp","nights","skippedNights"],"additionalProperties":false},"AdjustChannelDateRateResponse":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channelKey":{"type":"string"},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"adjustBp":{"type":"integer","minimum":-10000,"maximum":50000},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skippedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Nights with no price to take a percentage of. Always 0 here (the lane is required), reported so both adjust responses read the same."}},"required":["listingId","channelKey","from","to","adjustBp","nights","skippedNights"],"additionalProperties":false},"ListChannelRatesResponse":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"grain":{"type":"string","enum":["listing","listing_type","property"]},"lanes":{"type":"array","items":{"$ref":"#/components/schemas/ChannelRateLaneView"}}},"required":["listingId","grain","lanes"],"additionalProperties":false},"ChannelRateLaneView":{"type":"object","properties":{"channelKey":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,30}$","description":"The sales-channel token ('airbnb', 'booking_com', …) — open vocabulary."},"rateMinor":{"type":"string","pattern":"^\\d+$","description":"The nightly rate in MINOR units (bigint-safe string)."},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"The lane's OWN currency (the channel's selling currency; never converted)."}},"required":["channelKey","rateMinor","currency"],"additionalProperties":false},"SetChannelRateResponse":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"grain":{"type":"string","enum":["listing","listing_type","property"]},"channelKey":{"type":"string"},"rateMinor":{"type":["string","null"]}},"required":["listingId","listingTypeId","propertyId","grain","channelKey","rateMinor"],"additionalProperties":false},"PushedRateResponse":{"type":"object","properties":{"rates":{"type":"array","items":{"type":"object","properties":{"channelKey":{"type":["string","null"]},"currency":{"type":"string"},"rateMinor":{"type":["string","null"]},"source":{"anyOf":[{"type":"string","enum":["channel_date_override","channel_lane","listing_date","listing_base","listing_type_base","property_base","price_rule"]},{"type":"null"}]},"night":{"type":"string"},"rateAuthority":{"type":"string","enum":["internal","external"]}},"required":["channelKey","currency","rateMinor","source","night","rateAuthority"],"additionalProperties":false}}},"required":["rates"],"additionalProperties":false},"SetChannelDateRatesResponse":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channelKey":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"rateMinor":{"type":["string","null"]}},"required":["listingId","channelKey","from","to","nights","rateMinor"],"additionalProperties":false},"SetChannelRateAuthorityResponse":{"type":"object","properties":{"roomTypeMapId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"currency":{"type":"string"},"authority":{"type":"string","enum":["internal","external"]},"previousAuthority":{"type":"string","enum":["internal","external"]},"dirtiedSpans":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"ARI spans enqueued so the change actually reaches the provider. 0 when the lane already had this authority (a no-op writes nothing)."}},"required":["roomTypeMapId","listingId","listingTypeId","currency","authority","previousAuthority","dirtiedSpans"],"additionalProperties":false},"ListDateRestrictionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/DateRestrictionView"}}},"required":["items"],"additionalProperties":false},"DateRestrictionView":{"type":"object","properties":{"night":{"type":"string"},"minStay":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxStay":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"closedToArrival":{"type":["boolean","null"]},"closedToDeparture":{"type":["boolean","null"]},"stopSell":{"type":["boolean","null"]}},"required":["night","minStay","maxStay","closedToArrival","closedToDeparture","stopSell"],"additionalProperties":false},"SetDateRestrictionResponse":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"from":{"type":"string"},"to":{"type":"string"},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cleared":{"type":"boolean"}},"required":["listingId","from","to","nights","cleared"],"additionalProperties":false},"PriceRulesPage":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/PriceRuleView"}},"sendToChannels":{"type":"boolean"},"currency":{"type":"string"},"targets":{"type":"object","properties":{"properties":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"types":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id","name","propertyId"],"additionalProperties":false}},"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"code":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","code","propertyId","listingTypeId"],"additionalProperties":false}}},"required":["properties","types","listings"],"additionalProperties":false}},"required":["rules","sendToChannels","currency","targets"],"additionalProperties":false},"PriceRuleView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"scope":{"$ref":"#/components/schemas/PriceRuleScope"},"scopeLabel":{"type":["string","null"]},"weekdays":{"anyOf":[{"type":"array","items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},{"type":"null"}]},"dateFrom":{"type":["string","null"]},"dateTo":{"type":["string","null"]},"minNights":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"maxNights":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"leadMinDays":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"leadMaxDays":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"occupancyMinPct":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"occupancyMaxPct":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"paceSoldPct":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"paceWindowDays":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"adjustBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"addMinor":{"type":["string","null"]},"addCurrency":{"type":["string","null"]},"priority":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"active":{"type":"boolean"},"directOnly":{"type":"boolean","description":"A length-of-stay rule: it never reaches a channel."},"updatedAt":{"type":"string"}},"required":["id","name","scope","scopeLabel","weekdays","dateFrom","dateTo","minNights","maxNights","leadMinDays","leadMaxDays","occupancyMinPct","occupancyMaxPct","paceSoldPct","paceWindowDays","adjustBp","addMinor","addCurrency","priority","active","directOnly","updatedAt"],"additionalProperties":false},"PriceRuleRemoved":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"PriceRulePreview":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"currency":{"type":"string"},"stayNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"draftId":{"type":["string","null"]},"nights":{"type":"array","items":{"type":"object","properties":{"night":{"type":"string"},"baseMinor":{"type":["string","null"]},"directMinor":{"type":["string","null"]},"directRuleIds":{"type":"array","items":{"type":"string"}},"channelMinor":{"type":["string","null"]},"channelRuleIds":{"type":"array","items":{"type":"string"}},"source":{"type":"string","enum":["date","base","unpriced"]},"directClamped":{"anyOf":[{"type":"string","enum":["floor","ceiling"]},{"type":"null"}]},"channelClamped":{"anyOf":[{"type":"string","enum":["floor","ceiling"]},{"type":"null"}]}},"required":["night","baseMinor","directMinor","directRuleIds","channelMinor","channelRuleIds","source","directClamped","channelClamped"],"additionalProperties":false}}},"required":["listingId","currency","stayNights","draftId","nights"],"additionalProperties":false},"PriceRuleLimits":{"type":"object","properties":{"rows":{"type":"array","items":{"$ref":"#/components/schemas/PriceRuleLimitRow"}},"currency":{"type":"string"}},"required":["rows","currency"],"additionalProperties":false},"PriceRuleLimitRow":{"type":"object","properties":{"level":{"type":"string","enum":["property","listing_type"]},"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"floorMinor":{"type":["string","null"]},"ceilingMinor":{"type":["string","null"]},"currency":{"type":["string","null"]}},"required":["level","id","propertyId","name","floorMinor","ceilingMinor","currency"],"additionalProperties":false},"OpsIssuesPage":{"type":"object","properties":{"status":{"type":"string","enum":["open","fixed","dismissed","auto_resolved"]},"items":{"type":"array","items":{"$ref":"#/components/schemas/OpsIssueView"}},"counts":{"type":"object","properties":{"open":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"fixed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"dismissed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"auto_resolved":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["open","fixed","dismissed","auto_resolved"],"additionalProperties":false}},"required":["status","items","counts"],"additionalProperties":false},"OpsIssueView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["price_rule_ending","listing_unpriced","listing_no_photos","channel_room_unmapped","arrival_balance_due","arrival_no_id","site_no_copy","maintenance_urgent"]},"subjectKey":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"bookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"severity":{"type":"string","enum":["info","warning","urgent"]},"status":{"type":"string","enum":["open","fixed","dismissed","auto_resolved"]},"detail":{"type":"object","properties":{"unit":{"type":"string"},"property":{"type":"string"},"type":{"type":"string"},"date":{"type":"string"},"reference":{"type":"string"},"rule":{"type":"string"},"title":{"type":"string"},"site":{"type":"string"}},"additionalProperties":false},"firstSeenAt":{"type":"string"},"lastSeenAt":{"type":"string"},"closedAt":{"type":["string","null"]}},"required":["id","kind","subjectKey","propertyId","listingId","bookingId","severity","status","detail","firstSeenAt","lastSeenAt","closedAt"],"additionalProperties":false},"Folio":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"currency":{"type":"string","minLength":3,"maxLength":3},"chargedMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"paidMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"refundedMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"balanceMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/FolioLine"}},"excludedLineCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"invoices":{"type":"array","items":{"$ref":"#/components/schemas/GuestInvoice"}},"invoiceState":{"type":"string","enum":["none","current","outdated"]},"extraRequests":{"type":"array","items":{"$ref":"#/components/schemas/ExtraRequest"}}},"required":["bookingId","currency","chargedMinor","paidMinor","refundedMinor","balanceMinor","lines","excludedLineCount","invoices","invoiceState","extraRequests"],"additionalProperties":false,"description":"One stay's money statement with its balance due."},"FolioLine":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"origin":{"type":"string","enum":["stay","payment","returned","released","allowance","collected","collected_charge","folio_extra","folio_manual"]},"label":{"type":"string"},"amountMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"signedMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"at":{"type":"string"},"reversesId":{"type":["string","null"]},"reversed":{"type":"boolean"},"refId":{"type":"string"},"quantity":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"category":{"type":["string","null"]},"settled":{"type":["boolean","null"]},"note":{"type":["string","null"]},"day":{"description":"The day the line happened: a civil date (YYYY-MM-DD) in the workspace time zone.","type":["string","null"]},"paymentId":{"description":"A payment line's payment, for its detail page; null on every other line.","type":["string","null"]},"steps":{"type":"array","items":{"$ref":"#/components/schemas/FolioStep"},"description":"When each step of the line happened, oldest first: a payment paid, recorded and verified; a refund requested and approved; a settlement decided at the check-out; the day a guest left."}},"required":["id","kind","origin","label","amountMinor","signedMinor","at","reversesId","reversed","refId","quantity","category","settled","note","day","paymentId","steps"],"additionalProperties":false,"description":"One folio line; a reversal names the line it cancels."},"FolioStep":{"type":"object","properties":{"kind":{"type":"string","enum":["booked","paid","recorded","verified","requested","approved","checkout_settled","cancellation_settled","paid_out","left_early","cancelled","collected","added","reversed"]},"day":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["kind","day"],"additionalProperties":false,"description":"One dated step in a folio line, a workspace-local day."},"GuestInvoice":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["invoice","credit_note"]},"number":{"type":"string"},"totalMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"currency":{"type":"string","minLength":3,"maxLength":3},"issuedAt":{"type":"string"},"creditsInvoiceId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"credited":{"type":"boolean"}},"required":["id","kind","number","totalMinor","currency","issuedAt","creditsInvoiceId","credited"],"additionalProperties":false,"description":"An issued guest invoice or credit note."},"ExtraRequest":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"itemName":{"type":"string"},"category":{"type":["string","null"]},"variant":{"type":["string","null"]},"quantity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"amountMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"currency":{"type":"string","minLength":3,"maxLength":3},"status":{"type":"string","enum":["requested","confirmed","declined","cancelled"]},"guestNote":{"type":["string","null"]},"declineReason":{"type":["string","null"]},"createdAt":{"type":"string"},"referenceCode":{"type":["string","null"]},"guestName":{"type":["string","null"]},"checkIn":{"type":["string","null"]}},"required":["id","bookingId","itemName","category","variant","quantity","amountMinor","currency","status","guestNote","declineReason","createdAt","referenceCode","guestName","checkIn"],"additionalProperties":false,"description":"A guest's ask for an extra from the guest app."},"FolioChargeCreated":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"FolioChargeCollected":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"journalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id","journalEntryId"],"additionalProperties":false},"IssueGuestInvoiceResponse":{"type":"object","properties":{"invoice":{"$ref":"#/components/schemas/GuestInvoice"},"creditNote":{"anyOf":[{"$ref":"#/components/schemas/GuestInvoice"},{"type":"null"}]}},"required":["invoice","creditNote"],"additionalProperties":false},"GuestInvoiceEmailed":{"type":"object","properties":{"queued":{"type":"boolean","const":true}},"required":["queued"],"additionalProperties":false},"PendingExtraRequests":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ExtraRequest"}}},"required":["items"],"additionalProperties":false},"ExtraRequestDecided":{"type":"object","properties":{"status":{"type":"string","enum":["confirmed","declined"]},"folioChargeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["status","folioChargeId"],"additionalProperties":false},"UpsellSettingsList":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"offerInGuestApp":{"type":"boolean"},"category":{"anyOf":[{"type":"string","enum":["early_checkin","late_checkout","cleaning","transport","food","experience","other"]},{"type":"null"}]},"maxPerStay":{"anyOf":[{"type":"integer","minimum":1,"maximum":99},{"type":"null"}]},"cutoffHours":{"anyOf":[{"type":"integer","minimum":0,"maximum":720},{"type":"null"}]},"minNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"maxNights":{"anyOf":[{"type":"integer","minimum":1,"maximum":365},{"type":"null"}]},"availableFrom":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"availableTo":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"variants":{"maxItems":20,"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60},"amountMinor":{"type":"string","pattern":"^\\d{1,12}$"}},"required":["name","amountMinor"],"additionalProperties":false}},"feeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"photoUrl":{"type":["string","null"]}},"required":["offerInGuestApp","category","maxPerStay","cutoffHours","minNights","maxNights","availableFrom","availableTo","variants","feeId","photoUrl"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"UpsellSaved":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"UpsellPhotoTicket":{"type":"object","properties":{"objectKey":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["objectKey","uploadUrl","requiredHeaders"],"additionalProperties":false},"UpsellRevenue":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"currencies":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"totalMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"byMonth":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string"},"totalMinor":{"type":"string","pattern":"^-?\\d{1,15}$"}},"required":["month","totalMinor"],"additionalProperties":false}},"byCategory":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string"},"totalMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["category","totalMinor","count"],"additionalProperties":false}},"topItems":{"type":"array","items":{"type":"object","properties":{"feeScheduleId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"totalMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"quantity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["feeScheduleId","name","totalMinor","quantity"],"additionalProperties":false}}},"required":["currency","totalMinor","count","byMonth","byCategory","topItems"],"additionalProperties":false}},"history":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"collectedOn":{"type":"string"},"itemName":{"type":"string"},"category":{"type":"string"},"quantity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"amountMinor":{"type":"string","pattern":"^-?\\d{1,15}$"},"currency":{"type":"string"},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"referenceCode":{"type":["string","null"]}},"required":["id","collectedOn","itemName","category","quantity","amountMinor","currency","bookingId","referenceCode"],"additionalProperties":false}}},"required":["from","to","currencies","history"],"additionalProperties":false,"description":"Collected upsell sales only; owed extras are not revenue."},"AmenityHierarchyView":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The listing (null when queried by type/property)."},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The listing type (if any)."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The property (null for a legacy tenant-wide type)."},"listingAmenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"description":"The set stored at the UNIT level. `[]` = not set here, which is what makes this level fall through."},"listingTypeAmenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"description":"The set stored at the TYPE level. `[]` = not set here."},"propertyAmenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"description":"The set stored at the PROPERTY level. `[]` = not set here."},"effectiveAmenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"description":"The resolved set — listing ?? type ?? property. An OVERRIDE, not a union: the first non-empty level wins outright."},"effectiveSource":{"type":"string","enum":["listing","listing_type","property","unset"],"description":"Which hierarchy level supplied the effective set."}},"required":["listingId","listingTypeId","propertyId","listingAmenities","listingTypeAmenities","propertyAmenities","effectiveAmenities","effectiveSource"],"additionalProperties":false},"SetAmenitiesResponse":{"type":"object","properties":{"scope":{"type":"string","enum":["property","listing_type","listing"],"description":"The hierarchy level — the same three grains the base rate uses."},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amenities":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120}}},"required":["scope","entityId","amenities"],"additionalProperties":false},"ContentHierarchyView":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listing":{"type":"object","properties":{"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"importantInformation":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"petsPolicy":{"anyOf":[{"type":"string","enum":["allowed","by_arrangements","not_allowed"]},{"type":"null"}]},"smokingPolicy":{"anyOf":[{"type":"string","enum":["no_smoking","smoking_allowed","designated_areas"]},{"type":"null"}]},"parkingType":{"anyOf":[{"type":"string","enum":["on_site","nearby","none"]},{"type":"null"}]},"wifiCoverage":{"anyOf":[{"type":"string","enum":["entire_property","public_areas","none"]},{"type":"null"}]}},"required":["description","importantInformation","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false},"listingType":{"type":"object","properties":{"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"importantInformation":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"petsPolicy":{"anyOf":[{"type":"string","enum":["allowed","by_arrangements","not_allowed"]},{"type":"null"}]},"smokingPolicy":{"anyOf":[{"type":"string","enum":["no_smoking","smoking_allowed","designated_areas"]},{"type":"null"}]},"parkingType":{"anyOf":[{"type":"string","enum":["on_site","nearby","none"]},{"type":"null"}]},"wifiCoverage":{"anyOf":[{"type":"string","enum":["entire_property","public_areas","none"]},{"type":"null"}]}},"required":["description","importantInformation","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false},"property":{"type":"object","properties":{"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"importantInformation":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"petsPolicy":{"anyOf":[{"type":"string","enum":["allowed","by_arrangements","not_allowed"]},{"type":"null"}]},"smokingPolicy":{"anyOf":[{"type":"string","enum":["no_smoking","smoking_allowed","designated_areas"]},{"type":"null"}]},"parkingType":{"anyOf":[{"type":"string","enum":["on_site","nearby","none"]},{"type":"null"}]},"wifiCoverage":{"anyOf":[{"type":"string","enum":["entire_property","public_areas","none"]},{"type":"null"}]}},"required":["description","importantInformation","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false},"effective":{"type":"object","properties":{"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"importantInformation":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]},"petsPolicy":{"anyOf":[{"type":"string","enum":["allowed","by_arrangements","not_allowed"]},{"type":"null"}]},"smokingPolicy":{"anyOf":[{"type":"string","enum":["no_smoking","smoking_allowed","designated_areas"]},{"type":"null"}]},"parkingType":{"anyOf":[{"type":"string","enum":["on_site","nearby","none"]},{"type":"null"}]},"wifiCoverage":{"anyOf":[{"type":"string","enum":["entire_property","public_areas","none"]},{"type":"null"}]}},"required":["description","importantInformation","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false},"sources":{"type":"object","properties":{"description":{"type":"string","enum":["listing","listing_type","property","unset"]},"importantInformation":{"type":"string","enum":["listing","listing_type","property","unset"]},"petsPolicy":{"type":"string","enum":["listing","listing_type","property","unset"]},"smokingPolicy":{"type":"string","enum":["listing","listing_type","property","unset"]},"parkingType":{"type":"string","enum":["listing","listing_type","property","unset"]},"wifiCoverage":{"type":"string","enum":["listing","listing_type","property","unset"]}},"required":["description","importantInformation","petsPolicy","smokingPolicy","parkingType","wifiCoverage"],"additionalProperties":false}},"required":["listingId","listingTypeId","propertyId","listing","listingType","property","effective","sources"],"additionalProperties":false,"description":"A content card at every level, its per-field resolution, and which level answered."},"PropertyKnowledgeView":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listing":{"type":"object","properties":{"houseManual":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkInInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkOutInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"cleaningInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"parkingInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"trashInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"luggageStorage":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"buildingName":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["houseManual","checkInInstructions","checkOutInstructions","cleaningInstructions","parkingInstructions","trashInstructions","luggageStorage","buildingName"],"additionalProperties":false},"listingType":{"type":"object","properties":{"houseManual":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkInInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkOutInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"cleaningInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"parkingInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"trashInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"luggageStorage":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"buildingName":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["houseManual","checkInInstructions","checkOutInstructions","cleaningInstructions","parkingInstructions","trashInstructions","luggageStorage","buildingName"],"additionalProperties":false},"property":{"type":"object","properties":{"houseManual":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkInInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkOutInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"cleaningInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"parkingInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"trashInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"luggageStorage":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"buildingName":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["houseManual","checkInInstructions","checkOutInstructions","cleaningInstructions","parkingInstructions","trashInstructions","luggageStorage","buildingName"],"additionalProperties":false},"effective":{"type":"object","properties":{"houseManual":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkInInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"checkOutInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"cleaningInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"parkingInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"trashInstructions":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"luggageStorage":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]},"buildingName":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}]}},"required":["houseManual","checkInInstructions","checkOutInstructions","cleaningInstructions","parkingInstructions","trashInstructions","luggageStorage","buildingName"],"additionalProperties":false},"sources":{"type":"object","properties":{"houseManual":{"type":"string","enum":["listing","listing_type","property","unset"]},"checkInInstructions":{"type":"string","enum":["listing","listing_type","property","unset"]},"checkOutInstructions":{"type":"string","enum":["listing","listing_type","property","unset"]},"cleaningInstructions":{"type":"string","enum":["listing","listing_type","property","unset"]},"parkingInstructions":{"type":"string","enum":["listing","listing_type","property","unset"]},"trashInstructions":{"type":"string","enum":["listing","listing_type","property","unset"]},"luggageStorage":{"type":"string","enum":["listing","listing_type","property","unset"]},"buildingName":{"type":"string","enum":["listing","listing_type","property","unset"]}},"required":["houseManual","checkInInstructions","checkOutInstructions","cleaningInstructions","parkingInstructions","trashInstructions","luggageStorage","buildingName"],"additionalProperties":false}},"required":["listingId","listingTypeId","propertyId","listing","listingType","property","effective","sources"],"additionalProperties":false,"description":"A property-knowledge card at every level, its per-field resolution, and which level answered."},"GetConversationResponse":{"type":"object","properties":{"conversation":{"anyOf":[{"$ref":"#/components/schemas/ConversationView"},{"type":"null"}]}},"required":["conversation"],"additionalProperties":false},"ConversationView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"referenceCode":{"type":["string","null"]},"guestId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"guestName":{"type":["string","null"]},"status":{"type":"string","enum":["open","closed"]},"subject":{"type":["string","null"]},"lastMessageAt":{"type":["string","null"]},"hasChannelThread":{"type":"boolean","description":"True when an OTA thread is linked (replies on that OTA available)."},"threadChannel":{"anyOf":[{"type":"string","enum":["airbnb","booking_com","expedia","agoda","vrbo"]},{"type":"null"}],"description":"The OTA the linked thread belongs to (0439); its replies leave on it. Null with no thread."},"channelThreadUrl":{"description":"Deep link to this conversation on the channel (Airbnb's own thread id). Null on in-app/WhatsApp threads and on providers that expose no id.","type":["string","null"]},"channelListingUrl":{"description":"Deep link to the listing on the channel. Null when the channel gives us no id.","type":["string","null"]},"context":{"$ref":"#/components/schemas/ConversationContextView"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/MessageView"},"description":"The thread, oldest → newest."}},"required":["id","bookingId","referenceCode","guestId","guestName","status","subject","lastMessageAt","hasChannelThread","threadChannel","channelThreadUrl","channelListingUrl","context","messages"],"additionalProperties":false},"ConversationContextView":{"type":"object","properties":{"kind":{"type":"string","enum":["booking","inquiry","guest"]},"referenceCode":{"type":["string","null"]},"status":{"type":["string","null"]},"checkIn":{"type":["string","null"]},"checkOut":{"type":["string","null"]},"listingCode":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The unit's ids, so the rail can LINK the unit it already names. Both or neither — the listing route needs the property id too."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"openHref":{"type":["string","null"]}},"required":["kind","referenceCode","status","checkIn","checkOut","listingCode","propertyName","listingId","propertyId","openHref"],"additionalProperties":false},"MessageView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"direction":{"type":"string","enum":["inbound","outbound","internal"],"description":"From the guest / to the guest / an INTERNAL staff note the guest never sees (0168)."},"senderType":{"type":"string","enum":["guest","staff","system"]},"channel":{"type":"string","enum":["in_app","whatsapp","email","airbnb","booking_com","expedia","agoda","vrbo"]},"body":{"type":"string"},"status":{"type":"string","enum":["queued","sent","delivered","failed","received","read"]},"senderLabel":{"description":"WHO sent it, recorded at write time (0168). Null on inbound guest messages, on system writes, and on pre-0168 rows — read it as \"unknown\", never as a name.","type":["string","null"]},"sentAt":{"type":["string","null"]},"deliveredAt":{"type":["string","null"]},"createdAt":{"type":"string"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/MessageAttachmentView"},"description":"Bound, ready media (view URLs mint per attachment)."},"mentions":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"description":"The SEATS (membership ids) this message tagged (0244). Ids rather than names: display names live on the identity plane the tenant connection cannot read, and the client already holds the id→name map it built the mention picker from."}},"required":["id","direction","senderType","channel","body","status","senderLabel","sentAt","deliveredAt","createdAt","attachments","mentions"],"additionalProperties":false},"MessageAttachmentView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"contentType":{"type":"string"},"byteSize":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","contentType","byteSize"],"additionalProperties":false},"SendMessageResponse":{"type":"object","properties":{"conversation":{"$ref":"#/components/schemas/ConversationView"}},"required":["conversation"],"additionalProperties":false},"ListInboxResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InboxItemView"}},"nextCursor":{"description":"The id to pass as `cursor` for the next page; null on the last page.","type":["string","null"]}},"required":["items","nextCursor"],"additionalProperties":false},"InboxItemView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"referenceCode":{"type":["string","null"]},"guestId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"guestName":{"type":["string","null"]},"status":{"type":"string","enum":["open","closed"]},"subject":{"type":["string","null"]},"lastMessageAt":{"type":["string","null"]},"lastBody":{"type":["string","null"]},"lastDirection":{"type":["string","null"]},"lastChannel":{"type":["string","null"]},"channels":{"type":"array","items":{"type":"string"},"description":"Distinct transports seen on the thread."},"unread":{"type":"boolean","description":"Per-seat: newer activity than YOUR read mark."}},"required":["id","bookingId","referenceCode","guestId","guestName","status","subject","lastMessageAt","lastBody","lastDirection","lastChannel","channels","unread"],"additionalProperties":false},"ListMentionableMembersResponse":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/MentionableMemberView"}}},"required":["members"],"additionalProperties":false},"MentionableMemberView":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"The SEAT id — what a mention records and what a notification is addressed to. Never a platform-user id."},"displayName":{"type":"string"},"email":{"type":"string"}},"required":["membershipId","displayName","email"],"additionalProperties":false},"ChannelBackfillResponse":{"type":"object","properties":{"seen":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Reservations enumerated across every page read."},"alreadyPresent":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Already held as a booking or an inbox row — skipped without a per-booking fetch."},"applied":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"quarantined":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unclaimed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"On a provider property no tenant map claims."},"unfetchable":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reachedPageLimit":{"type":"boolean","description":"True ⇒ the page ceiling stopped this run and there may be more history. Re-run it."}},"required":["seen","alreadyPresent","applied","quarantined","unclaimed","unfetchable","failed","reachedPageLimit"],"additionalProperties":false},"ListImportBatchesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ImportBatchView"}}},"required":["items"],"additionalProperties":false},"ImportBatchView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"channel":{"type":"string","enum":["airbnb","spreadsheet"]},"filename":{"type":"string"},"status":{"type":"string","enum":["created","committed","rolled_back"]},"rowCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"committedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"quarantinedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"columnMapping":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},{"type":"null"}]},"listingMapping":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},{"type":"null"}]},"sourceHeaders":{"type":"array","items":{"type":"string"}},"dateOrder":{"type":["string","null"]},"numberFormat":{"type":["string","null"]},"recognizeFrom":{"description":"The money cutoff: stays starting on or after this date get a payment posted. Null ⇒ unanswered, and the money step refuses to run.","type":["string","null"]},"committedByLabel":{"description":"WHO ran the import, recorded at commit time. Null on batches imported before this was tracked.","type":["string","null"]},"committedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","channel","filename","status","rowCount","committedCount","quarantinedCount","columnMapping","listingMapping","sourceHeaders","dateOrder","numberFormat","recognizeFrom","committedByLabel","committedAt","createdAt"],"additionalProperties":false},"ImportBatchWithRowsResponse":{"type":"object","properties":{"batch":{"$ref":"#/components/schemas/ImportBatchView"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/ImportRowView"}}},"required":["batch","rows"],"additionalProperties":false},"ImportRowView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"rowIndex":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"externalId":{"type":"string"},"status":{"type":"string","enum":["parsed","mapped","validated","committed","conflict","quarantined","rolled_back"]},"conflictReason":{"description":"Why this row cannot commit, in words the operator can act on. Null when clean.","type":["string","null"]},"listingRef":{"type":["string","null"]},"guestName":{"type":["string","null"]},"checkIn":{"type":["string","null"]},"checkOut":{"type":["string","null"]},"amountMinor":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"currency":{"type":["string","null"]},"commissionMinor":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"resultingBookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","rowIndex","externalId","status","conflictReason","listingRef","guestName","checkIn","checkOut","amountMinor","currency","commissionMinor","resultingBookingId"],"additionalProperties":false},"ImportPreviewResponse":{"type":"object","properties":{"batch":{"$ref":"#/components/schemas/ImportBatchView"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/ImportRowView"}},"listingRefs":{"type":"array","items":{"$ref":"#/components/schemas/ListingRefSuggestionView"}},"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"}},"required":["id","listingCode"],"additionalProperties":false}}},"required":["batch","rows","listingRefs","listings"],"additionalProperties":false},"ListingRefSuggestionView":{"type":"object","properties":{"ref":{"type":"string"},"rowCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"suggestedListingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"mappedListingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["ref","rowCount","suggestedListingId","mappedListingId"],"additionalProperties":false},"CommitImportResponse":{"type":"object","properties":{"batch":{"$ref":"#/components/schemas/ImportBatchView"},"committed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"quarantined":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["batch","committed","quarantined"],"additionalProperties":false},"ImportMoneyPreviewResponse":{"type":"object","properties":{"batchId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"recognizeFrom":{"type":["string","null"]},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ImportMoneyLineView"}},"totalsByCurrency":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"amountMinor":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["currency","amountMinor"],"additionalProperties":false}},"willPostCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skippedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"commissionExcludedMinor":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["batchId","recognizeFrom","lines","totalsByCurrency","willPostCount","skippedCount","commissionExcludedMinor"],"additionalProperties":false},"ImportMoneyLineView":{"type":"object","properties":{"rowId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"rowIndex":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"externalId":{"type":"string"},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"checkIn":{"type":"string"},"entryDate":{"type":"string","description":"The date this receipt would post on: the stay’s check-in for a stay that has already started, today for one that has not. This is the period the row restates, so it is part of what the operator approves."},"paidAt":{"description":"The payment row’s `paid_at` for a backdated receipt (noon UTC of the posting date), or null when the stay has not started and the real instant is used.","type":["string","null"]},"amountMinor":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"currency":{"type":"string"},"commissionMinor":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"liability":{"type":"string","enum":["deferred","owner_payable","investor_pool"],"description":"Where the gross would be credited, decided by the operating model: managed ⇒ owner_payable, investor ⇒ investor_pool, otherwise deferred. Only deferred later becomes operator revenue."},"willPost":{"type":"boolean"},"skipReason":{"description":"Why this row posts nothing, in words. Null when it will post.","type":["string","null"]}},"required":["rowId","rowIndex","externalId","bookingId","checkIn","entryDate","paidAt","amountMinor","currency","commissionMinor","liability","willPost","skipReason"],"additionalProperties":false},"PostImportMoneyResponse":{"type":"object","properties":{"posted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"skipped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"failed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalsByCurrency":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"amountMinor":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["currency","amountMinor"],"additionalProperties":false}}},"required":["posted","skipped","failed","totalsByCurrency"],"additionalProperties":false},"SetImportCutoffResponse":{"type":"object","properties":{"recognizeFrom":{"type":"string"}},"required":["recognizeFrom"],"additionalProperties":false},"RollbackImportResponse":{"type":"object","properties":{"rolledBack":{"type":"boolean","const":true}},"required":["rolledBack"],"additionalProperties":false},"ListMessageTemplatesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MessageTemplateView"}}},"required":["items"],"additionalProperties":false},"MessageTemplateView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"body":{"type":"string"},"channels":{"type":"array","items":{"type":"string","enum":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"]},"description":"The channels this phrase is offered on. Non-empty; all three means \"offered anywhere\". There is no `any` sentinel — a set already says it."},"categories":{"type":"array","items":{"type":"string","enum":["inquiry","pre_arrival","in_stay","checkout","review","general"]},"description":"The moments in a stay this phrase belongs to (0179). Non-empty; a phrase in several moments is listed under each. `general` is the catch-all moment, NOT a sentinel for all of them."},"isArchived":{"type":"boolean"},"useCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastUsedAt":{"type":["string","null"]},"tokens":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","body","channels","categories","isArchived","useCount","lastUsedAt","tokens","createdAt","updatedAt"],"additionalProperties":false},"MessageTemplateResponse":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/MessageTemplateView"}},"required":["template"],"additionalProperties":false},"ListAutoResponseRulesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AutoResponseRuleView"}}},"required":["items"],"additionalProperties":false},"AutoResponseRuleView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"phase":{"type":"string","enum":["inquiry","pre_arrival","in_stay","post_stay"]},"templateId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"templateName":{"type":"string"},"enabled":{"type":"boolean"},"channels":{"type":"array","items":{"type":"string","enum":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"]},"description":"The inbound channels this rule answers on. A FILTER, never a destination — the reply always goes back on the channel the guest wrote on."},"respondWhen":{"type":"string","enum":["always","outside_hours"]},"hoursFrom":{"type":["string","null"]},"hoursTo":{"type":["string","null"]},"cooldownMinutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updatedAt":{"type":"string"}},"required":["id","phase","templateId","templateName","enabled","channels","respondWhen","hoursFrom","hoursTo","cooldownMinutes","updatedAt"],"additionalProperties":false},"AutoResponseRuleResponse":{"type":"object","properties":{"rule":{"$ref":"#/components/schemas/AutoResponseRuleView"}},"required":["rule"],"additionalProperties":false},"DeleteAutoResponseRuleResponse":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"],"additionalProperties":false},"ListStarterTemplatesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/StarterTemplateView"}}},"required":["items"],"additionalProperties":false},"StarterTemplateView":{"type":"object","properties":{"key":{"type":"string","description":"The catalog's stable identity for this phrase — what the Add button sends back. It is never stored on the row it creates."},"name":{"type":"string"},"description":{"type":"string"},"body":{"type":"string"},"categories":{"type":"array","items":{"type":"string","enum":["inquiry","pre_arrival","in_stay","checkout","review","general"]}},"channels":{"type":"array","items":{"type":"string","enum":["in_app","whatsapp","airbnb","booking_com","expedia","agoda","vrbo"]}},"blanks":{"type":"array","items":{"type":"string"},"description":"The `[bracketed blanks]` in the body — facts this product does not hold, which the operator fills in before sending. Shown on the card so \"this one needs two details from you\" is visible BEFORE it is added."},"alreadyAdded":{"type":"boolean","description":"A live row (archived included) already holds this name. Matched by NAME, not by key — rename an added phrase and it is offered again, which is deliberate: once renamed it is the tenant’s."}},"required":["key","name","description","body","categories","channels","blanks","alreadyAdded"],"additionalProperties":false},"AddStarterTemplatesResponse":{"type":"object","properties":{"added":{"type":"array","items":{"$ref":"#/components/schemas/MessageTemplateView"}},"skipped":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"reason":{"type":"string","const":"already_added"}},"required":["key","reason"],"additionalProperties":false},"description":"Requested keys that were not added, each with its reason."}},"required":["added","skipped"],"additionalProperties":false},"DeleteMessageTemplateResponse":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"],"additionalProperties":false},"RenderMessageTemplateResponse":{"type":"object","properties":{"templateId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"text":{"type":"string"},"missing":{"type":"array","items":{"type":"string","enum":["guest_name","guest_first_name","guest_last_name","guests","adults","children","reference_code","check_in","check_out","nights","check_in_time","check_out_time","listing_code","listing_type","property_name","property_code","property_address","next_check_in","next_check_in_time","nights_free_after","house_manual","check_in_instructions","check_out_instructions","parking_instructions","trash_instructions","luggage_storage","building_name","currency","total_price","total_paid","balance_due","cleaning_fee","extra_charges","host_payout","channel_commission","guest_email","guest_phone","guest_nationality","guest_id_kind","guest_id_number"]}}},"required":["templateId","text","missing"],"additionalProperties":false},"ListTenantVariablesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TenantVariableView"}}},"required":["items"],"additionalProperties":false},"TenantVariableView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"key":{"type":"string"},"label":{"type":"string"},"value":{"type":["string","null"]}},"required":["id","key","label","value"],"additionalProperties":false},"DeleteTenantVariableResponse":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"],"additionalProperties":false},"ConversationTemplateVariablesResponse":{"type":"object","properties":{"variables":{"type":"array","items":{"$ref":"#/components/schemas/ConversationTemplateVariable"}}},"required":["variables"],"additionalProperties":false},"ConversationTemplateVariable":{"type":"object","properties":{"token":{"type":"string","enum":["guest_name","guest_first_name","guest_last_name","guests","adults","children","reference_code","check_in","check_out","nights","check_in_time","check_out_time","listing_code","listing_type","property_name","property_code","property_address","next_check_in","next_check_in_time","nights_free_after","house_manual","check_in_instructions","check_out_instructions","parking_instructions","trash_instructions","luggage_storage","building_name","currency","total_price","total_paid","balance_due","cleaning_fee","extra_charges","host_payout","channel_commission","guest_email","guest_phone","guest_nationality","guest_id_kind","guest_id_number"]},"value":{"type":["string","null"]}},"required":["token","value"],"additionalProperties":false},"CreateInquiryFromConversationResponse":{"type":"object","properties":{"inquiryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"referenceCode":{"type":"string"}},"required":["inquiryId","referenceCode"],"additionalProperties":false},"MarkConversationReadResponse":{"type":"object","properties":{"marked":{"type":"boolean"}},"required":["marked"],"additionalProperties":false},"RequestAttachmentUploadResponse":{"type":"object","properties":{"attachmentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["attachmentId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmAttachmentUploadResponse":{"type":"object","properties":{"attachmentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"uploadStatus":{"type":"string","const":"ready"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["attachmentId","uploadStatus","byteSize"],"additionalProperties":false},"AttachmentViewUrlResponse":{"type":"object","properties":{"attachmentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["attachmentId","url","expiresInSeconds"],"additionalProperties":false},"AiAssistantView":{"type":"object","properties":{"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"profile":{"type":"object","properties":{"tone":{"type":"string"},"standingRules":{"type":"string"},"facts":{"type":"array","items":{"$ref":"#/components/schemas/AiFact"}},"offerExtras":{"type":"boolean"},"discountsAllowed":{"type":"boolean"},"discountPolicy":{"type":"string"},"updatedAt":{"type":["string","null"]}},"required":["tone","standingRules","facts","offerExtras","discountsAllowed","discountPolicy","updatedAt"],"additionalProperties":false},"known":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"value":{"type":["string","null"]},"source":{"type":"string","enum":["content","policies","types","guest_app","fees"]}},"required":["key","label","value","source"],"additionalProperties":false}},"gaps":{"type":"array","items":{"type":"string"}},"extras":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"price":{"type":"string"}},"required":["name","price"],"additionalProperties":false}},"autopilot":{"type":"object","properties":{"enabled":{"type":"boolean"},"thresholdBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"inherited":{"type":"boolean"}},"required":["enabled","thresholdBp","inherited"],"additionalProperties":false},"entitled":{"type":"boolean"}},"required":["property","profile","known","gaps","extras","autopilot","entitled"],"additionalProperties":false,"description":"One property's AI assistant, as its page shows it."},"GuestReplyDraftView":{"type":"object","properties":{"reply":{"type":"string"},"canAnswer":{"type":"boolean"},"confidenceBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"topics":{"type":"array","items":{"type":"string","enum":["general","availability","arrival","departure","directions","amenities","house_rules","extras","money","refund","discount","cancellation","complaint","door_code"]}},"needsPerson":{"type":"boolean"},"missing":{"type":["string","null"]}},"required":["reply","canAnswer","confidenceBp","topics","needsPerson","missing"],"additionalProperties":false,"description":"A draft reply for a person to edit and send. Nothing is sent or saved."},"ListDailyReportsResponse":{"type":"object","properties":{"reports":{"type":"array","items":{"$ref":"#/components/schemas/DailyReportMetaView"}}},"required":["reports"],"additionalProperties":false},"DailyReportMetaView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reportDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"generatedAt":{"type":"string"}},"required":["id","reportDate","generatedAt"],"additionalProperties":false},"GetDailyReportResponse":{"type":"object","properties":{"report":{"anyOf":[{"$ref":"#/components/schemas/DailyReportDetailView"},{"type":"null"}]}},"required":["report"],"additionalProperties":false},"DailyReportDetailView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"reportDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"generatedAt":{"type":"string"},"sections":{"$ref":"#/components/schemas/ReportSections"},"minimalBody":{"type":"string"},"detailedBody":{"type":"string"},"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/DailyReportDeliveryView"}}},"required":["id","reportDate","generatedAt","sections","minimalBody","detailedBody","deliveries"],"additionalProperties":false},"ReportSections":{"type":"object","properties":{"reportDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"board":{"type":"array","items":{"$ref":"#/components/schemas/ReportBoardRow"}},"arrivals":{"type":"array","items":{"$ref":"#/components/schemas/ReportStayRow"}},"departures":{"type":"array","items":{"$ref":"#/components/schemas/ReportDepartureRow"}},"sameDayTurnovers":{"type":"array","items":{"$ref":"#/components/schemas/ReportTurnoverRow"}},"inHouse":{"type":"array","items":{"$ref":"#/components/schemas/ReportStayRow"}},"vacantTonight":{"type":"array","items":{"$ref":"#/components/schemas/ReportVacantRow"}},"availableForSale":{"type":"array","items":{"$ref":"#/components/schemas/ReportVacantRow"}},"pendingPayments":{"type":"array","items":{"$ref":"#/components/schemas/ReportPendingPaymentRow"}},"pendingPaymentVerifications":{"type":"array","items":{"$ref":"#/components/schemas/ReportPendingVerificationRow"}},"pendingIdVerifications":{"type":"object","properties":{"pendingCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["pendingCount"],"additionalProperties":false},"pendingLockCodes":{"type":"array","items":{"$ref":"#/components/schemas/ReportLockCodeRow"}},"cleaningRequired":{"type":"array","items":{"$ref":"#/components/schemas/ReportCleaningRow"}},"inspectionsPending":{"type":"array","items":{"$ref":"#/components/schemas/ReportInspectionRow"}},"damageFollowUps":{"type":"array","items":{"$ref":"#/components/schemas/ReportDamageRow"}},"tomorrowArrivals":{"type":"array","items":{"$ref":"#/components/schemas/ReportStayRow"}}},"required":["reportDate","board","arrivals","departures","sameDayTurnovers","inHouse","vacantTonight","availableForSale","pendingPayments","pendingPaymentVerifications","pendingIdVerifications","pendingLockCodes","cleaningRequired","inspectionsPending","damageFollowUps","tomorrowArrivals"],"additionalProperties":false},"ReportBoardRow":{"type":"object","properties":{"listingCode":{"type":"string"},"propertyName":{"type":"string"},"bedrooms":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"guestName":{"type":["string","null"]},"checkIn":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"checkOut":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},{"type":"null"}]},"channel":{"anyOf":[{"type":"string","enum":["online","offline"]},{"type":"null"}]},"guestCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"pendingAmount":{"anyOf":[{"$ref":"#/components/schemas/ReportAmount"},{"type":"null"}]}},"required":["listingCode","propertyName","bedrooms","guestName","checkIn","checkOut","channel","guestCount","pendingAmount"],"additionalProperties":false},"ReportAmount":{"type":"object","properties":{"minorUnits":{"type":"string","pattern":"^-?\\d+$","description":"Integer minor units, as a string."},"currency":{"type":"string","minLength":3,"maxLength":3}},"required":["minorUnits","currency"],"additionalProperties":false},"ReportStayRow":{"type":"object","properties":{"listingCode":{"type":"string"},"propertyName":{"type":"string"},"guestName":{"type":"string"},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"channel":{"type":"string","enum":["online","offline"]},"guestCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pendingAmount":{"anyOf":[{"$ref":"#/components/schemas/ReportAmount"},{"type":"null"}]},"status":{"type":"string"}},"required":["listingCode","propertyName","guestName","checkIn","checkOut","channel","guestCount","pendingAmount","status"],"additionalProperties":false},"ReportDepartureRow":{"type":"object","properties":{"listingCode":{"type":"string"},"propertyName":{"type":"string"},"guestName":{"type":"string"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"sameDayTurnover":{"type":"boolean"},"pendingAmount":{"anyOf":[{"$ref":"#/components/schemas/ReportAmount"},{"type":"null"}]}},"required":["listingCode","propertyName","guestName","checkOut","sameDayTurnover","pendingAmount"],"additionalProperties":false},"ReportTurnoverRow":{"type":"object","properties":{"listingCode":{"type":"string"},"propertyName":{"type":"string"},"outGuestName":{"type":"string"},"inGuestName":{"type":"string"}},"required":["listingCode","propertyName","outGuestName","inGuestName"],"additionalProperties":false},"ReportVacantRow":{"type":"object","properties":{"listingCode":{"type":"string"},"propertyName":{"type":"string"},"bedrooms":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"readiness":{"type":"string"}},"required":["listingCode","propertyName","bedrooms","readiness"],"additionalProperties":false},"ReportPendingPaymentRow":{"type":"object","properties":{"guestName":{"type":"string"},"listingCodes":{"type":"array","items":{"type":"string"}},"amount":{"$ref":"#/components/schemas/ReportAmount"}},"required":["guestName","listingCodes","amount"],"additionalProperties":false},"ReportPendingVerificationRow":{"type":"object","properties":{"guestName":{"type":"string"},"listingCode":{"type":"string"},"amount":{"$ref":"#/components/schemas/ReportAmount"}},"required":["guestName","listingCode","amount"],"additionalProperties":false},"ReportLockCodeRow":{"type":"object","properties":{"listingCode":{"type":"string"},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"state":{"type":"string","description":"The relay STATE only — a code value never rides the wire."}},"required":["listingCode","checkIn","state"],"additionalProperties":false},"ReportCleaningRow":{"type":"object","properties":{"listingCode":{"type":"string"},"propertyName":{"type":"string"},"status":{"type":"string"},"urgent":{"type":"boolean"},"deadlineMissed":{"type":"boolean"}},"required":["listingCode","propertyName","status","urgent","deadlineMissed"],"additionalProperties":false},"ReportInspectionRow":{"type":"object","properties":{"listingCode":{"type":"string"},"round":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["listingCode","round"],"additionalProperties":false},"ReportDamageRow":{"type":"object","properties":{"listingCode":{"type":"string"},"kind":{"type":"string"},"description":{"type":"string"}},"required":["listingCode","kind","description"],"additionalProperties":false},"DailyReportDeliveryView":{"type":"object","properties":{"channel":{"type":"string","enum":["email","whatsapp"]},"variant":{"type":"string","enum":["minimal","detailed"]},"recipientMembershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"status":{"type":"string","enum":["queued","sent","delivered","failed","bounced","opted_out"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]}},"required":["channel","variant","recipientMembershipId","status","error","sentAt"],"additionalProperties":false},"ListStaffPhoneLinksResponse":{"type":"object","properties":{"links":{"type":"array","items":{"$ref":"#/components/schemas/StaffPhoneLinkView"}}},"required":["links"],"additionalProperties":false},"StaffPhoneLinkView":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"whatsapp":{"type":"string","pattern":"^\\+[1-9][0-9]{7,14}$"}},"required":["membershipId","whatsapp"],"additionalProperties":false},"SetStaffPhoneLinkResponse":{"type":"object","properties":{"link":{"$ref":"#/components/schemas/StaffPhoneLinkView"}},"required":["link"],"additionalProperties":false},"ListReportAudienceResponse":{"type":"object","properties":{"seats":{"type":"array","items":{"$ref":"#/components/schemas/ReportAudienceSeat"}},"usingDefaultAudience":{"type":"boolean","description":"true when nothing is configured, so the report falls back to the active owner/admin seats. An empty configuration is NEVER an empty audience."}},"required":["seats","usingDefaultAudience"],"additionalProperties":false},"ReportAudienceSeat":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"displayName":{"type":"string"},"email":{"type":"string"},"accountRole":{"type":"string"},"canViewInApp":{"type":"boolean","description":"false when the seat cannot open /daily-report in-app — configuring it emails data the seat cannot otherwise see. Permitted (owner decision 2026-08-13); surfaced so it is never blind."},"receivesEmail":{"type":"boolean"}},"required":["membershipId","displayName","email","accountRole","canViewInApp","receivesEmail"],"additionalProperties":false},"ReportRecipientResponse":{"type":"object","properties":{"recipient":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["membershipId"],"additionalProperties":false}},"required":["recipient"],"additionalProperties":false},"ListTreasuryAccountsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TreasuryAccountView"}},"companyBalance":{"type":"array","items":{"$ref":"#/components/schemas/CompanyBalanceSlice"}}},"required":["items","companyBalance"],"additionalProperties":false},"TreasuryAccountView":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"currency":{"type":"string"},"cachedBalance":{"type":"string"},"glCode":{"type":"string"},"isActive":{"type":"boolean"},"bankAccountId":{"type":["string","null"]}},"required":["id","name","type","currency","cachedBalance","glCode","isActive","bankAccountId"],"additionalProperties":false},"CompanyBalanceSlice":{"type":"object","properties":{"currency":{"type":"string"},"totalMinor":{"type":"string"}},"required":["currency","totalMinor"],"additionalProperties":false},"CreateTreasuryAccountResponse":{"type":"object","properties":{"id":{"type":"string"},"openingJournalEntryId":{"type":["string","null"]}},"required":["id","openingJournalEntryId"],"additionalProperties":false},"ListTreasuryTransactionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TreasuryTransactionView"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","total"],"additionalProperties":false},"TreasuryTransactionView":{"type":"object","properties":{"ledgerEntryId":{"type":"string"},"journalEntryId":{"type":"string"},"entryDate":{"type":"string"},"kind":{"type":"string","enum":["inflow","outflow","transfer"]},"amount":{"type":"string"},"currency":{"type":"string"},"accountId":{"type":"string"},"accountName":{"type":"string"},"memo":{"type":["string","null"]},"sourceType":{"type":"string"},"sourceId":{"type":["string","null"]},"bookingId":{"type":["string","null"]},"bookingReferences":{"type":"array","items":{"type":"string"}},"bookingGuestNames":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"entryNumber":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"fiscalYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"book":{"type":"string","enum":["BANK","SALES","PURCH","GEN"]}},"required":["ledgerEntryId","journalEntryId","entryDate","kind","amount","currency","accountId","accountName","memo","sourceType","sourceId","bookingId","bookingReferences","bookingGuestNames","createdAt","entryNumber","fiscalYear","book"],"additionalProperties":false},"RecordTransferResponse":{"type":"object","properties":{"journalEntryId":{"type":"string"},"replayed":{"type":"boolean"}},"required":["journalEntryId","replayed"],"additionalProperties":false},"RecordConversionResponse":{"type":"object","properties":{"conversionId":{"type":"string"},"fromJournalEntryId":{"type":"string"},"toJournalEntryId":{"type":"string"},"differenceMinor":{"type":"string"},"impliedRate":{"type":"string"},"replayed":{"type":"boolean"}},"required":["conversionId","fromJournalEntryId","toJournalEntryId","differenceMinor","impliedRate","replayed"],"additionalProperties":false},"ListOpenChannelReceivablesResponse":{"type":"object","properties":{"receivables":{"type":"array","items":{"$ref":"#/components/schemas/OpenChannelReceivableView"}}},"required":["receivables"],"additionalProperties":false},"OpenChannelReceivableView":{"type":"object","properties":{"bookingId":{"type":"string"},"propertyId":{"type":"string"},"propertyName":{"type":"string"},"reference":{"type":["string","null"]},"checkIn":{"type":"string"},"currency":{"type":"string"},"receivableMinor":{"type":"string"}},"required":["bookingId","propertyId","propertyName","reference","checkIn","currency","receivableMinor"],"additionalProperties":false},"SettleChannelPayoutResponse":{"type":"object","properties":{"payoutId":{"type":"string"},"journalEntryId":{"type":"string"},"residualMinor":{"type":"string"},"replayed":{"type":"boolean"}},"required":["payoutId","journalEntryId","residualMinor","replayed"],"additionalProperties":false},"ListChannelAccountsResponse":{"type":"object","properties":{"accounts":{"type":"array","items":{"$ref":"#/components/schemas/ChannelAccountView"}}},"required":["accounts"],"additionalProperties":false},"ChannelAccountView":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"label":{"type":"string"},"payoutFinancialAccountId":{"type":["string","null"]},"payoutAccountName":{"type":["string","null"]},"payoutCurrency":{"type":["string","null"]}},"required":["id","provider","label","payoutFinancialAccountId","payoutAccountName","payoutCurrency"],"additionalProperties":false},"UpsertChannelAccountResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"PayoutSweepPlanResponse":{"type":"object","properties":{"baseCurrency":{"type":"string"},"legs":{"type":"array","items":{"$ref":"#/components/schemas/SweepPlanLeg"}},"blocked":{"type":"array","items":{"$ref":"#/components/schemas/SweepPlanBlocked"}},"blockedByMoney":{"type":"boolean"}},"required":["baseCurrency","legs","blocked","blockedByMoney"],"additionalProperties":false},"SweepPlanLeg":{"type":"object","properties":{"sourceAccountId":{"type":"string"},"sourceName":{"type":"string"},"sourceCurrency":{"type":"string"},"destinationAccountId":{"type":"string"},"destinationName":{"type":"string"},"destinationCurrency":{"type":"string"},"properties":{"type":"array","items":{"$ref":"#/components/schemas/SweepPlanProperty"}},"amountMinor":{"type":"string"},"carriedBaseMinor":{"type":"string"}},"required":["sourceAccountId","sourceName","sourceCurrency","destinationAccountId","destinationName","destinationCurrency","properties","amountMinor","carriedBaseMinor"],"additionalProperties":false},"SweepPlanProperty":{"type":"object","properties":{"propertyId":{"type":"string"},"propertyName":{"type":"string"},"amountMinor":{"type":"string"},"carriedBaseMinor":{"type":"string"}},"required":["propertyId","propertyName","amountMinor","carriedBaseMinor"],"additionalProperties":false},"SweepPlanBlocked":{"type":"object","properties":{"sourceAccountId":{"type":"string"},"sourceName":{"type":"string"},"propertyId":{"type":["string","null"]},"propertyName":{"type":"string"},"amountMinor":{"type":"string"},"reason":{"type":"string","enum":["no_bank_assigned","bank_has_no_store","store_inactive","store_currency_mismatch"]}},"required":["sourceAccountId","sourceName","propertyId","propertyName","amountMinor","reason"],"additionalProperties":false},"ExecutePayoutSweepResponse":{"type":"object","properties":{"sweepId":{"type":"string"},"conversionIds":{"type":"array","items":{"type":"string"}},"totalDifferenceMinor":{"type":"string"}},"required":["sweepId","conversionIds","totalDifferenceMinor"],"additionalProperties":false},"OwnerPayableResponse":{"type":"object","properties":{"owner":{"type":"array","items":{"$ref":"#/components/schemas/PayableSlice"}},"investor":{"type":"array","items":{"$ref":"#/components/schemas/PayableSlice"}}},"required":["owner","investor"],"additionalProperties":false},"PayableSlice":{"type":"object","properties":{"propertyId":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"balance":{"type":"string"},"currency":{"type":"string"}},"required":["propertyId","propertyName","balance","currency"],"additionalProperties":false},"RequestExpenseReceiptUploadResponse":{"type":"object","properties":{"objectKey":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["objectKey","uploadUrl","requiredHeaders"],"additionalProperties":false},"AttachExpenseReceiptResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"ListExpenseReceiptsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseReceiptView"}}},"required":["items"],"additionalProperties":false},"ExpenseReceiptView":{"type":"object","properties":{"id":{"type":"string"},"contentType":{"type":"string"},"byteSize":{"type":["string","null"]},"label":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","contentType","byteSize","label","createdAt"],"additionalProperties":false},"ExpenseReceiptViewUrlResponse":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"contentType":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","url","contentType","expiresInSeconds"],"additionalProperties":false},"RemoveExpenseReceiptResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"ListExpenseCategoriesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseCategoryView"}}},"required":["items"],"additionalProperties":false},"ExpenseCategoryView":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"parentId":{"type":["string","null"]},"accountClass":{"type":"string"},"costBehavior":{"anyOf":[{"type":"string","enum":["fixed","variable"]},{"type":"null"}]},"isSystem":{"type":"boolean"},"isActive":{"type":"boolean"}},"required":["id","key","name","parentId","accountClass","costBehavior","isSystem","isActive"],"additionalProperties":false},"ExpenseCategoryResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"ListExpensesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ExpenseView"}},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["items","total"],"additionalProperties":false},"ExpenseView":{"type":"object","properties":{"id":{"type":"string"},"categoryId":{"type":"string"},"categoryName":{"type":"string"},"accountClass":{"type":"string"},"scope":{"type":"string","enum":["tenant","property","listing"]},"propertyId":{"type":["string","null"]},"listingId":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"propertyCode":{"type":["string","null"]},"listingCode":{"type":["string","null"]},"amount":{"type":"string"},"currency":{"type":"string"},"incurredOn":{"type":"string"},"paidFromName":{"type":["string","null"]},"vendor":{"type":["string","null"]},"memo":{"type":["string","null"]},"passThroughFlag":{"type":"boolean"},"journalEntryId":{"type":"string"},"settlementStatus":{"type":"string","enum":["paid","unpaid","settled"]},"billId":{"type":["string","null"]},"billDueOn":{"type":["string","null"]},"claimedByMembershipId":{"type":["string","null"]},"claimedByName":{"type":["string","null"]},"correctedAt":{"type":["string","null"]},"correctionReason":{"type":["string","null"]}},"required":["id","categoryId","categoryName","accountClass","scope","propertyId","listingId","propertyName","propertyCode","listingCode","amount","currency","incurredOn","paidFromName","vendor","memo","passThroughFlag","journalEntryId","settlementStatus","billId","billDueOn","claimedByMembershipId","claimedByName","correctedAt","correctionReason"],"additionalProperties":false},"RecordExpenseResponse":{"type":"object","properties":{"id":{"type":"string"},"journalEntryId":{"type":"string"},"replayed":{"type":"boolean"},"passThroughApplied":{"type":"boolean"},"passThroughRefusal":{"anyOf":[{"type":"string","enum":["not_managed","mixed_building"]},{"type":"null"}]}},"required":["id","journalEntryId","replayed","passThroughApplied","passThroughRefusal"],"additionalProperties":false},"UpdateExpenseDetailsResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"CorrectExpenseResponse":{"type":"object","properties":{"id":{"type":"string"},"journalEntryId":{"type":"string"},"reversalJournalEntryId":{"type":"string"},"replayed":{"type":"boolean"},"passThroughApplied":{"type":"boolean"},"passThroughRefusal":{"anyOf":[{"type":"string","enum":["not_managed","mixed_building"]},{"type":"null"}]}},"required":["id","journalEntryId","reversalJournalEntryId","replayed","passThroughApplied","passThroughRefusal"],"additionalProperties":false},"ListVendorBillsResponse":{"type":"object","properties":{"bills":{"type":"array","items":{"$ref":"#/components/schemas/VendorBillView"}},"outstandingMinor":{"type":"string"},"overdueMinor":{"type":"string"},"reimbursementMinor":{"type":"string"},"currency":{"type":"string"}},"required":["bills","outstandingMinor","overdueMinor","reimbursementMinor","currency"],"additionalProperties":false},"VendorBillView":{"type":"object","properties":{"id":{"type":"string"},"expenseId":{"type":"string"},"vendor":{"type":["string","null"]},"categoryName":{"type":"string"},"propertyName":{"type":["string","null"]},"claimedByMembershipId":{"type":["string","null"]},"claimedByName":{"type":["string","null"]},"billedOn":{"type":"string"},"dueOn":{"type":"string"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string"},"settledOn":{"type":["string","null"]},"paidFromName":{"type":["string","null"]},"reference":{"type":["string","null"]},"note":{"type":["string","null"]},"voidedAt":{"type":["string","null"]},"voidReason":{"type":["string","null"]},"daysOverdue":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","expenseId","vendor","categoryName","propertyName","claimedByMembershipId","claimedByName","billedOn","dueOn","amountMinor","currency","status","settledOn","paidFromName","reference","note","voidedAt","voidReason","daysOverdue"],"additionalProperties":false},"RecordVendorBillResponse":{"type":"object","properties":{"id":{"type":"string"},"expenseId":{"type":"string"},"journalEntryId":{"type":"string"},"replayed":{"type":"boolean"},"passThroughApplied":{"type":"boolean"},"passThroughRefusal":{"anyOf":[{"type":"string","enum":["not_managed","mixed_building"]},{"type":"null"}]}},"required":["id","expenseId","journalEntryId","replayed","passThroughApplied","passThroughRefusal"],"additionalProperties":false},"SettleVendorBillResponse":{"type":"object","properties":{"journalEntryId":{"type":"string"},"replayed":{"type":"boolean"}},"required":["journalEntryId","replayed"],"additionalProperties":false},"VoidVendorBillResponse":{"type":"object","properties":{"journalEntryId":{"type":"string"},"replayed":{"type":"boolean"}},"required":["journalEntryId","replayed"],"additionalProperties":false},"PropertyFinanceResponse":{"type":"object","properties":{"currentModel":{"anyOf":[{"type":"string","enum":["owned","leased","managed","profit_share","investor"]},{"type":"null"}]},"modelHistory":{"type":"array","items":{"$ref":"#/components/schemas/ModelHistoryRow"}},"lease":{"anyOf":[{"$ref":"#/components/schemas/LeaseAgreementView"},{"type":"null"}]},"management":{"anyOf":[{"$ref":"#/components/schemas/ManagementAgreementView"},{"type":"null"}]},"investment":{"anyOf":[{"$ref":"#/components/schemas/InvestmentAgreementView"},{"type":"null"}]},"investmentAgreements":{"type":"array","items":{"$ref":"#/components/schemas/InvestmentAgreementView"}},"investments":{"type":"array","items":{"$ref":"#/components/schemas/PropertyInvestmentView"},"description":"DEPRECATED (slice 0b-1) — use `capitalLines`, which also covers the `asset` register. This field is frozen on the legacy `property_investment` table and will stop growing once capex writes move to the register."},"capitalLines":{"type":"array","items":{"$ref":"#/components/schemas/CapitalLineView"}},"sources":{"type":"object","properties":{"model":{"anyOf":[{"type":"string","enum":["listing","property"]},{"type":"null"}]},"lease":{"anyOf":[{"type":"string","enum":["listing","property"]},{"type":"null"}]},"management":{"anyOf":[{"type":"string","enum":["listing","property"]},{"type":"null"}]},"investment":{"anyOf":[{"type":"string","enum":["listing","property"]},{"type":"null"}]}},"required":["model","lease","management","investment"],"additionalProperties":false}},"required":["currentModel","modelHistory","lease","management","investment","investmentAgreements","investments","capitalLines","sources"],"additionalProperties":false},"ModelHistoryRow":{"type":"object","properties":{"id":{"type":"string"},"model":{"type":"string","enum":["owned","leased","managed","profit_share","investor"]},"effectiveFrom":{"type":"string"},"effectiveTo":{"type":["string","null"]}},"required":["id","model","effectiveFrom","effectiveTo"],"additionalProperties":false},"LeaseAgreementView":{"type":"object","properties":{"id":{"type":"string"},"landlordPartyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"landlordName":{"type":["string","null"]},"rentMinor":{"type":"string"},"currency":{"type":"string"},"termStart":{"type":"string"},"termEnd":{"type":["string","null"]},"depositMinor":{"type":["string","null"]},"landlordProfitSharePct":{"type":"string"},"effectiveFrom":{"type":["string","null"]}},"required":["id","landlordPartyId","landlordName","rentMinor","currency","termStart","termEnd","depositMinor","landlordProfitSharePct","effectiveFrom"],"additionalProperties":false},"ManagementAgreementView":{"type":"object","properties":{"id":{"type":"string"},"ownerPartyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"ownerName":{"type":["string","null"]},"feeBase":{"type":"string","enum":["net","gross","revenue_split"]},"feePct":{"type":"string"},"reserveFloatPct":{"type":"string"},"payoutSchedule":{"type":"string"},"effectiveFrom":{"type":["string","null"]}},"required":["id","ownerPartyId","ownerName","feeBase","feePct","reserveFloatPct","payoutSchedule","effectiveFrom"],"additionalProperties":false},"InvestmentAgreementView":{"type":"object","properties":{"id":{"type":"string"},"investorPartyId":{"type":["string","null"]},"investorName":{"type":["string","null"]},"returnModel":{"type":"string","enum":["pro_rata_split","preferred_return_then_split"]},"investorSplitPct":{"type":"string"},"unitsHeld":{"type":["string","null"]},"capitalMinor":{"type":["string","null"]},"capitalCurrency":{"type":["string","null"]},"effectiveFrom":{"type":"string"},"termStart":{"type":["string","null"]},"termEnd":{"type":["string","null"]}},"required":["id","investorPartyId","investorName","returnModel","investorSplitPct","unitsHeld","capitalMinor","capitalCurrency","effectiveFrom","termStart","termEnd"],"additionalProperties":false},"PropertyInvestmentView":{"type":"object","properties":{"id":{"type":"string"},"listingId":{"type":["string","null"]},"kind":{"type":"string","enum":["purchase","renovation","fitout"]},"fundedBy":{"type":"string","enum":["operator","owner","investor"]},"amount":{"type":"string"},"currency":{"type":"string"},"incurredOn":{"type":"string"},"memo":{"type":["string","null"]}},"required":["id","listingId","kind","fundedBy","amount","currency","incurredOn","memo"],"additionalProperties":false},"CapitalLineView":{"type":"object","properties":{"id":{"type":"string"},"source":{"type":"string","enum":["asset","property_investment"]},"listingId":{"type":["string","null"]},"kind":{"anyOf":[{"type":"string","enum":["purchase","renovation","fitout"]},{"type":"null"}]},"category":{"type":["string","null"]},"name":{"type":["string","null"]},"fundedBy":{"type":"string","enum":["operator","owner","investor"]},"funderPartyId":{"type":["string","null"]},"funderName":{"type":["string","null"]},"amount":{"type":"string"},"currency":{"type":"string"},"incurredOn":{"type":"string"},"memo":{"type":["string","null"]},"postedJournalEntryId":{"type":["string","null"]}},"required":["id","source","listingId","kind","category","name","fundedBy","funderPartyId","funderName","amount","currency","incurredOn","memo","postedJournalEntryId"],"additionalProperties":false},"FinanceConfigResult":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"ApplyPoolEquityResponse":{"type":"object","properties":{"splits":{"type":"array","items":{"$ref":"#/components/schemas/PoolEquitySplit"}}},"required":["splits"],"additionalProperties":false},"PoolEquitySplit":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"splitPct":{"type":"string"},"units":{"type":"string"}},"required":["partyId","name","splitPct","units"],"additionalProperties":false},"AddPropertyCapitalLineResponse":{"type":"object","properties":{"id":{"type":"string"},"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","journalEntryId"],"additionalProperties":false},"StayClassRevenueResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"currency":{"type":"string"},"rows":{"type":"array","items":{"type":"object","properties":{"stayClass":{"type":"string","enum":["short","weekly","monthly","unclassified"]},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"revenueMinor":{"type":"string"},"shareBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["stayClass","nights","revenueMinor","shareBp"],"additionalProperties":false}},"totalMinor":{"type":"string"},"totalNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["from","to","currency","rows","totalMinor","totalNights"],"additionalProperties":false},"OccupancyReportResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"summary":{"$ref":"#/components/schemas/OccupancySummary"},"byListing":{"type":"array","items":{"$ref":"#/components/schemas/OccupancyListingRow"}},"byDow":{"type":"array","items":{"$ref":"#/components/schemas/OccupancyDowRow"}}},"required":["from","to","summary","byListing","byDow"],"additionalProperties":false},"OccupancySummary":{"type":"object","properties":{"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"adrMinor":{"type":"string"},"revparMinor":{"type":"string"},"currency":{"type":"string"},"airbnbNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"otaNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Nights an OTA collected the money for, Airbnb included (0439)."},"offlineNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Occupied nights minus `otaNights`."}},"required":["occupiedNights","availableNights","occupancyBp","adrMinor","revparMinor","currency","airbnbNights","otaNights","offlineNights"],"additionalProperties":false},"OccupancyListingRow":{"type":"object","properties":{"listingId":{"type":"string"},"listingCode":{"type":"string"},"propertyName":{"type":"string"},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["listingId","listingCode","propertyName","occupiedNights","availableNights","occupancyBp"],"additionalProperties":false},"OccupancyDowRow":{"type":"object","properties":{"dow":{"type":"integer","minimum":0,"maximum":6},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["dow","occupiedNights","availableNights","occupancyBp"],"additionalProperties":false},"ComplimentaryStaysResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string","description":"EXCLUSIVE — the half-open check-in window."},"currency":{"type":"string"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/ComplimentaryStayRow"}},"byReason":{"type":"array","items":{"$ref":"#/components/schemas/ComplimentaryReasonTotal"},"description":"EVERY reason in the vocabulary, including those with no stays in the window: \"we gave away nothing on goodwill\" is a real answer that an omitted row cannot express."},"totalValueMinor":{"type":"string"},"totalStays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["from","to","currency","rows","byReason","totalValueMinor","totalStays","totalNights"],"additionalProperties":false},"ComplimentaryStayRow":{"type":"object","properties":{"inquiryId":{"type":"string"},"referenceCode":{"type":"string","description":"The human-facing reservation reference."},"guestName":{"type":["string","null"]},"reason":{"type":"string","description":"WHY the stay was given away (closed vocabulary)."},"note":{"type":["string","null"]},"checkIn":{"type":"string"},"checkOut":{"type":"string"},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unitCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many units the DEAL covered. ⚠️ A LABEL, never a multiplier: valueMinor already describes the whole deal, so multiplying by this would report a group comp as several times its worth."},"unitCodes":{"type":"array","items":{"type":"string"}},"propertyName":{"type":["string","null"]},"valueMinor":{"type":"string","description":"The LIST value of the stay in minor units — what it would have sold for. ⚠️ NOT REVENUE AND NOT A LEDGER FIGURE: a complimentary stay posts no journal, so this never reconciles against the P&L or the cash report."},"confirmedAt":{"type":["string","null"]}},"required":["inquiryId","referenceCode","guestName","reason","note","checkIn","checkOut","nights","unitCount","unitCodes","propertyName","valueMinor","confirmedAt"],"additionalProperties":false},"ComplimentaryReasonTotal":{"type":"object","properties":{"reason":{"type":"string"},"stays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"valueMinor":{"type":"string"},"shareBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"This reason as basis points of the window total (integer arithmetic — a share of money is never computed in floating point here)."}},"required":["reason","stays","nights","valueMinor","shareBp"],"additionalProperties":false},"PnlReportResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"currency":{"type":"string"},"totals":{"type":"object","properties":{"revenueMinor":{"type":"string"},"expenseMinor":{"type":"string"},"noiMinor":{"type":"string"}},"required":["revenueMinor","expenseMinor","noiMinor"],"additionalProperties":false},"groups":{"type":"array","items":{"$ref":"#/components/schemas/PnlModelGroup"}},"lines":{"type":"array","items":{"$ref":"#/components/schemas/PnlLine"}},"trend":{"type":"array","items":{"$ref":"#/components/schemas/PnlTrendPoint"}},"trendGrain":{"type":"string","enum":["day","month"]},"scope":{"$ref":"#/components/schemas/EstateScope"},"dimensions":{"$ref":"#/components/schemas/EstateDimensions"}},"required":["from","to","currency","totals","groups","lines","trend","trendGrain","scope","dimensions"],"additionalProperties":false},"PnlModelGroup":{"type":"object","properties":{"model":{"type":"string"},"revenueMinor":{"type":"string"},"expenseMinor":{"type":"string"},"noiMinor":{"type":"string"},"stayClasses":{"$ref":"#/components/schemas/PnlStayClassSplit"},"properties":{"type":"array","items":{"$ref":"#/components/schemas/PnlPropertyRow"}}},"required":["model","revenueMinor","expenseMinor","noiMinor","stayClasses","properties"],"additionalProperties":false},"PnlStayClassSplit":{"type":"object","properties":{"shortMinor":{"type":"string"},"weeklyMinor":{"type":"string"},"monthlyMinor":{"type":"string"},"unclassedMinor":{"type":"string"}},"required":["shortMinor","weeklyMinor","monthlyMinor","unclassedMinor"],"additionalProperties":false},"PnlPropertyRow":{"type":"object","properties":{"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyName":{"type":"string"},"model":{"type":"string"},"revenueMinor":{"type":"string"},"expenseMinor":{"type":"string"},"noiMinor":{"type":"string"},"accruedFeeMinor":{"type":["string","null"]},"stayClasses":{"$ref":"#/components/schemas/PnlStayClassSplit"},"listings":{"type":"array","items":{"$ref":"#/components/schemas/PnlListingRow"}}},"required":["propertyId","propertyName","model","revenueMinor","expenseMinor","noiMinor","accruedFeeMinor","stayClasses","listings"],"additionalProperties":false},"PnlListingRow":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":"string"},"model":{"type":"string"},"revenueMinor":{"type":"string"},"expenseMinor":{"type":"string"},"noiMinor":{"type":"string"},"accruedFeeMinor":{"type":["string","null"]},"stayClasses":{"$ref":"#/components/schemas/PnlStayClassSplit"}},"required":["listingId","listingCode","model","revenueMinor","expenseMinor","noiMinor","accruedFeeMinor","stayClasses"],"additionalProperties":false},"PnlLine":{"type":"object","properties":{"model":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["income","expense"]},"amountMinor":{"type":"string"}},"required":["model","code","name","kind","amountMinor"],"additionalProperties":false},"PnlTrendPoint":{"type":"object","properties":{"bucket":{"type":"string"},"model":{"type":"string"},"revenueMinor":{"type":"string"},"expenseMinor":{"type":"string"}},"required":["bucket","model","revenueMinor","expenseMinor"],"additionalProperties":false},"EstateScope":{"type":"object","properties":{"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["propertyId","listingTypeId","listingId"],"additionalProperties":false},"EstateDimensions":{"type":"object","properties":{"properties":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"code":{"type":"string"}},"required":["id","name","code"],"additionalProperties":false}},"listingTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","name","propertyId"],"additionalProperties":false}},"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id","listingCode","propertyId","listingTypeId"],"additionalProperties":false}}},"required":["properties","listingTypes","listings"],"additionalProperties":false},"PropertyReportResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"kind":{"type":"string","enum":["income","expense"]},"grain":{"type":"string","enum":["property","listing_type","listing"]},"currency":{"type":"string"},"totalMinor":{"type":"string"},"deferredMinor":{"type":["string","null"]},"entryCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"rows":{"type":"array","items":{"$ref":"#/components/schemas/PropertyReportRow"}},"accounts":{"type":"array","items":{"$ref":"#/components/schemas/PropertyReportAccountRow"}},"buckets":{"type":"array","items":{"$ref":"#/components/schemas/PropertyReportBucket"}},"bucketGrain":{"type":"string","enum":["day","month"]},"entries":{"type":"array","items":{"$ref":"#/components/schemas/PropertyReportEntry"}},"entriesTruncated":{"type":"boolean"},"entryLimit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"filters":{"$ref":"#/components/schemas/PropertyReportFilters"},"dimensions":{"$ref":"#/components/schemas/PropertyReportDimensions"}},"required":["from","to","kind","grain","currency","totalMinor","deferredMinor","entryCount","rows","accounts","buckets","bucketGrain","entries","entriesTruncated","entryLimit","filters","dimensions"],"additionalProperties":false},"PropertyReportRow":{"type":"object","properties":{"key":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyName":{"type":"string"},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeName":{"type":["string","null"]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":["string","null"]},"amountMinor":{"type":"string"},"entryCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"shareBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"accounts":{"type":"array","items":{"$ref":"#/components/schemas/PropertyReportAccountRow"}}},"required":["key","propertyId","propertyName","listingTypeId","listingTypeName","listingId","listingCode","amountMinor","entryCount","shareBp","accounts"],"additionalProperties":false},"PropertyReportAccountRow":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"amountMinor":{"type":"string"}},"required":["code","name","amountMinor"],"additionalProperties":false},"PropertyReportBucket":{"type":"object","properties":{"bucket":{"type":"string"},"amountMinor":{"type":"string"}},"required":["bucket","amountMinor"],"additionalProperties":false},"PropertyReportEntry":{"type":"object","properties":{"id":{"type":"string"},"entryDate":{"type":"string"},"entryNumber":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"memo":{"type":["string","null"]},"accountCode":{"type":"string"},"accountName":{"type":"string"},"propertyName":{"type":["string","null"]},"listingTypeName":{"type":["string","null"]},"listingCode":{"type":["string","null"]},"amountMinor":{"type":"string"}},"required":["id","entryDate","entryNumber","memo","accountCode","accountName","propertyName","listingTypeName","listingCode","amountMinor"],"additionalProperties":false},"PropertyReportFilters":{"type":"object","properties":{"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingTypeId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"accountCode":{"type":["string","null"]}},"required":["propertyId","listingTypeId","listingId","accountCode"],"additionalProperties":false},"PropertyReportDimensions":{"type":"object","properties":{"properties":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"code":{"type":"string"}},"required":["id","name","code"],"additionalProperties":false}},"listingTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","name","propertyId"],"additionalProperties":false}},"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id","listingCode","propertyId","listingTypeId"],"additionalProperties":false}},"accounts":{"type":"array","items":{"$ref":"#/components/schemas/PropertyReportAccountOption"}}},"required":["properties","listingTypes","listings","accounts"],"additionalProperties":false},"PropertyReportAccountOption":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}},"required":["code","name"],"additionalProperties":false},"CustomReportCatalogResponse":{"type":"object","properties":{"datasets":{"type":"array","items":{"$ref":"#/components/schemas/CustomReportDatasetOption"}},"dimensions":{"$ref":"#/components/schemas/EstateDimensions"},"baseCurrency":{"type":"string","minLength":3,"maxLength":3},"timezone":{"type":"string"},"today":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"maxRows":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["datasets","dimensions","baseCurrency","timezone","today","maxRows"],"additionalProperties":false},"CustomReportDatasetOption":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"group":{"type":"string"},"exclusions":{"type":["string","null"]},"defaultDateField":{"type":"string"},"defaultColumns":{"type":"array","items":{"type":"string"}},"fields":{"type":"array","items":{"$ref":"#/components/schemas/CustomReportFieldOption"}}},"required":["key","label","description","group","exclusions","defaultDateField","defaultColumns","fields"],"additionalProperties":false},"CustomReportFieldOption":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"kind":{"type":"string","enum":["text","date","timestamp","number","money","boolean","percent"]},"group":{"type":"string"},"filterable":{"type":"boolean"},"groupable":{"type":"boolean"},"operators":{"type":"array","items":{"type":"string","enum":["eq","ne","in","not_in","contains","not_contains","starts_with","ends_with","gt","gte","lt","lte","between","is_null","is_not_null","is_empty","is_not_empty"]}},"aggregates":{"type":"array","items":{"type":"string","enum":["sum","avg","median","min","max","count","count_distinct"]}},"buckets":{"type":"array","items":{"type":"string","enum":["day","week","month","quarter","year","day_of_week","hour"]}},"options":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"dimension":{"anyOf":[{"type":"string","enum":["property","listing","listing_type"]},{"type":"null"}]},"sensitive":{"type":"boolean"},"hint":{"type":["string","null"]}},"required":["key","label","kind","group","filterable","groupable","operators","aggregates","buckets","options","dimension","sensitive","hint"],"additionalProperties":false},"CustomReportRunResponse":{"type":"object","properties":{"dataset":{"type":"string"},"datasetLabel":{"type":"string"},"datasetDescription":{"type":"string"},"exclusions":{"type":["string","null"]},"mode":{"type":"string","enum":["detail","summary"]},"columns":{"type":"array","items":{"$ref":"#/components/schemas/CustomReportColumn"}},"rows":{"type":"array","items":{"type":"array","items":{"type":["string","null"]}}},"totals":{"anyOf":[{"type":"array","items":{"type":["string","null"]}},{"type":"null"}]},"rowCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"truncated":{"type":"boolean"},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"offset":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"window":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"preset":{"type":["string","null"]}},"required":["field","from","to","preset"],"additionalProperties":false},{"type":"null"}]},"currencyGrouped":{"type":"boolean"},"baseCurrency":{"type":"string","minLength":3,"maxLength":3},"timezone":{"type":"string"},"generatedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["dataset","datasetLabel","datasetDescription","exclusions","mode","columns","rows","totals","rowCount","truncated","limit","offset","window","currencyGrouped","baseCurrency","timezone","generatedOn"],"additionalProperties":false},"CustomReportColumn":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"kind":{"type":"string","enum":["text","date","timestamp","number","money","boolean","percent"]},"aggregate":{"anyOf":[{"type":"string","enum":["sum","avg","median","min","max","count","count_distinct"]},{"type":"null"}]},"align":{"type":"string","enum":["left","right"]},"sensitive":{"type":"boolean"},"currency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"currencyColumnKey":{"type":["string","null"]},"totalled":{"type":"boolean"},"dimension":{"type":"boolean"}},"required":["key","label","kind","aggregate","align","sensitive","currency","currencyColumnKey","totalled","dimension"],"additionalProperties":false},"BreakevenReportResponse":{"type":"object","properties":{"asOf":{"type":"string"},"currency":{"type":"string"},"totalOperatorCapexMinor":{"type":"string"},"capexByModel":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"capexMinor":{"type":"string"}},"required":["model","capexMinor"],"additionalProperties":false}},"models":{"type":"array","items":{"$ref":"#/components/schemas/BreakevenModelGroup"}},"rows":{"type":"array","items":{"$ref":"#/components/schemas/BreakevenRow"}}},"required":["asOf","currency","totalOperatorCapexMinor","capexByModel","models","rows"],"additionalProperties":false},"BreakevenModelGroup":{"type":"object","properties":{"model":{"type":"string"},"capexMinor":{"type":"string"},"netMonthlyMinor":{"type":"string"},"paybackMonths":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"propertyCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"listingCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["model","capexMinor","netMonthlyMinor","paybackMonths","propertyCount","listingCount"],"additionalProperties":false},"BreakevenRow":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"model":{"type":"string"},"operatorCapexMinor":{"type":"string"},"netMonthlyMinor":{"type":"string"},"paybackMonths":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capRateBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"monthlyFixedMinor":{"type":["string","null"]},"trailingAdrMinor":{"type":["string","null"]},"trailingOccupancyBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"breakEvenOccupancyBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"breakEvenAdrMinor":{"type":["string","null"]},"listings":{"type":"array","items":{"$ref":"#/components/schemas/BreakevenListingRow"}}},"required":["propertyId","propertyName","model","operatorCapexMinor","netMonthlyMinor","paybackMonths","capRateBp","monthlyFixedMinor","trailingAdrMinor","trailingOccupancyBp","breakEvenOccupancyBp","breakEvenAdrMinor","listings"],"additionalProperties":false},"BreakevenListingRow":{"type":"object","properties":{"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":"string"},"operatorCapexMinor":{"type":"string"},"netMonthlyMinor":{"type":"string"},"paybackMonths":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capRateBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["listingId","listingCode","operatorCapexMinor","netMonthlyMinor","paybackMonths","capRateBp"],"additionalProperties":false},"MonthlyBreakevenResponse":{"type":"object","properties":{"month":{"type":"string"},"daysInMonth":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"today":{"type":"string"},"fixedMinor":{"type":"string"},"variableMinor":{"type":"string"},"revenueMinor":{"type":"string"},"contributionMarginBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"breakEvenDay":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"daily":{"type":"array","items":{"type":"object","properties":{"day":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cumulativeRevenueMinor":{"type":"string"}},"required":["day","cumulativeRevenueMinor"],"additionalProperties":false}},"history":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string"},"breakEvenDay":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["month","breakEvenDay"],"additionalProperties":false}},"currency":{"type":"string"}},"required":["month","daysInMonth","today","fixedMinor","variableMinor","revenueMinor","contributionMarginBp","breakEvenDay","daily","history","currency"],"additionalProperties":false},"ListFeesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/FeeScheduleView"}}},"required":["items"],"additionalProperties":false},"FeeScheduleView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"kind":{"type":"string","enum":["per_stay","per_night","per_guest","tax_pct","tax_per_night"]},"amountMinor":{"type":["string","null"]},"pct":{"type":["string","null"]},"currency":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"minGuests":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"taxable":{"type":"boolean"},"isActive":{"type":"boolean"},"isOptional":{"type":"boolean"},"showOnSite":{"type":"boolean"},"publicName":{"type":["string","null"]},"publicDescription":{"type":["string","null"]},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","kind","amountMinor","pct","currency","propertyId","listingId","minGuests","taxable","isActive","isOptional","showOnSite","publicName","publicDescription","sortOrder"],"additionalProperties":false},"CreatedIdResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"PaymentsOverviewResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"processedMinor":{"type":"string"},"processedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pendingProofCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"investorPayoutsMtdMinor":{"type":"string"},"currency":{"type":"string"},"recent":{"type":"array","items":{"$ref":"#/components/schemas/PaymentRowView"}},"dualGate":{"type":"array","items":{"$ref":"#/components/schemas/DualGateRow"}},"scope":{"$ref":"#/components/schemas/EstateScope"},"dimensions":{"$ref":"#/components/schemas/EstateDimensions"}},"required":["from","to","processedMinor","processedCount","pendingProofCount","investorPayoutsMtdMinor","currency","recent","dualGate","scope","dimensions"],"additionalProperties":false},"PaymentRowView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingId":{"type":["string","null"]},"bookingReference":{"type":["string","null"]},"inquiryId":{"type":["string","null"]},"inquiryReference":{"type":["string","null"]},"bookingGroupId":{"type":["string","null"]},"bookingGroupSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"guestName":{"type":["string","null"]},"senderName":{"type":["string","null"]},"note":{"type":["string","null"]},"method":{"type":"string"},"status":{"type":"string"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"receivedOn":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","bookingId","bookingReference","inquiryId","inquiryReference","bookingGroupId","bookingGroupSize","guestName","senderName","note","method","status","amountMinor","currency","receivedOn","createdAt"],"additionalProperties":false},"DualGateRow":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingReference":{"type":"string"},"listingCode":{"type":"string"},"checkIn":{"type":"string"},"paymentState":{"type":"string","enum":["verified","pending","partial","missing"]},"idState":{"type":"string"},"gateClear":{"type":"boolean"},"relayState":{"type":["string","null"]}},"required":["bookingId","bookingReference","listingCode","checkIn","paymentState","idState","gateClear","relayState"],"additionalProperties":false},"WorkspaceSettingsResponse":{"type":"object","properties":{"name":{"type":"string"},"country":{"type":"string","minLength":2,"maxLength":2},"timezone":{"type":"string"},"baseCurrency":{"type":"string","minLength":3,"maxLength":3},"dateFormat":{"type":"string","enum":["dd_mmm_yyyy","mmm_dd_yyyy","iso","dd_mm_yyyy","mm_dd_yyyy"]},"timeFormat":{"type":"string","enum":["h24","h12"]},"currencyLocked":{"type":"boolean"}},"required":["name","country","timezone","baseCurrency","dateFormat","timeFormat","currencyLocked"],"additionalProperties":false},"WhiteLabelView":{"type":"object","properties":{"logoObjectKey":{"type":["string","null"]},"logoContentType":{"type":["string","null"]},"logoUrl":{"type":["string","null"]},"brandColor":{"type":["string","null"]}},"required":["logoObjectKey","logoContentType","logoUrl","brandColor"],"additionalProperties":false},"RequestLogoUploadResponse":{"type":"object","properties":{"objectKey":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["objectKey","uploadUrl","requiredHeaders"],"additionalProperties":false},"WhiteLabelOk":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"QuoteShareView":{"type":"object","properties":{"token":{"type":"string"},"url":{"type":"string"},"createdAt":{"type":"string"},"viewCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastViewedAt":{"type":["string","null"]}},"required":["token","url","createdAt","viewCount","lastViewedAt"],"additionalProperties":false},"RevokeQuoteShareResponse":{"type":"object","properties":{"revoked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["revoked"],"additionalProperties":false},"ListTenantPaymentRailsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TenantPaymentRailView"}}},"required":["items"],"additionalProperties":false},"TenantPaymentRailView":{"type":"object","properties":{"rail":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"label":{"type":"string"},"settlesTo":{"anyOf":[{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},{"type":"null"}]},"enabled":{"type":"boolean"},"custom":{"type":"boolean"}},"required":["rail","label","settlesTo","enabled","custom"],"additionalProperties":false},"ListTreasuryTypesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TenantTreasuryTypeView"}}},"required":["items"],"additionalProperties":false},"TenantTreasuryTypeView":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z][a-z0-9_]{1,40}$"},"label":{"type":"string"},"glCode":{"type":"string"}},"required":["key","label","glCode"],"additionalProperties":false},"RetireTreasuryTypeResponse":{"type":"object","properties":{"retired":{"type":"boolean"}},"required":["retired"],"additionalProperties":false},"ListSaasInvoicesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SaasInvoiceView"}}},"required":["items"],"additionalProperties":false},"SaasInvoiceView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"periodStart":{"type":"string"},"periodEnd":{"type":"string"},"memo":{"type":["string","null"]},"amountDueUsdMinor":{"type":"string"},"status":{"type":"string","enum":["open","receipt_submitted","paid","void"]},"fxRate":{"type":["string","null"]},"settlementCurrency":{"type":"string","minLength":3,"maxLength":3},"expectedSettlementMinor":{"type":["string","null"]},"paidSettlementMinor":{"type":["string","null"]},"receiptReference":{"type":["string","null"]},"receiptRail":{"type":["string","null"]},"verifiedAt":{"type":["string","null"]},"source":{"type":"string","enum":["manual","generated"]},"dueDate":{"type":["string","null"]},"lines":{"type":"array","items":{"$ref":"#/components/schemas/SaasInvoiceLineView"}}},"required":["id","periodStart","periodEnd","memo","amountDueUsdMinor","status","fxRate","settlementCurrency","expectedSettlementMinor","paidSettlementMinor","receiptReference","receiptRail","verifiedAt","source","dueDate","lines"],"additionalProperties":false},"SaasInvoiceLineView":{"type":"object","properties":{"kind":{"type":"string","enum":["plan_base","addon","metered_usage","adjustment","credit","manual"]},"description":{"type":"string"},"quantity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unitAmountUsdMinor":{"type":"string"},"amountUsdMinor":{"type":"string"},"meterKey":{"type":["string","null"]},"periodStart":{"type":["string","null"]},"periodEnd":{"type":["string","null"]}},"required":["kind","description","quantity","unitAmountUsdMinor","amountUsdMinor","meterKey","periodStart","periodEnd"],"additionalProperties":false},"ListSaasPaymentsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SaasPaymentView"}}},"required":["items"],"additionalProperties":false},"SaasPaymentView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"invoiceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"method":{"type":"string","enum":["bank_transfer","cash"]},"amountSettlementMinor":{"type":"string"},"settlementCurrency":{"type":"string","minLength":3,"maxLength":3},"paidAt":{"type":"string"},"notes":{"type":["string","null"]},"bankTxnRef":{"type":["string","null"]},"receiptNumber":{"type":["string","null"]},"receivedByName":{"type":["string","null"]},"receivedLocation":{"type":["string","null"]},"recordedByKind":{"type":"string","enum":["tenant","platform"]},"status":{"type":"string","enum":["pending_verification","pending_second_approval","verified","rejected"]},"requiresSecondApproval":{"type":"boolean"},"rejectionKind":{"anyOf":[{"type":"string","enum":["proof_unclear","invalid_payment"]},{"type":"null"}]},"rejectionNote":{"type":["string","null"]},"createdAt":{"type":"string"},"evidence":{"type":"array","items":{"$ref":"#/components/schemas/SaasPaymentEvidenceView"}}},"required":["id","invoiceId","method","amountSettlementMinor","settlementCurrency","paidAt","notes","bankTxnRef","receiptNumber","receivedByName","receivedLocation","recordedByKind","status","requiresSecondApproval","rejectionKind","rejectionNote","createdAt","evidence"],"additionalProperties":false},"SaasPaymentEvidenceView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"contentType":{"type":"string"},"url":{"type":"string","description":"A short-lived presigned GET url for the proof object."}},"required":["id","contentType","url"],"additionalProperties":false},"SubmitSaasPaymentResponse":{"type":"object","properties":{"paymentId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"receiptNumber":{"description":"System-issued for cash at the point of record (spec 3.5); null for transfers.","type":["string","null"]}},"required":["paymentId","receiptNumber"],"additionalProperties":false},"RequestPaymentEvidenceResponse":{"type":"object","properties":{"evidenceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["evidenceId","uploadUrl","requiredHeaders"],"additionalProperties":false},"ConfirmPaymentEvidenceResponse":{"type":"object","properties":{"evidenceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"byteSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["evidenceId","byteSize"],"additionalProperties":false},"ChangePlanResponse":{"type":"object","properties":{"applied":{"type":"string","enum":["immediate","scheduled"]},"pendingChangeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["applied"],"additionalProperties":false},"CancelPendingPlanChangeResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"ListInvitationsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InvitationView"}}},"required":["items"],"additionalProperties":false},"InvitationView":{"type":"object","properties":{"invitationId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"email":{"type":"string"},"name":{"type":["string","null"]},"accountRole":{"type":"string"},"operationalRoleKeys":{"type":"array","items":{"type":"string"}},"expiresAt":{"type":"string"},"createdAt":{"type":"string"}},"required":["invitationId","email","name","accountRole","operationalRoleKeys","expiresAt","createdAt"],"additionalProperties":false},"RevokeInvitationResponse":{"type":"object","properties":{"revoked":{"type":"boolean","const":true}},"required":["revoked"],"additionalProperties":false},"ListMembersResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MemberView"}}},"required":["items"],"additionalProperties":false},"MemberView":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":["string","null"]},"email":{"type":"string"},"phone":{"type":["string","null"]},"accountRole":{"type":"string"},"seatStatus":{"type":"string"},"operationalRoles":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"}},"required":["key","name"],"additionalProperties":false}},"teamRoles":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"teamName":{"type":"string"}},"required":["key","name","teamName"],"additionalProperties":false}},"teams":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"isSelf":{"type":"boolean"},"createdAt":{"type":"string"},"emailConfirmed":{"type":"boolean"}},"required":["membershipId","name","email","phone","accountRole","seatStatus","operationalRoles","teamRoles","teams","isSelf","createdAt","emailConfirmed"],"additionalProperties":false},"InviteMemberResponse":{"type":"object","properties":{"membershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"invitationId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"pending":{"type":"boolean"}},"required":["membershipId","invitationId","pending"],"additionalProperties":false},"RemoveMemberResponse":{"type":"object","properties":{"mode":{"type":"string","enum":["deleted","deactivated_retained"]}},"required":["mode"],"additionalProperties":false},"ListTeamsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TeamView"}}},"required":["items"],"additionalProperties":false},"TeamView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"description":{"type":["string","null"]},"members":{"type":"array","items":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["membershipId"],"additionalProperties":false}},"roles":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"}},"required":["key","name"],"additionalProperties":false}}},"required":["id","name","description","members","roles"],"additionalProperties":false},"ListScopeAssignmentsResponse":{"type":"object","properties":{"enforcedRoles":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"}},"required":["key","name"],"additionalProperties":false}},"assignments":{"type":"array","items":{"$ref":"#/components/schemas/ScopeAssignmentView"}},"targets":{"type":"array","items":{"$ref":"#/components/schemas/ScopeTargetView"}}},"required":["enforcedRoles","assignments","targets"],"additionalProperties":false},"ScopeAssignmentView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"subjectKind":{"type":"string","enum":["member","team"]},"membershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"teamId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":["string","null"]}},"required":["id","subjectKind","membershipId","teamId","propertyId","propertyName","listingId","listingCode"],"additionalProperties":false},"ScopeTargetView":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false}}},"required":["propertyId","propertyName","listings"],"additionalProperties":false},"SetEnforcedScopeRolesResponse":{"type":"object","properties":{"enforced":{"type":"array","items":{"type":"string"}},"released":{"type":"array","items":{"type":"string"}}},"required":["enforced","released"],"additionalProperties":false},"ListStaffShiftsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/StaffShiftView"}}},"required":["items"],"additionalProperties":false},"StaffShiftView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"staffName":{"type":["string","null"]},"kind":{"type":"string"},"startAt":{"type":"string"},"endAt":{"type":"string"},"note":{"type":["string","null"]}},"required":["id","membershipId","staffName","kind","startAt","endAt","note"],"additionalProperties":false},"InvestorsOverviewResponse":{"type":"object","properties":{"investors":{"type":"array","items":{"$ref":"#/components/schemas/InvestorManagementView"}},"totals":{"type":"object","properties":{"investorCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"capitalMinor":{"type":"string"},"accruedMinor":{"type":"string"},"distributedMinor":{"type":"string"},"outstandingMinor":{"type":"string"},"propertiesCovered":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["investorCount","capitalMinor","accruedMinor","distributedMinor","outstandingMinor","propertiesCovered"],"additionalProperties":false},"currency":{"type":"string"}},"required":["investors","totals","currency"],"additionalProperties":false},"InvestorManagementView":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"contactName":{"type":["string","null"]},"loginLinked":{"type":"boolean"},"agreements":{"type":"array","items":{"$ref":"#/components/schemas/InvestorAgreementRow"}},"propertiesCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"listingsCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"capitalMinor":{"type":"string"},"contributedMinor":{"type":"string"},"deployedMinor":{"type":"string"},"accruedMinor":{"type":"string"},"distributedMinor":{"type":"string"},"pendingMinor":{"type":"string"},"outstandingMinor":{"type":"string"},"payouts":{"type":"array","items":{"$ref":"#/components/schemas/InvestorPayoutRow"}},"roiBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"multipleBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"paybackMonth":{"type":["string","null"]},"paybackMonthIndex":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"annualisedBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"monthly":{"type":"array","items":{"$ref":"#/components/schemas/InvestorMonthlyAccrual"}}},"required":["partyId","name","contactName","loginLinked","agreements","propertiesCount","listingsCount","capitalMinor","contributedMinor","deployedMinor","accruedMinor","distributedMinor","pendingMinor","outstandingMinor","payouts","roiBp","multipleBp","paybackMonth","paybackMonthIndex","annualisedBp","monthly"],"additionalProperties":false},"InvestorAgreementRow":{"type":"object","properties":{"agreementId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"returnModel":{"type":"string"},"investorSplitPct":{"type":"string"},"capitalMinor":{"type":["string","null"]},"isActive":{"type":"boolean"}},"required":["agreementId","propertyId","propertyName","returnModel","investorSplitPct","capitalMinor","isActive"],"additionalProperties":false},"InvestorPayoutRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string"},"reference":{"type":["string","null"]},"accountName":{"type":"string"},"requestedAt":{"type":"string"},"decidedAt":{"type":["string","null"]},"requestedBySelf":{"type":"boolean"}},"required":["id","amountMinor","currency","status","reference","accountName","requestedAt","decidedAt","requestedBySelf"],"additionalProperties":false},"InvestorMonthlyAccrual":{"type":"object","properties":{"month":{"type":"string"},"accruedMinor":{"type":"string"},"distributedMinor":{"type":"string"}},"required":["month","accruedMinor","distributedMinor"],"additionalProperties":false},"DecideInvestorPayoutResponse":{"type":"object","properties":{"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["journalEntryId"],"additionalProperties":false},"InvestorPortalResponse":{"type":"object","properties":{"partyName":{"type":"string"},"listings":{"type":"array","items":{"$ref":"#/components/schemas/InvestorPortalListing"}},"performance":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"grossMinor":{"type":["string","null"]},"adrMinor":{"type":["string","null"]},"revparMinor":{"type":["string","null"]},"currency":{"type":["string","null"]},"byListing":{"type":"array","items":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyName":{"type":"string"},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"grossMinor":{"type":["string","null"]},"adrMinor":{"type":["string","null"]}},"required":["listingId","listingCode","propertyName","occupiedNights","availableNights","occupancyBp","grossMinor","adrMinor"],"additionalProperties":false}},"byMonth":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string"},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"grossMinor":{"type":["string","null"]}},"required":["month","occupiedNights","grossMinor"],"additionalProperties":false}}},"required":["from","to","occupiedNights","availableNights","occupancyBp","grossMinor","adrMinor","revparMinor","currency","byListing","byMonth"],"additionalProperties":false},"upcoming":{"type":"array","items":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyName":{"type":"string"},"checkIn":{"type":"string"},"checkOut":{"type":"string"},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"channel":{"type":"string"},"grossMinor":{"type":"string"},"currency":{"type":"string"}},"required":["bookingId","listingCode","propertyName","checkIn","checkOut","nights","channel","grossMinor","currency"],"additionalProperties":false}},"payback":{"type":"object","properties":{"capitalMinor":{"type":["string","null"]},"distributedMinor":{"type":["string","null"]},"remainingMinor":{"type":["string","null"]},"roiBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"multipleBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"paybackMonth":{"type":["string","null"]},"paybackMonthIndex":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"annualisedBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"monthsElapsed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"currency":{"type":["string","null"]},"mixedCurrency":{"type":"boolean"}},"required":["capitalMinor","distributedMinor","remainingMinor","roiBp","multipleBp","paybackMonth","paybackMonthIndex","annualisedBp","monthsElapsed","currency","mixedCurrency"],"additionalProperties":false},"capital":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"kind":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"incurredOn":{"type":"string"},"memo":{"type":["string","null"]}},"required":["id","propertyName","kind","amount","currency","incurredOn","memo"],"additionalProperties":false}},"agreements":{"type":"array","items":{"type":"object","properties":{"propertyName":{"type":"string"},"listingCode":{"type":["string","null"]},"returnModel":{"type":"string"},"investorSplitPct":{"type":"string"},"capitalMinor":{"type":["string","null"]},"capitalCurrency":{"type":["string","null"]},"unitsHeld":{"type":["string","null"]},"poolTotalUnits":{"type":["string","null"]},"operatorMgmtSharePct":{"type":["string","null"]}},"required":["propertyName","listingCode","returnModel","investorSplitPct","capitalMinor","capitalCurrency","unitsHeld","poolTotalUnits","operatorMgmtSharePct"],"additionalProperties":false}},"payments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"reference":{"type":["string","null"]},"memo":{"type":["string","null"]},"paidOn":{"type":"string"}},"required":["id","amountMinor","currency","reference","memo","paidOn"],"additionalProperties":false}},"accruedMinor":{"type":"string"},"outstandingMinor":{"type":"string"},"statements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"statementMonth":{"type":"string"},"currency":{"type":"string"},"poolGrossMinor":{"type":"string"},"poolDeductionsMinor":{"type":"string"},"poolNetMinor":{"type":"string"},"shareNetMinor":{"type":"string"},"outstandingMinor":{"type":"string"},"distributableMinor":{"type":"string"}},"required":["id","statementMonth","currency","poolGrossMinor","poolDeductionsMinor","poolNetMinor","shareNetMinor","outstandingMinor","distributableMinor"],"additionalProperties":false}},"monthlyNet":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string"},"shareNetMinor":{"type":"string"},"final":{"type":"boolean"}},"required":["month","shareNetMinor","final"],"additionalProperties":false}},"deployment":{"$ref":"#/components/schemas/DeploymentPlanResponse"}},"required":["partyName","listings","performance","upcoming","payback","capital","agreements","payments","accruedMinor","outstandingMinor","statements","monthlyNet","deployment"],"additionalProperties":false},"InvestorPortalListing":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"grain":{"type":"string","enum":["property","listing"]}},"required":["listingId","listingCode","propertyId","propertyName","grain"],"additionalProperties":false},"DeploymentPlanResponse":{"type":"object","properties":{"lines":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentLineView"}},"summary":{"type":"object","properties":{"plannedMinor":{"type":"string"},"actualMinor":{"type":"string"},"varianceMinor":{"type":"string"},"refundableMinor":{"type":"string"},"depreciatingMinor":{"type":"string"},"consumedMinor":{"type":"string"}},"required":["plannedMinor","actualMinor","varianceMinor","refundableMinor","depreciatingMinor","consumedMinor"],"additionalProperties":false}},"required":["lines","summary"],"additionalProperties":false},"DeploymentLineView":{"type":"object","properties":{"id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"funderPartyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"funderPartyName":{"type":["string","null"]},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":["string","null"]},"category":{"type":"string"},"treatment":{"type":"string","enum":["refundable","depreciating","consumed"]},"plannedMinor":{"type":"string"},"actualMinor":{"type":"string"},"varianceMinor":{"type":"string"},"unplanned":{"type":"boolean"},"currency":{"type":"string"},"note":{"type":["string","null"]}},"required":["id","funderPartyId","funderPartyName","propertyId","propertyName","listingId","listingCode","category","treatment","plannedMinor","actualMinor","varianceMinor","unplanned","currency","note"],"additionalProperties":false},"ListCapitalNoticesResponse":{"type":"object","properties":{"notices":{"type":"array","items":{"$ref":"#/components/schemas/CapitalNoticeRow"}}},"required":["notices"],"additionalProperties":false},"CapitalNoticeRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"splitPct":{"type":"string"},"unitsHeld":{"type":["string","null"]},"effectiveFrom":{"type":["string","null"]},"issuedAt":{"type":"string"},"acknowledgedAt":{"type":["string","null"]},"noticeKind":{"type":"string","enum":["assigned","close_out"]}},"required":["id","propertyId","propertyName","splitPct","unitsHeld","effectiveFrom","issuedAt","acknowledgedAt","noticeKind"],"additionalProperties":false},"InvestorStatementDetailResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"statementMonth":{"type":"string"},"currency":{"type":"string"},"poolGrossMinor":{"type":"string"},"poolDeductionsMinor":{"type":"string"},"poolNetMinor":{"type":"string"},"shareNetMinor":{"type":"string"},"outstandingMinor":{"type":"string"},"distributableMinor":{"type":"string"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/InvestorStatementLine"}}},"required":["id","statementMonth","currency","poolGrossMinor","poolDeductionsMinor","poolNetMinor","shareNetMinor","outstandingMinor","distributableMinor","lines"],"additionalProperties":false},"InvestorStatementLine":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["booking","month_costs","unattributed"]},"bookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":["string","null"]},"guestName":{"type":["string","null"]},"checkIn":{"type":["string","null"]},"checkOut":{"type":["string","null"]},"currency":{"type":"string"},"revenueMinor":{"type":"string"},"deductionsAllocMinor":{"type":"string"},"netMinor":{"type":"string"},"shareMinor":{"type":"string"}},"required":["id","kind","bookingId","listingCode","guestName","checkIn","checkOut","currency","revenueMinor","deductionsAllocMinor","netMinor","shareMinor"],"additionalProperties":false},"AcknowledgeCapitalNoticeResponse":{"type":"object","properties":{"acknowledgedAt":{"type":"string"}},"required":["acknowledgedAt"],"additionalProperties":false},"ExitPreviewResponse":{"type":"object","properties":{"noticeOn":{"type":"string"},"noticeDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"noticeEndsOn":{"type":"string"},"finalAccrualMonth":{"type":"string"},"effectiveTo":{"type":"string"},"computedValueMinor":{"type":"string"},"currency":{"type":"string"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ExitSettlementLine"}}},"required":["noticeOn","noticeDays","noticeEndsOn","finalAccrualMonth","effectiveTo","computedValueMinor","currency","lines"],"additionalProperties":false},"ExitSettlementLine":{"type":"object","properties":{"kind":{"type":"string","enum":["furniture_fmv","refundable_deposit","advance_rent_unamortised","other"]},"amountMinor":{"type":"string"},"basisMissing":{"type":"boolean"}},"required":["kind","amountMinor","basisMissing"],"additionalProperties":false},"ListInvestorExitsResponse":{"type":"object","properties":{"exits":{"type":"array","items":{"$ref":"#/components/schemas/InvestorExitRow"}}},"required":["exits"],"additionalProperties":false},"InvestorExitRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyName":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"noticeOn":{"type":"string"},"noticeEndsOn":{"type":"string"},"finalAccrualMonth":{"type":"string"},"computedValueMinor":{"type":"string"},"overrideValueMinor":{"type":["string","null"]},"overrideReason":{"type":["string","null"]},"settlementMinor":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string"},"requestedBySelf":{"type":"boolean"},"frrDecision":{"anyOf":[{"type":"string","enum":["operator_buys","released_to_investor"]},{"type":"null"}]},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ExitSettlementLine"}}},"required":["id","partyId","partyName","propertyId","propertyName","noticeOn","noticeEndsOn","finalAccrualMonth","computedValueMinor","overrideValueMinor","overrideReason","settlementMinor","currency","status","requestedBySelf","frrDecision","lines"],"additionalProperties":false},"NoticeInvestorExitResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"settlementMinor":{"type":"string"},"effectiveTo":{"type":"string"}},"required":["id","settlementMinor","effectiveTo"],"additionalProperties":false},"DecideInvestorExitResponse":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"],"additionalProperties":false},"SettleInvestorExitResponse":{"type":"object","properties":{"journalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["journalEntryId"],"additionalProperties":false},"InvestorAssignmentsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InvestorAssignmentView"}},"parties":{"type":"array","items":{"$ref":"#/components/schemas/InvestorPartyView"}}},"required":["items","parties"],"additionalProperties":false},"InvestorAssignmentView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyName":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyName":{"type":["string","null"]},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["id","partyId","partyName","propertyId","propertyName","listingId","listingCode","note"],"additionalProperties":false},"InvestorPartyView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string"},"name":{"type":"string"},"linkedMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","kind","name","linkedMembershipId"],"additionalProperties":false},"CreateInvestorPartyResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"created":{"type":"boolean"}},"required":["id","created"],"additionalProperties":false},"ListPayeeAccountsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PayeeAccountView"}}},"required":["items"],"additionalProperties":false},"PayeeAccountView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"membershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"label":{"type":"string"},"route":{"type":"string"},"bankName":{"type":["string","null"]},"accountTitle":{"type":["string","null"]},"accountNumber":{"type":["string","null"]},"iban":{"type":["string","null"]},"payeePhone":{"type":["string","null"]},"cashCarrierMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"isDefault":{"type":"boolean"},"isActive":{"type":"boolean"},"usedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","partyId","membershipId","label","route","bankName","accountTitle","accountNumber","iban","payeePhone","cashCarrierMembershipId","isDefault","isActive","usedCount"],"additionalProperties":false},"RetirePayeeAccountResponse":{"type":"object","properties":{"deactivated":{"type":"boolean"},"usedCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["deactivated","usedCount"],"additionalProperties":false},"ListOperatingModelsResponse":{"type":"object","properties":{"units":{"type":"array","items":{"$ref":"#/components/schemas/OperatingModelUnitView"}},"byModel":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"units":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["model","units"],"additionalProperties":false}},"findingCounts":{"type":"array","items":{"type":"object","properties":{"finding":{"type":"string","enum":["agreement_without_model","owned_with_counterparty"]},"units":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["finding","units"],"additionalProperties":false}},"totalUnits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["units","byModel","findingCounts","totalUnits"],"additionalProperties":false},"OperatingModelUnitView":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"modelInForce":{"type":["string","null"]},"modelGrain":{"anyOf":[{"type":"string","enum":["listing","property"]},{"type":"null"}]},"modelEffectiveFrom":{"type":["string","null"]},"counterparties":{"type":"array","items":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyName":{"type":"string"},"agreementModel":{"type":"string","enum":["managed","leased","profit_share"]},"unitGrain":{"type":"boolean"}},"required":["partyId","partyName","agreementModel","unitGrain"],"additionalProperties":false}},"finding":{"anyOf":[{"type":"string","enum":["agreement_without_model","owned_with_counterparty"]},{"type":"null"}]}},"required":["listingId","listingCode","propertyId","propertyName","modelInForce","modelGrain","modelEffectiveFrom","counterparties","finding"],"additionalProperties":false},"ListOwnersResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/OwnerRowView"}},"unassigned":{"type":"array","items":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"modelInForce":{"type":["string","null"]},"modelGrain":{"anyOf":[{"type":"string","enum":["listing","property"]},{"type":"null"}]},"modelEffectiveFrom":{"type":["string","null"]}},"required":["listingId","listingCode","propertyId","propertyName","modelInForce","modelGrain","modelEffectiveFrom"],"additionalProperties":false}},"totalUnits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"targets":{"type":"array","items":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"modelInForce":{"type":["string","null"]},"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"code":{"type":"string"},"modelInForce":{"type":["string","null"]}},"required":["id","code","modelInForce"],"additionalProperties":false}}},"required":["propertyId","propertyName","modelInForce","listings"],"additionalProperties":false}}},"required":["items","unassigned","totalUnits","targets"],"additionalProperties":false},"OwnerRowView":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"kind":{"type":"string"},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"linkedMembershipId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"holdings":{"type":"array","items":{"$ref":"#/components/schemas/OwnerHoldingView"}},"unitCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"propertyCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"models":{"type":"array","items":{"type":"string","enum":["managed","leased","profit_share"]}}},"required":["partyId","name","kind","email","phone","linkedMembershipId","holdings","unitCount","propertyCount","models"],"additionalProperties":false},"OwnerHoldingView":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"agreementId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"model":{"type":"string","enum":["managed","leased","profit_share"]},"feePct":{"type":["string","null"]},"feeBase":{"type":["string","null"]},"rentMinor":{"type":["string","null"]},"landlordProfitSharePct":{"type":["string","null"]},"currency":{"type":["string","null"]},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"unitGrain":{"type":"boolean"}},"required":["partyId","agreementId","model","feePct","feeBase","rentMinor","landlordProfitSharePct","currency","listingId","listingCode","propertyId","propertyName","unitGrain"],"additionalProperties":false},"CreateOwnerPartyResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"created":{"type":"boolean"}},"required":["id","created"],"additionalProperties":false},"LinkOwnerSeatResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"UnassignOwnerHoldingResponse":{"type":"object","properties":{"releasedUnits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["releasedUnits"],"additionalProperties":false},"CounterpartiesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InvestorPartyView"}}},"required":["items"],"additionalProperties":false},"ListTrackRecordSnapshotsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TrackRecordSnapshotView"}}},"required":["items"],"additionalProperties":false},"TrackRecordSnapshotView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"fromDate":{"type":"string"},"toDate":{"type":"string"},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"grossMinor":{"type":["string","null"]},"adrMinor":{"type":["string","null"]},"revparMinor":{"type":["string","null"]},"currency":{"type":["string","null"]},"nightsHosted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"guestsHosted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reviewsReceived":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"avgRatingMilli":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"spotlightListingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"spotlightListingCode":{"type":["string","null"]},"spotlightPropertyName":{"type":["string","null"]},"spotlightMonth":{"type":["string","null"]},"spotlightOccupancyBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capturedAt":{"type":"string"},"badges":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"label":{"type":"string"},"source":{"type":"string"},"asOf":{"type":"string"}},"required":["id","label","source","asOf"],"additionalProperties":false}}},"required":["id","label","fromDate","toDate","occupiedNights","availableNights","occupancyBp","grossMinor","adrMinor","revparMinor","currency","nightsHosted","guestsHosted","reviewsReceived","avgRatingMilli","spotlightListingId","spotlightListingCode","spotlightPropertyName","spotlightMonth","spotlightOccupancyBp","capturedAt","badges"],"additionalProperties":false},"ListInvestorDealsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/InvestorDealView"}}},"required":["items"],"additionalProperties":false},"InvestorDealView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"status":{"type":"string"},"partyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"partyName":{"type":["string","null"]},"prospectName":{"type":["string","null"]},"proposalId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"agreementId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"propertyName":{"type":["string","null"]},"committedMinor":{"type":"string"},"currency":{"type":"string"},"expectedCloseOn":{"type":["string","null"]},"note":{"type":["string","null"]},"tranches":{"type":"array","items":{"$ref":"#/components/schemas/CapitalTrancheView"}},"scheduledMinor":{"type":"string"},"receivedMinor":{"type":"string"},"outstandingMinor":{"type":"string"}},"required":["id","title","status","partyId","partyName","prospectName","proposalId","agreementId","propertyId","propertyName","committedMinor","currency","expectedCloseOn","note","tranches","scheduledMinor","receivedMinor","outstandingMinor"],"additionalProperties":false},"CapitalTrancheView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"dueOn":{"type":"string"},"amountMinor":{"type":"string"},"label":{"type":["string","null"]},"received":{"type":"boolean"},"contributionId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"receivedMinor":{"type":["string","null"]},"receivedOn":{"type":["string","null"]}},"required":["id","dueOn","amountMinor","label","received","contributionId","receivedMinor","receivedOn"],"additionalProperties":false},"ListUnmatchedContributionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyName":{"type":["string","null"]},"amountMinor":{"type":"string"},"currency":{"type":"string"},"receivedOn":{"type":"string"}},"required":["id","partyId","partyName","amountMinor","currency","receivedOn"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"ListUnitLaunchesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/UnitLaunchView"}},"unenrolled":{"type":"array","items":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyName":{"type":"string"}},"required":["listingId","listingCode","propertyName"],"additionalProperties":false}},"byProperty":{"type":"array","items":{"type":"object","properties":{"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"live":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["propertyId","propertyName","total","live"],"additionalProperties":false}}},"required":["items","unenrolled","byProperty"],"additionalProperties":false},"UnitLaunchView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"targetLiveOn":{"type":"string"},"furnishedOn":{"type":["string","null"]},"photographedOn":{"type":["string","null"]},"listedOn":{"type":["string","null"]},"liveOn":{"type":["string","null"]},"note":{"type":["string","null"]},"stage":{"type":"string","enum":["not_started","furnished","photographed","listed","live"]},"varianceDays":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","listingId","listingCode","propertyId","propertyName","targetLiveOn","furnishedOn","photographedOn","listedOn","liveOn","note","stage","varianceDays"],"additionalProperties":false},"ObservedRampResponse":{"type":"object","properties":{"liveUnits":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"medianDaysToLive":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"medianVarianceDays":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"onOrBeforeTarget":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["liveUnits","medianDaysToLive","medianVarianceDays","onOrBeforeTarget"],"additionalProperties":false},"ListProposalsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ProposalView"}}},"required":["items"],"additionalProperties":false},"ProposalView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"title":{"type":"string"},"partyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"partyName":{"type":["string","null"]},"prospectName":{"type":["string","null"]},"modelId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"modelName":{"type":"string"},"scenarioId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"scenarioLabel":{"type":"string"},"trackRecordSnapshotId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"trackRecordLabel":{"type":"string"},"capitalMinor":{"type":"string"},"unitsMilli":{"type":"string"},"unitPriceMinor":{"type":"string"},"mgmtShareMilliPct":{"type":"string"},"noticeDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"currency":{"type":"string"},"generatedAt":{"type":["string","null"]},"splitMilliPct":{"type":["string","null"]},"totalUnitsMilli":{"type":["string","null"]},"projectedGrossMinor":{"type":["string","null"]},"projectedNetMinor":{"type":["string","null"]},"paybackMonths":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"status":{"type":"string","enum":["draft","sent","viewed","accepted","declined","withdrawn"]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"supersedesId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"sentAt":{"type":["string","null"]},"viewedAt":{"type":["string","null"]},"decidedAt":{"type":["string","null"]},"declineReason":{"type":["string","null"]},"shareToken":{"type":["string","null"]},"shareExpiresAt":{"type":["string","null"]},"shareViewCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","title","partyId","partyName","prospectName","modelId","modelName","scenarioId","scenarioLabel","trackRecordSnapshotId","trackRecordLabel","capitalMinor","unitsMilli","unitPriceMinor","mgmtShareMilliPct","noticeDays","currency","generatedAt","splitMilliPct","totalUnitsMilli","projectedGrossMinor","projectedNetMinor","paybackMonths","status","version","supersedesId","sentAt","viewedAt","decidedAt","declineReason","shareToken","shareExpiresAt","shareViewCount"],"additionalProperties":false},"SendProposalResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"token":{"type":"string"},"expiresAt":{"type":"string"}},"required":["id","token","expiresAt"],"additionalProperties":false},"ReviseProposalResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","version"],"additionalProperties":false},"RevokeProposalShareResponse":{"type":"object","properties":{"revoked":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["revoked"],"additionalProperties":false},"TrackRecordPreviewResponse":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"grossMinor":{"type":["string","null"]},"adrMinor":{"type":["string","null"]},"revparMinor":{"type":["string","null"]},"currency":{"type":["string","null"]},"nightsHosted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"guestsHosted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"reviewsReceived":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"avgRatingMilli":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"spotlight":{"anyOf":[{"$ref":"#/components/schemas/TrackRecordSpotlight"},{"type":"null"}]}},"required":["from","to","occupiedNights","availableNights","occupancyBp","grossMinor","adrMinor","revparMinor","currency","nightsHosted","guestsHosted","reviewsReceived","avgRatingMilli","spotlight"],"additionalProperties":false},"TrackRecordSpotlight":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyName":{"type":"string"},"month":{"type":"string"},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"availableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"occupancyBp":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["listingId","listingCode","propertyName","month","occupiedNights","availableNights","occupancyBp"],"additionalProperties":false},"OwnerPortalResponse":{"type":"object","properties":{"partyName":{"type":"string"},"listings":{"type":"array","items":{"$ref":"#/components/schemas/OwnerPortalListing"}},"month":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"additionalProperties":false},"totals":{"type":"object","properties":{"grossMinor":{"type":"string"},"ownerShareMinor":{"type":"string"},"opexMinor":{"type":"string"},"rentDueMinor":{"type":"string"},"currency":{"type":"string"}},"required":["grossMinor","ownerShareMinor","opexMinor","rentDueMinor","currency"],"additionalProperties":false},"payouts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"periodMonth":{"type":"string"},"status":{"type":"string"},"reference":{"type":["string","null"]},"memo":{"type":["string","null"]},"decidedAt":{"type":["string","null"]}},"required":["id","amountMinor","currency","periodMonth","status","reference","memo","decidedAt"],"additionalProperties":false}},"policy":{"anyOf":[{"type":"object","properties":{"nightsPerPeriod":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"period":{"type":"string"},"allowedWeekdays":{"type":"array","items":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"mayBlockOwnListings":{"type":"boolean"}},"required":["nightsPerPeriod","period","allowedWeekdays","mayBlockOwnListings"],"additionalProperties":false},{"type":"null"}]},"shareBasis":{"type":"string","const":"managed_net_of_allocated_opex"},"ownerReturn":{"type":"object","properties":{"basis":{"type":"string","enum":["capital_return","operating_breakeven","mixed"]},"capitalInvestedMinor":{"type":"string"},"distributionsPaidMinor":{"type":"string"},"returnBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"costsMinor":{"type":"string"},"coverageBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"currency":{"type":"string"}},"required":["basis","capitalInvestedMinor","distributionsPaidMinor","returnBp","costsMinor","coverageBp","currency"],"additionalProperties":false},"monthly":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string"},"grossMinor":{"type":"string"},"ownerShareMinor":{"type":"string"}},"required":["month","grossMinor","ownerShareMinor"],"additionalProperties":false}}},"required":["partyName","listings","month","totals","payouts","policy","shareBasis","ownerReturn","monthly"],"additionalProperties":false},"OwnerPortalListing":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"model":{"type":"string","enum":["managed","leased"]},"feePct":{"type":["string","null"]},"feeBase":{"type":["string","null"]},"reserveFloatPct":{"type":["string","null"]},"rentMinor":{"type":["string","null"]},"landlordProfitSharePct":{"type":["string","null"]},"grossMinor":{"type":"string"},"ownerShareMinor":{"type":"string"},"opexMinor":{"type":"string"},"rentDueMinor":{"type":["string","null"]},"currency":{"type":"string"}},"required":["listingId","listingCode","propertyId","propertyName","model","feePct","feeBase","reserveFloatPct","rentMinor","landlordProfitSharePct","grossMinor","ownerShareMinor","opexMinor","rentDueMinor","currency"],"additionalProperties":false},"ListOwnerStatementsResponse":{"type":"object","properties":{"statements":{"type":"array","items":{"$ref":"#/components/schemas/OwnerStatementRow"}}},"required":["statements"],"additionalProperties":false},"OwnerStatementRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"statementMonth":{"type":"string"},"currency":{"type":"string"},"grossMinor":{"type":"string"},"opexMinor":{"type":"string"},"passThroughMinor":{"type":"string"},"feeMinor":{"type":"string"},"rentDueMinor":{"type":"string"},"shareNetMinor":{"type":"string"}},"required":["id","statementMonth","currency","grossMinor","opexMinor","passThroughMinor","feeMinor","rentDueMinor","shareNetMinor"],"additionalProperties":false},"OwnerStatementDetailResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"statementMonth":{"type":"string"},"currency":{"type":"string"},"grossMinor":{"type":"string"},"opexMinor":{"type":"string"},"passThroughMinor":{"type":"string"},"feeMinor":{"type":"string"},"rentDueMinor":{"type":"string"},"shareNetMinor":{"type":"string"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/OwnerStatementLine"}}},"required":["id","statementMonth","currency","grossMinor","opexMinor","passThroughMinor","feeMinor","rentDueMinor","shareNetMinor","lines"],"additionalProperties":false},"OwnerStatementLine":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["booking","month_costs","unattributed"]},"bookingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"listingCode":{"type":["string","null"]},"guestName":{"type":["string","null"]},"checkIn":{"type":["string","null"]},"checkOut":{"type":["string","null"]},"currency":{"type":"string"},"revenueMinor":{"type":"string"},"opexAllocMinor":{"type":"string"},"passThroughAllocMinor":{"type":"string"},"feeAllocMinor":{"type":"string"},"shareMinor":{"type":"string"}},"required":["id","kind","bookingId","listingCode","guestName","checkIn","checkOut","currency","revenueMinor","opexAllocMinor","passThroughAllocMinor","feeAllocMinor","shareMinor"],"additionalProperties":false},"DecideOwnerPayoutResponse":{"type":"object","properties":{"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["journalEntryId"],"additionalProperties":false},"ListDamageClaimsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/DamageClaimView"}}},"required":["items"],"additionalProperties":false},"DamageClaimView":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"propertyId":{"type":["string","null"]},"listingId":{"type":["string","null"]},"route":{"type":"string","enum":["aircover","direct"]},"status":{"type":"string","enum":["filed","pending","paid","denied"]},"claimedAmountMinor":{"type":"string","pattern":"^\\d+$"},"recoveredAmountMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"currency":{"type":"string"},"filedOn":{"type":"string"},"decidedOn":{"type":["string","null"]},"externalReference":{"type":["string","null"]},"description":{"type":"string"},"recoveryChargeId":{"type":["string","null"]},"denialReason":{"type":["string","null"]}},"required":["id","bookingId","propertyId","listingId","route","status","claimedAmountMinor","recoveredAmountMinor","currency","filedOn","decidedOn","externalReference","description","recoveryChargeId","denialReason"],"additionalProperties":false},"FileDamageClaimResponse":{"type":"object","properties":{"id":{"type":"string"},"route":{"type":"string","enum":["aircover","direct"]}},"required":["id","route"],"additionalProperties":false},"MarkDamageClaimPendingResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"PayDamageClaimResponse":{"type":"object","properties":{"id":{"type":"string"},"chargeId":{"type":"string"},"journalEntryId":{"type":"string"}},"required":["id","chargeId","journalEntryId"],"additionalProperties":false},"DenyDamageClaimResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"RecordBookingChargeResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"journalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id","journalEntryId"],"additionalProperties":false},"ListBookingChargesResponse":{"type":"object","properties":{"charges":{"type":"array","items":{"$ref":"#/components/schemas/BookingChargeRow"}},"totalMinor":{"type":"string"}},"required":["charges","totalMinor"],"additionalProperties":false},"BookingChargeRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string"},"fineKey":{"type":["string","null"]},"label":{"type":"string"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"collectedOn":{"type":"string"},"memo":{"type":["string","null"]},"voidedAt":{"type":["string","null"]},"voidReason":{"type":["string","null"]}},"required":["id","kind","fineKey","label","amountMinor","currency","collectedOn","memo","voidedAt","voidReason"],"additionalProperties":false},"ListChargesResponse":{"type":"object","properties":{"charges":{"type":"array","items":{"$ref":"#/components/schemas/TenantChargeRow"}},"totalMinor":{"type":"string"},"byKind":{"type":"array","items":{"$ref":"#/components/schemas/ChargeKindTotal"}},"currency":{"type":"string"}},"required":["charges","totalMinor","byKind","currency"],"additionalProperties":false},"TenantChargeRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string"},"fineKey":{"type":["string","null"]},"label":{"type":"string"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"collectedOn":{"type":"string"},"memo":{"type":["string","null"]},"voidedAt":{"type":["string","null"]},"voidReason":{"type":["string","null"]},"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"bookingReference":{"type":"string"},"guestName":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"createdAt":{"type":"string"},"entryNumber":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"fiscalYear":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"book":{"type":"string","enum":["BANK","SALES","PURCH","GEN"]}},"required":["id","kind","fineKey","label","amountMinor","currency","collectedOn","memo","voidedAt","voidReason","bookingId","bookingReference","guestName","propertyName","createdAt","entryNumber","fiscalYear","book"],"additionalProperties":false},"ChargeKindTotal":{"type":"object","properties":{"kind":{"type":"string"},"fineKey":{"type":["string","null"]},"countCharges":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"totalMinor":{"type":"string"}},"required":["kind","fineKey","countCharges","totalMinor"],"additionalProperties":false},"DeleteDuplicateBookingResponse":{"type":"object","properties":{"deletedBookingIds":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"nightsReleased":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"dealDeleted":{"type":"boolean"}},"required":["deletedBookingIds","nightsReleased","dealDeleted"],"additionalProperties":false},"DeleteDuplicateInquiryResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"nightsReleased":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lockReleased":{"type":"boolean"}},"required":["id","nightsReleased","lockReleased"],"additionalProperties":false},"DeleteDuplicatePaymentResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"voidJournalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"amountMinor":{"type":"string"},"currency":{"type":"string","minLength":3,"maxLength":3}},"required":["id","voidJournalEntryId","amountMinor","currency"],"additionalProperties":false},"DeleteDuplicateExpenseResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"voidJournalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"replayed":{"type":"boolean"}},"required":["id","voidJournalEntryId","replayed"],"additionalProperties":false},"VoidBookingChargeResponse":{"type":"object","properties":{"voidJournalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["voidJournalEntryId"],"additionalProperties":false},"ListHouseRuleFinesResponse":{"type":"object","properties":{"fines":{"type":"array","items":{"$ref":"#/components/schemas/HouseRuleFineRow"}}},"required":["fines"],"additionalProperties":false},"HouseRuleFineRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"key":{"type":"string"},"name":{"type":"string"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","key","name","amountMinor","currency","propertyId"],"additionalProperties":false},"ListStaffCompensationResponse":{"type":"object","properties":{"rows":{"type":"array","items":{"$ref":"#/components/schemas/StaffCompensationRow"}}},"required":["rows"],"additionalProperties":false},"StaffCompensationRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"staffName":{"type":"string"},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"baseMinor":{"type":"string"},"allowancesMinor":{"type":"string"},"perCleaningMinor":{"type":"string"},"perBookingClosedMinor":{"type":"string"},"currency":{"type":"string"},"paidByThirdParty":{"type":"boolean"},"note":{"type":["string","null"]}},"required":["id","membershipId","staffName","propertyId","baseMinor","allowancesMinor","perCleaningMinor","perBookingClosedMinor","currency","paidByThirdParty","note"],"additionalProperties":false},"PayrollPreviewResponse":{"type":"object","properties":{"month":{"type":"string"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/PayPreviewRow"}},"postableTotalMinor":{"type":"string"},"currency":{"type":"string"}},"required":["month","rows","postableTotalMinor","currency"],"additionalProperties":false},"PayPreviewRow":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"staffName":{"type":"string"},"baseMinor":{"type":"string"},"allowancesMinor":{"type":"string"},"cleaningsCompleted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cleaningAddMinor":{"type":"string"},"bookingsClosed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bookingAddMinor":{"type":"string"},"totalMinor":{"type":"string"},"paidByThirdParty":{"type":"boolean"}},"required":["membershipId","staffName","baseMinor","allowancesMinor","cleaningsCompleted","cleaningAddMinor","bookingsClosed","bookingAddMinor","totalMinor","paidByThirdParty"],"additionalProperties":false},"ListAssetsResponse":{"type":"object","properties":{"assets":{"type":"array","items":{"$ref":"#/components/schemas/AssetRow"}},"totalsByFunder":{"type":"array","items":{"$ref":"#/components/schemas/AssetFunderTotal"}}},"required":["assets","totalsByFunder"],"additionalProperties":false},"AssetRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"subUnitLabel":{"type":["string","null"]},"category":{"type":"string"},"name":{"type":"string"},"funderPartyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"funderName":{"type":["string","null"]},"costMinor":{"type":"string"},"currency":{"type":"string"},"acquiredOn":{"type":"string"},"condition":{"type":["string","null"]},"usefulLifeMonths":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"note":{"type":["string","null"]},"paidFromAccountId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"postedJournalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","propertyId","listingId","subUnitLabel","category","name","funderPartyId","funderName","costMinor","currency","acquiredOn","condition","usefulLifeMonths","note","paidFromAccountId","postedJournalEntryId"],"additionalProperties":false},"AssetFunderTotal":{"type":"object","properties":{"funderPartyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"funderName":{"type":["string","null"]},"costMinor":{"type":"string"}},"required":["funderPartyId","funderName","costMinor"],"additionalProperties":false},"UpsertAssetResponse":{"type":"object","properties":{"id":{"type":"string"},"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["id","journalEntryId"],"additionalProperties":false},"RecordLeaseOutlayResponse":{"type":"object","properties":{"journalEntryId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"replayed":{"type":"boolean"}},"required":["journalEntryId","replayed"],"additionalProperties":false},"TerminateLeaseResponse":{"type":"object","properties":{"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["journalEntryId"],"additionalProperties":false},"TermWatchResponse":{"type":"object","properties":{"rows":{"type":"array","items":{"$ref":"#/components/schemas/TermWatchRow"}}},"required":["rows"],"additionalProperties":false},"TermWatchRow":{"type":"object","properties":{"leaseId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"landlordName":{"type":["string","null"]},"termEnd":{"type":"string"},"daysLeft":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"kind":{"type":"string","enum":["lease","investment"]},"splitPct":{"type":["string","null"]}},"required":["leaseId","propertyId","propertyName","landlordName","termEnd","daysLeft","kind","splitPct"],"additionalProperties":false},"ListPoolModelsResponse":{"type":"object","properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/PoolModelView"}}},"required":["models"],"additionalProperties":false},"PoolModelView":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"propertyId":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"unitCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"adrMinor":{"type":"string"},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"leaseMinor":{"type":"string"},"opexBp":{"type":"string"},"mgmtShareMilliPct":{"type":"string"},"currency":{"type":"string"},"effectiveFrom":{"type":"string"},"prefilledAt":{"type":["string","null"]},"prefilledFrom":{"type":["string","null"]},"prefilledTo":{"type":["string","null"]},"prefilledScope":{"anyOf":[{"type":"string","enum":["portfolio","property"]},{"type":"null"}]},"prefilledPropertyId":{"type":["string","null"]},"prefillStale":{"type":"boolean"},"scenarios":{"type":"array","items":{"$ref":"#/components/schemas/PoolModelScenarioView"}}},"required":["id","name","propertyId","propertyName","unitCount","adrMinor","nights","leaseMinor","opexBp","mgmtShareMilliPct","currency","effectiveFrom","prefilledAt","prefilledFrom","prefilledTo","prefilledScope","prefilledPropertyId","prefillStale","scenarios"],"additionalProperties":false},"PoolModelScenarioView":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"label":{"type":"string"},"occupancyBp":{"type":["string","null"]},"adrMinor":{"type":["string","null"]},"leaseMinor":{"type":["string","null"]},"opexBp":{"type":["string","null"]}},"required":["id","key","label","occupancyBp","adrMinor","leaseMinor","opexBp"],"additionalProperties":false},"CreatePoolModelResponse":{"type":"object","properties":{"id":{"type":"string"},"scenarioIds":{"type":"array","items":{"type":"string"}}},"required":["id","scenarioIds"],"additionalProperties":false},"PoolModelIdResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"UpsertPoolModelScenarioResponse":{"type":"object","properties":{"id":{"type":"string"},"created":{"type":"boolean"}},"required":["id","created"],"additionalProperties":false},"PrefillPoolModelResponse":{"type":"object","properties":{"modelId":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"adrMinor":{"type":"string"},"opexBp":{"type":"string"},"occupancyBp":{"type":"string"},"scenarioKey":{"type":"string"},"scope":{"type":"string","enum":["portfolio","property"]},"scopePropertyId":{"type":["string","null"]},"occupiedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sellableNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"recognisedRevenueMinor":{"type":"string"},"ledgerRevenueMinor":{"type":"string"},"ledgerExpenseMinor":{"type":"string"},"excludedManagedListings":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"excludedManagedNights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"prefilledAt":{"type":"string"}},"required":["modelId","from","to","adrMinor","opexBp","occupancyBp","scenarioKey","scope","scopePropertyId","occupiedNights","sellableNights","recognisedRevenueMinor","ledgerRevenueMinor","ledgerExpenseMinor","excludedManagedListings","excludedManagedNights","prefilledAt"],"additionalProperties":false},"DealProjectionResponse":{"type":"object","properties":{"modelId":{"type":"string"},"modelName":{"type":"string"},"currency":{"type":"string"},"propertyId":{"type":["string","null"]},"propertyName":{"type":["string","null"]},"unitCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nights":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"mgmtShareMilliPct":{"type":"string"},"effectiveFrom":{"type":"string"},"capitalMinor":{"type":"string"},"unitSharePriceMinor":{"type":"string"},"unitsMilli":{"type":"string"},"totalUnitsMilli":{"type":"string"},"unallocatedCapitalMinor":{"type":"string"},"splitMilliPct":{"type":"string"},"prefilledAt":{"type":["string","null"]},"prefilledFrom":{"type":["string","null"]},"prefilledTo":{"type":["string","null"]},"prefilledScope":{"anyOf":[{"type":"string","enum":["portfolio","property"]},{"type":"null"}]},"prefilledPropertyId":{"type":["string","null"]},"prefillStale":{"type":"boolean"},"lossPreview":{"type":"object","properties":{"poolNetMinor":{"type":"string"},"investorShareMinor":{"type":"string"}},"required":["poolNetMinor","investorShareMinor"],"additionalProperties":false},"scenarios":{"type":"array","items":{"$ref":"#/components/schemas/ProjectedScenarioView"}}},"required":["modelId","modelName","currency","propertyId","propertyName","unitCount","nights","mgmtShareMilliPct","effectiveFrom","capitalMinor","unitSharePriceMinor","unitsMilli","totalUnitsMilli","unallocatedCapitalMinor","splitMilliPct","prefilledAt","prefilledFrom","prefilledTo","prefilledScope","prefilledPropertyId","prefillStale","lossPreview","scenarios"],"additionalProperties":false},"ProjectedScenarioView":{"type":"object","properties":{"scenarioId":{"type":"string"},"key":{"type":"string"},"label":{"type":"string"},"occupancyBp":{"type":["string","null"]},"adrMinor":{"type":"string"},"leaseMinor":{"type":"string"},"opexBp":{"type":"string"},"adrOverridden":{"type":"boolean"},"leaseOverridden":{"type":"boolean"},"opexOverridden":{"type":"boolean"},"breakEvenOccupancyBp":{"type":["string","null"]},"projection":{"anyOf":[{"$ref":"#/components/schemas/ScenarioProjectionView"},{"type":"null"}]}},"required":["scenarioId","key","label","occupancyBp","adrMinor","leaseMinor","opexBp","adrOverridden","leaseOverridden","opexOverridden","breakEvenOccupancyBp","projection"],"additionalProperties":false},"ScenarioProjectionView":{"type":"object","properties":{"grossMinor":{"type":"string"},"opexMinor":{"type":"string"},"netMinor":{"type":"string"},"poolNetMinor":{"type":"string"},"shareMinor":{"type":"string"},"annualShareMinor":{"type":"string"},"monthlyYieldBp":{"type":["string","null"]},"annualYieldBp":{"type":["string","null"]},"paybackMonths":{"type":["string","null"]},"marginOfSafetyBp":{"type":["string","null"]}},"required":["grossMinor","opexMinor","netMinor","poolNetMinor","shareMinor","annualShareMinor","monthlyYieldBp","annualYieldBp","paybackMonths","marginOfSafetyBp"],"additionalProperties":false},"OwnersOverviewResponse":{"type":"object","properties":{"owners":{"type":"array","items":{"$ref":"#/components/schemas/OwnerOverviewRow"}},"currency":{"type":"string"},"scope":{"$ref":"#/components/schemas/EstateScope"},"dimensions":{"$ref":"#/components/schemas/EstateDimensions"}},"required":["owners","currency","scope","dimensions"],"additionalProperties":false},"OwnerOverviewRow":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"kind":{"type":"string"},"propertiesCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"accruedMinor":{"type":"string"},"paidMinor":{"type":"string"},"pendingMinor":{"type":"string"},"availableMinor":{"type":"string"},"payouts":{"type":"array","items":{"$ref":"#/components/schemas/OwnerPayoutRequestRow"}}},"required":["partyId","name","kind","propertiesCount","accruedMinor","paidMinor","pendingMinor","availableMinor","payouts"],"additionalProperties":false},"OwnerPayoutRequestRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"amountMinor":{"type":"string"},"currency":{"type":"string"},"periodMonth":{"type":"string"},"status":{"type":"string"},"accountName":{"type":"string"},"reference":{"type":["string","null"]},"requestedAt":{"type":"string"},"decidedAt":{"type":["string","null"]},"requestedBySelf":{"type":"boolean"},"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"journalEntryDate":{"type":["string","null"]}},"required":["id","amountMinor","currency","periodMonth","status","accountName","reference","requestedAt","decidedAt","requestedBySelf","journalEntryId","journalEntryDate"],"additionalProperties":false},"MonthEndAccrualPreviewResponse":{"type":"object","properties":{"periodMonth":{"type":"string"},"currency":{"type":"string"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/MonthEndAccrualLine"}},"feeTotalMinor":{"type":"string","pattern":"^-?\\d+$"},"rechargeTotalMinor":{"type":"string","pattern":"^-?\\d+$"},"feeJournalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"rechargeJournalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"periodClosed":{"type":"boolean"},"unpricedCurrencies":{"type":"array","items":{"type":"string"}}},"required":["periodMonth","currency","lines","feeTotalMinor","rechargeTotalMinor","feeJournalEntryId","rechargeJournalEntryId","periodClosed","unpricedCurrencies"],"additionalProperties":false},"MonthEndAccrualLine":{"type":"object","properties":{"listingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingCode":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"ownerName":{"type":["string","null"]},"grossMinor":{"type":"string","pattern":"^-?\\d+$"},"opexMinor":{"type":"string","pattern":"^-?\\d+$"},"feeBase":{"type":["string","null"]},"feePct":{"type":["string","null"]},"feeMinor":{"type":"string","pattern":"^-?\\d+$"},"rechargeMinor":{"type":"string","pattern":"^-?\\d+$"}},"required":["listingId","listingCode","propertyId","propertyName","ownerName","grossMinor","opexMinor","feeBase","feePct","feeMinor","rechargeMinor"],"additionalProperties":false},"PostMonthEndAccrualsResponse":{"type":"object","properties":{"feeJournalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"rechargeJournalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"feeTotalMinor":{"type":"string","pattern":"^-?\\d+$"},"rechargeTotalMinor":{"type":"string","pattern":"^-?\\d+$"},"unitsAccrued":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"replayed":{"type":"boolean"}},"required":["feeJournalEntryId","rechargeJournalEntryId","feeTotalMinor","rechargeTotalMinor","unitsAccrued","replayed"],"additionalProperties":false},"DepreciationPreviewResponse":{"type":"object","properties":{"periodMonth":{"type":"string"},"currency":{"type":"string"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/DepreciationLine"}},"chargeTotalMinor":{"type":"string"},"netBookValueTotalMinor":{"type":"string"},"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"periodClosed":{"type":"boolean"}},"required":["periodMonth","currency","lines","chargeTotalMinor","netBookValueTotalMinor","journalEntryId","periodClosed"],"additionalProperties":false},"DepreciationLine":{"type":"object","properties":{"assetId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"category":{"type":"string"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyName":{"type":"string"},"listingId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"costMinor":{"type":"string"},"acquiredOn":{"type":"string"},"usefulLifeMonths":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"funderName":{"type":["string","null"]},"posts":{"type":"boolean"},"chargeMinor":{"type":"string"},"netBookValueMinor":{"type":"string"}},"required":["assetId","name","category","propertyId","propertyName","listingId","costMinor","acquiredOn","usefulLifeMonths","funderName","posts","chargeMinor","netBookValueMinor"],"additionalProperties":false},"PostDepreciationResponse":{"type":"object","properties":{"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"chargeTotalMinor":{"type":"string"},"assetsCharged":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"replayed":{"type":"boolean"}},"required":["journalEntryId","chargeTotalMinor","assetsCharged","replayed"],"additionalProperties":false},"OutstandingCapitalNoticesResponse":{"type":"object","properties":{"rows":{"type":"array","items":{"$ref":"#/components/schemas/OutstandingNoticeRow"}}},"required":["rows"],"additionalProperties":false},"OutstandingNoticeRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"partyName":{"type":"string"},"propertyName":{"type":"string"},"splitPct":{"type":"string"},"issuedAt":{"type":"string"},"daysOutstanding":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","partyId","partyName","propertyName","splitPct","issuedAt","daysOutstanding"],"additionalProperties":false},"ListPeriodClosesResponse":{"type":"object","properties":{"periods":{"type":"array","items":{"$ref":"#/components/schemas/PeriodCloseRow"}}},"required":["periods"],"additionalProperties":false},"PeriodCloseRow":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"periodMonth":{"type":"string"},"closedAt":{"type":"string"},"reopenedAt":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["id","periodMonth","closedAt","reopenedAt","note"],"additionalProperties":false},"PayableCalendarResponse":{"type":"object","properties":{"instances":{"type":"array","items":{"$ref":"#/components/schemas/PayableCalendarRow"}}},"required":["instances"],"additionalProperties":false},"PayableCalendarRow":{"type":"object","properties":{"instanceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"payableId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"kind":{"type":"string"},"payeeName":{"type":["string","null"]},"dueOn":{"type":"string"},"amountMinor":{"type":["string","null"]},"currency":{"type":"string"},"status":{"type":"string"},"overdue":{"type":"boolean"},"verifyStatus":{"type":"string"},"route":{"type":["string","null"]}},"required":["instanceId","payableId","name","kind","payeeName","dueOn","amountMinor","currency","status","overdue","verifyStatus","route"],"additionalProperties":false},"PreviewPayableAccrualsResponse":{"$ref":"#/components/schemas/PayableAccrualResult"},"PayableAccrualRow":{"type":"object","properties":{"payableInstanceId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"scheduledPayableName":{"type":"string"},"dueOn":{"type":"string"},"amountMinor":{"type":"string","pattern":"^\\d+$"},"currency":{"type":"string"},"expenseId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"skipped":{"anyOf":[{"type":"string","enum":["already_accrued","no_amount","period_closed"]},{"type":"null"}]}},"required":["payableInstanceId","scheduledPayableName","dueOn","amountMinor","currency","expenseId","journalEntryId","skipped"],"additionalProperties":false},"PayableAccrualResult":{"type":"object","properties":{"asOf":{"type":"string"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/PayableAccrualRow"}},"accruedTotalMinor":{"type":"string","pattern":"^\\d+$"}},"required":["asOf","rows","accruedTotalMinor"],"additionalProperties":false},"AccrueDuePayablesResponse":{"$ref":"#/components/schemas/PayableAccrualResult"},"PayeeDirectoryResponse":{"type":"object","properties":{"payees":{"type":"array","items":{"$ref":"#/components/schemas/PayeeDirectoryRow"}}},"required":["payees"],"additionalProperties":false},"PayeeDirectoryRow":{"type":"object","properties":{"partyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"kind":{"type":"string"},"destinationCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"defaultRoute":{"type":["string","null"]},"totalRentMinor":{"type":"string"},"units":{"type":"array","items":{"$ref":"#/components/schemas/PayeeUnitRow"}}},"required":["partyId","name","kind","destinationCount","defaultRoute","totalRentMinor","units"],"additionalProperties":false},"PayeeUnitRow":{"type":"object","properties":{"propertyName":{"type":"string"},"listingCode":{"type":["string","null"]},"rentMinor":{"type":"string"},"currency":{"type":"string"}},"required":["propertyName","listingCode","rentMinor","currency"],"additionalProperties":false},"PreparePayRunResponse":{"$ref":"#/components/schemas/PayRunDetailView"},"PayRunLineView":{"type":"object","properties":{"id":{"type":"string"},"membershipId":{"type":"string"},"staffLabel":{"type":"string"},"baseMinor":{"type":"string","pattern":"^\\d+$"},"allowancesMinor":{"type":"string","pattern":"^\\d+$"},"cleaningsCompleted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cleaningAddMinor":{"type":"string","pattern":"^\\d+$"},"bookingsClosed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"bookingAddMinor":{"type":"string","pattern":"^\\d+$"},"grossMinor":{"type":"string","pattern":"^\\d+$"},"taxableMinor":{"type":"string","pattern":"^\\d+$"},"taxMinor":{"type":"string","pattern":"^\\d+$"},"deductionMinor":{"type":"string","pattern":"^\\d+$"},"netMinor":{"type":"string","pattern":"^\\d+$"},"paidByThirdParty":{"type":"boolean"},"deductions":{"type":"array","items":{"$ref":"#/components/schemas/PayRunLineDeductionView"}}},"required":["id","membershipId","staffLabel","baseMinor","allowancesMinor","cleaningsCompleted","cleaningAddMinor","bookingsClosed","bookingAddMinor","grossMinor","taxableMinor","taxMinor","deductionMinor","netMinor","paidByThirdParty","deductions"],"additionalProperties":false},"PayRunLineDeductionView":{"type":"object","properties":{"staffDeductionId":{"type":"string"},"label":{"type":"string"},"kind":{"type":"string"},"requestedMinor":{"type":"string","pattern":"^\\d+$"},"appliedMinor":{"type":"string","pattern":"^\\d+$"},"deferredMinor":{"type":"string","pattern":"^\\d+$"}},"required":["staffDeductionId","label","kind","requestedMinor","appliedMinor","deferredMinor"],"additionalProperties":false},"PayRunDetailView":{"type":"object","properties":{"id":{"type":"string"},"periodMonth":{"type":"string"},"status":{"type":"string","enum":["draft","approved","paid","cancelled"]},"currency":{"type":"string"},"grossMinor":{"type":"string","pattern":"^\\d+$"},"taxMinor":{"type":"string","pattern":"^\\d+$"},"deductionMinor":{"type":"string","pattern":"^\\d+$"},"netMinor":{"type":"string","pattern":"^\\d+$"},"preparedAt":{"type":"string"},"approvedAt":{"type":["string","null"]},"paidAt":{"type":["string","null"]},"cancelReason":{"type":["string","null"]},"note":{"type":["string","null"]},"lines":{"type":"array","items":{"$ref":"#/components/schemas/PayRunLineView"}}},"required":["id","periodMonth","status","currency","grossMinor","taxMinor","deductionMinor","netMinor","preparedAt","approvedAt","paidAt","cancelReason","note","lines"],"additionalProperties":false},"ListPayRunsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PayRunView"}}},"required":["items"],"additionalProperties":false},"PayRunView":{"type":"object","properties":{"id":{"type":"string"},"periodMonth":{"type":"string"},"status":{"type":"string","enum":["draft","approved","paid","cancelled"]},"currency":{"type":"string"},"grossMinor":{"type":"string","pattern":"^\\d+$"},"taxMinor":{"type":"string","pattern":"^\\d+$"},"deductionMinor":{"type":"string","pattern":"^\\d+$"},"netMinor":{"type":"string","pattern":"^\\d+$"},"preparedAt":{"type":"string"},"approvedAt":{"type":["string","null"]},"paidAt":{"type":["string","null"]},"cancelReason":{"type":["string","null"]},"note":{"type":["string","null"]}},"required":["id","periodMonth","status","currency","grossMinor","taxMinor","deductionMinor","netMinor","preparedAt","approvedAt","paidAt","cancelReason","note"],"additionalProperties":false},"GetPayRunResponse":{"$ref":"#/components/schemas/PayRunDetailView"},"ApprovePayRunResponse":{"type":"object","properties":{"payRunId":{"type":"string"},"journalId":{"type":"string"}},"required":["payRunId","journalId"],"additionalProperties":false},"PayPayRunResponse":{"type":"object","properties":{"payRunId":{"type":"string"},"journalId":{"type":"string"}},"required":["payRunId","journalId"],"additionalProperties":false},"CancelPayRunResponse":{"type":"object","properties":{"payRunId":{"type":"string"}},"required":["payRunId"],"additionalProperties":false},"WithholdingPositionResponse":{"type":"object","properties":{"currency":{"type":"string"},"outstandingMinor":{"type":"string","pattern":"^\\d+$"},"totalWithheldMinor":{"type":"string","pattern":"^\\d+$"},"totalRemittedMinor":{"type":"string","pattern":"^\\d+$"},"byMonth":{"type":"array","items":{"type":"object","properties":{"periodMonth":{"type":"string"},"withheldMinor":{"type":"string","pattern":"^\\d+$"}},"required":["periodMonth","withheldMinor"],"additionalProperties":false}}},"required":["currency","outstandingMinor","totalWithheldMinor","totalRemittedMinor","byMonth"],"additionalProperties":false},"RemitWithholdingResponse":{"type":"object","properties":{"journalId":{"type":"string"},"outstandingMinor":{"type":"string","pattern":"^\\d+$"}},"required":["journalId","outstandingMinor"],"additionalProperties":false},"ListStaffDeductionsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/StaffDeductionView"}}},"required":["items"],"additionalProperties":false},"StaffDeductionView":{"type":"object","properties":{"id":{"type":"string"},"membershipId":{"type":"string"},"staffLabel":{"type":"string"},"kind":{"type":"string"},"label":{"type":"string"},"originalMinor":{"type":"string","pattern":"^\\d+$"},"outstandingMinor":{"type":"string","pattern":"^\\d+$"},"perRunMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$"},{"type":"null"}]},"currency":{"type":"string"},"isActive":{"type":"boolean"},"note":{"type":["string","null"]}},"required":["id","membershipId","staffLabel","kind","label","originalMinor","outstandingMinor","perRunMinor","currency","isActive","note"],"additionalProperties":false},"RecordStaffDeductionResponse":{"type":"object","properties":{"id":{"type":"string"},"journalId":{"type":["string","null"]}},"required":["id","journalId"],"additionalProperties":false},"ListPayrollTaxTablesResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PayrollTaxTableView"}}},"required":["items"],"additionalProperties":false},"PayrollTaxTableView":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"effectiveFrom":{"type":"string"},"effectiveTo":{"type":["string","null"]},"period":{"type":"string","enum":["monthly","annual"]},"bands":{"type":"array","items":{"$ref":"#/components/schemas/PayrollTaxBandView"}}},"required":["id","name","effectiveFrom","effectiveTo","period","bands"],"additionalProperties":false},"UpsertPayrollTaxTableResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"RecordFxRateResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"RevaluateFxResponse":{"$ref":"#/components/schemas/FxRevaluationResultView"},"FxRevaluationRowView":{"type":"object","properties":{"financialAccountId":{"type":["string","null"]},"accountId":{"type":["string","null"]},"kind":{"type":"string","enum":["store","monetary_account"]},"accountName":{"type":"string"},"foreignCurrency":{"type":"string"},"foreignBalanceMinor":{"type":"string","pattern":"^-?\\d+$"},"carriedBaseMinor":{"type":"string","pattern":"^-?\\d+$"},"revaluedBaseMinor":{"type":"string","pattern":"^-?\\d+$"},"differenceMinor":{"type":"string","pattern":"^-?\\d+$"},"rate":{"type":"string"},"journalEntryId":{"type":["string","null"]},"skipped":{"anyOf":[{"type":"string","enum":["no_rate","already_revalued"]},{"type":"null"}]}},"required":["financialAccountId","accountId","kind","accountName","foreignCurrency","foreignBalanceMinor","carriedBaseMinor","revaluedBaseMinor","differenceMinor","rate","journalEntryId","skipped"],"additionalProperties":false},"FxRevaluationResultView":{"type":"object","properties":{"month":{"type":"string"},"baseCurrency":{"type":"string"},"rows":{"type":"array","items":{"$ref":"#/components/schemas/FxRevaluationRowView"}},"netDifferenceMinor":{"type":"string","pattern":"^-?\\d+$"}},"required":["month","baseCurrency","rows","netDifferenceMinor"],"additionalProperties":false},"ListFxRevaluationsResponse":{"$ref":"#/components/schemas/FxRevaluationResultView"},"RecordUnitTransferResponse":{"type":"object","properties":{"id":{"type":"string"},"journalEntryIds":{"type":"array","items":{"type":"string"}}},"required":["id","journalEntryIds"],"additionalProperties":false},"ListUnitTransfersResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/UnitTransferView"}}},"required":["items"],"additionalProperties":false},"UnitTransferView":{"type":"object","properties":{"id":{"type":"string"},"propertyId":{"type":"string"},"sellerPartyId":{"type":["string","null"]},"sellerName":{"type":["string","null"]},"buyerPartyId":{"type":"string"},"buyerName":{"type":"string"},"units":{"type":"string"},"considerationMinor":{"type":"string","pattern":"^\\d+$"},"currency":{"type":"string"},"route":{"type":"string","enum":["via_company","direct"]},"transferredOn":{"type":"string"},"receiptJournalEntryId":{"type":["string","null"]},"payoutJournalEntryId":{"type":["string","null"]},"capitalTransferJournalEntryId":{"type":["string","null"]},"memo":{"type":["string","null"]}},"required":["id","propertyId","sellerPartyId","sellerName","buyerPartyId","buyerName","units","considerationMinor","currency","route","transferredOn","receiptJournalEntryId","payoutJournalEntryId","capitalTransferJournalEntryId","memo"],"additionalProperties":false},"RequestAgentRequestUploadResponse":{"type":"object","properties":{"objectKey":{"type":"string","description":"The server-minted key to submit with the request."},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["objectKey","uploadUrl","requiredHeaders"],"additionalProperties":false},"SubmitAgentRequestResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"RequestFeedbackUploadResponse":{"type":"object","properties":{"objectKey":{"type":"string","description":"The server-minted key to submit with the report."},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["objectKey","uploadUrl","requiredHeaders"],"additionalProperties":false},"SubmitFeedbackResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"ListSupportThreadsResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SupportThreadListItem"}}},"required":["items"],"additionalProperties":false},"SupportThreadListItem":{"type":"object","properties":{"id":{"type":"string"},"subject":{"type":"string","enum":["feedback","agent_request"],"description":"Which board this came from."},"title":{"type":"string","description":"The feedback kind, or the agent request title."},"status":{"type":"string"},"pagePath":{"type":"string"},"bodyPreview":{"type":"string"},"messageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lastActivityAt":{"type":"string"},"createdAt":{"type":"string"},"isMine":{"type":"boolean","description":"Whether the asking seat filed it."}},"required":["id","subject","title","status","pagePath","bodyPreview","messageCount","lastActivityAt","createdAt","isMine"],"additionalProperties":false},"SupportThreadResponse":{"type":"object","properties":{"id":{"type":"string"},"subject":{"type":"string","enum":["feedback","agent_request"]},"title":{"type":"string"},"status":{"type":"string"},"body":{"type":"string"},"pagePath":{"type":"string"},"pageUrl":{"type":"string"},"createdAt":{"type":"string"},"isMine":{"type":"boolean"},"screenshotUrl":{"type":["string","null"]},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/SupportAttachment"}},"messages":{"type":"array","items":{"$ref":"#/components/schemas/SupportThreadMessage"}}},"required":["id","subject","title","status","body","pagePath","pageUrl","createdAt","isMine","screenshotUrl","attachments","messages"],"additionalProperties":false},"SupportAttachment":{"type":"object","properties":{"url":{"type":"string"},"contentType":{"type":["string","null"]}},"required":["url","contentType"],"additionalProperties":false},"SupportThreadMessage":{"type":"object","properties":{"id":{"type":"string"},"authorRealm":{"type":"string","description":"tenant | platform | system."},"authorLabel":{"type":"string"},"body":{"type":"string"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/SupportAttachment"}},"createdAt":{"type":"string"}},"required":["id","authorRealm","authorLabel","body","attachments","createdAt"],"additionalProperties":false},"PostSupportMessageResponse":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"GetGuestAppTenantResponse":{"type":"object","properties":{"app":{"anyOf":[{"$ref":"#/components/schemas/GuestAppTenant"},{"type":"null"}]}},"required":["app"],"additionalProperties":false},"GuestAppTenant":{"type":"object","properties":{"id":{"type":"string"},"publicId":{"type":"string","description":"The /g/{publicId} handle. An identifier printed on QR cards, never a credential."},"isEnabled":{"type":"boolean"},"displayName":{"type":["string","null"]},"welcomeMessage":{"type":["string","null"]},"termsAndConditions":{"type":["string","null"]},"contactEmail":{"type":["string","null"]},"contactPhone":{"type":["string","null"]},"socialUrls":{"type":"array","items":{"type":"string"}},"resolvedBrandName":{"description":"What a guest reads at the top of the app, cascade already applied: this override, else the booking site name, else the workspace name.","type":["string","null"]},"updatedAt":{"type":"string"}},"required":["id","publicId","isEnabled","displayName","welcomeMessage","termsAndConditions","contactEmail","contactPhone","socialUrls","resolvedBrandName","updatedAt"],"additionalProperties":false,"description":"The workspace's one guest app."},"GuestAppTenantResponse":{"type":"object","properties":{"app":{"$ref":"#/components/schemas/GuestAppTenant"}},"required":["app"],"additionalProperties":false},"GetGuestAppConfigResponse":{"type":"object","properties":{"config":{"anyOf":[{"$ref":"#/components/schemas/GuestAppConfig"},{"type":"null"}]}},"required":["config"],"additionalProperties":false,"description":"null until first ensured."},"GuestAppConfig":{"type":"object","properties":{"id":{"type":"string"},"propertyId":{"type":"string"},"publicId":{"type":"string"},"isEnabled":{"type":"boolean"},"welcomeMessage":{"type":["string","null"]},"wlanNetwork":{"type":["string","null"]},"wlanPassword":{"type":["string","null"]},"doorOpeningInfo":{"type":["string","null"]},"arrivalInfo":{"type":["string","null"]},"checkinEnabled":{"type":"boolean"},"termsAndConditions":{"type":["string","null"]},"messagingEnabled":{"type":"boolean"},"socialUrls":{"type":"array","items":{"type":"string"}},"logoUrl":{"type":["string","null"]},"logoContentType":{"type":["string","null"]},"updatedAt":{"type":"string"}},"required":["id","propertyId","publicId","isEnabled","welcomeMessage","wlanNetwork","wlanPassword","doorOpeningInfo","arrivalInfo","checkinEnabled","termsAndConditions","messagingEnabled","socialUrls","logoUrl","logoContentType","updatedAt"],"additionalProperties":false,"description":"One property's guest-app configuration."},"GuestAppConfigResponse":{"type":"object","properties":{"config":{"$ref":"#/components/schemas/GuestAppConfig"}},"required":["config"],"additionalProperties":false},"LogoUploadTicket":{"type":"object","properties":{"objectKey":{"type":"string"},"uploadUrl":{"type":"string"},"requiredHeaders":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["objectKey","uploadUrl","requiredHeaders"],"additionalProperties":false,"description":"Presigned PUT for an app-icon logo. Writes no row."},"GuestAppOk":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"ListGuestAppPagesResponse":{"type":"object","properties":{"pages":{"type":"array","items":{"$ref":"#/components/schemas/GuestAppPage"}}},"required":["pages"],"additionalProperties":false},"GuestAppPage":{"type":"object","properties":{"id":{"type":"string"},"propertyId":{"type":["string","null"]},"section":{"type":"string"},"parentPageId":{"type":["string","null"]},"title":{"type":"string"},"slug":{"type":"string"},"icon":{"type":["string","null"]},"body":{"type":["string","null"]},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isPublished":{"type":"boolean"},"updatedAt":{"type":"string"}},"required":["id","propertyId","section","parentPageId","title","slug","icon","body","sortOrder","isPublished","updatedAt"],"additionalProperties":false},"GuestAppPageResponse":{"type":"object","properties":{"page":{"$ref":"#/components/schemas/GuestAppPage"}},"required":["page"],"additionalProperties":false},"DeleteGuestAppPageResponse":{"type":"object","properties":{"deleted":{"type":"boolean","const":true}},"required":["deleted"],"additionalProperties":false},"ListGuestCheckinsResponse":{"type":"object","properties":{"checkins":{"type":"array","items":{"$ref":"#/components/schemas/GuestCheckinQueueItem"}}},"required":["checkins"],"additionalProperties":false},"GuestCheckinQueueItem":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"referenceCode":{"type":"string"},"checkIn":{"type":"string"},"checkOut":{"type":"string"},"propertyId":{"type":"string"},"propertyName":{"type":["string","null"]},"guestName":{"type":["string","null"]},"guestCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"completedAt":{"type":"string"}},"required":["id","bookingId","referenceCode","checkIn","checkOut","propertyId","propertyName","guestName","guestCount","completedAt"],"additionalProperties":false},"GuestCheckinDetailResponse":{"type":"object","properties":{"checkin":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"status":{"type":"string"},"termsAcceptedAt":{"type":"string"},"completedAt":{"type":"string"},"guests":{"type":"array","items":{"$ref":"#/components/schemas/GuestCheckinGuest"}}},"required":["id","bookingId","status","termsAcceptedAt","completedAt","guests"],"additionalProperties":false}},"required":["checkin"],"additionalProperties":false},"GuestCheckinGuest":{"type":"object","properties":{"id":{"type":"string"},"guestIndex":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isChild":{"type":"boolean"},"firstName":{"type":"string"},"lastName":{"type":"string"},"dateOfBirth":{"type":"string"},"nationality":{"type":"string"},"idKind":{"type":["string","null"]},"docNumber":{"description":"The FULL number on the operator wire (owner decision 2026-07-07 parity with verification); events and audit diffs never carry it.","type":["string","null"]},"docNumberMasked":{"type":["string","null"]},"docExpiry":{"type":["string","null"]},"verificationId":{"type":["string","null"]}},"required":["id","guestIndex","isChild","firstName","lastName","dateOfBirth","nationality","idKind","docNumber","docNumberMasked","docExpiry","verificationId"],"additionalProperties":false},"GuestCheckinSignatureUrlResponse":{"type":"object","properties":{"url":{"type":"string"},"expiresInSeconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["url","expiresInSeconds"],"additionalProperties":false,"description":"A 120s presigned GET."},"AccessOverview":{"type":"object","properties":{"properties":{"type":"array","items":{"$ref":"#/components/schemas/AccessPropertyView"}},"gaps":{"type":"object","properties":{"unitsWithoutWifi":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"propertiesWithoutDoorInfo":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"propertiesWithoutArrivalInfo":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["unitsWithoutWifi","propertiesWithoutDoorInfo","propertiesWithoutArrivalInfo"],"additionalProperties":false}},"required":["properties","gaps"],"additionalProperties":false,"description":"Every unit's Wi-Fi, door and arrival instructions."},"AccessPropertyView":{"type":"object","properties":{"propertyId":{"type":"string"},"propertyName":{"type":"string"},"wifiNetwork":{"type":["string","null"]},"wifiPassword":{"type":["string","null"]},"doorInfo":{"type":["string","null"]},"arrivalInfo":{"type":["string","null"]},"missingDoorInfo":{"type":"boolean"},"missingArrivalInfo":{"type":"boolean"},"units":{"type":"array","items":{"$ref":"#/components/schemas/AccessUnitView"}}},"required":["propertyId","propertyName","wifiNetwork","wifiPassword","doorInfo","arrivalInfo","missingDoorInfo","missingArrivalInfo","units"],"additionalProperties":false},"AccessUnitView":{"type":"object","properties":{"listingId":{"type":"string"},"listingCode":{"type":"string"},"propertyId":{"type":"string"},"wifiNetwork":{"type":["string","null"]},"wifiNetworkSource":{"type":"string","enum":["unit","property","none"]},"wifiPassword":{"type":["string","null"]},"wifiPasswordSource":{"type":"string","enum":["unit","property","none"]},"hasWifiOverride":{"type":"boolean"},"missingWifi":{"type":"boolean"}},"required":["listingId","listingCode","propertyId","wifiNetwork","wifiNetworkSource","wifiPassword","wifiPasswordSource","hasWifiOverride","missingWifi"],"additionalProperties":false},"AccessOk":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"RotateWifiResponse":{"type":"object","properties":{"units":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"properties":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["units","properties"],"additionalProperties":false},"GetSiteResponse":{"type":"object","properties":{"site":{"anyOf":[{"$ref":"#/components/schemas/Site"},{"type":"null"}]},"properties":{"type":"array","items":{"$ref":"#/components/schemas/SiteProperty"}}},"required":["site","properties"],"additionalProperties":false},"Site":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"status":{"type":"string","enum":["draft","published","disabled"]},"name":{"type":"string"},"tagline":{"type":["string","null"]},"introText":{"type":["string","null"]},"locale":{"type":"string"},"colorPrimary":{"type":["string","null"]},"colorAccent":{"type":["string","null"]},"colorSurface":{"type":["string","null"]},"colorInk":{"type":["string","null"]},"fontFamily":{"type":"string","enum":["sans","serif","grotesk","humanist"]},"heroStyle":{"type":"string","enum":["full_bleed","split","minimal"]},"template":{"type":"string","enum":["harbour","atlas","lantern","ledger","quiet"]},"heroPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"contactEmail":{"type":["string","null"]},"contactPhone":{"type":["string","null"]},"socialUrls":{"type":"array","items":{"type":"string"}},"searchWindowDays":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"showReviews":{"type":"boolean"},"logoUrl":{"type":["string","null"]},"logoContentType":{"type":["string","null"]},"tracking":{"$ref":"#/components/schemas/SiteTracking"},"updatedAt":{"type":"string"}},"required":["id","slug","status","name","tagline","introText","locale","colorPrimary","colorAccent","colorSurface","colorInk","fontFamily","heroStyle","template","heroPhotoId","contactEmail","contactPhone","socialUrls","searchWindowDays","showReviews","logoUrl","logoContentType","tracking","updatedAt"],"additionalProperties":false,"description":"The workspace's public booking website."},"SiteTracking":{"type":"object","properties":{"ga4":{"type":["string","null"]},"gtm":{"type":["string","null"]},"metaPixel":{"type":["string","null"]}},"required":["ga4","gtm","metaPixel"],"additionalProperties":false},"SiteProperty":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"propertyId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"slug":{"type":"string"},"introText":{"type":["string","null"]},"heroPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isPublished":{"type":"boolean"},"theSpace":{"type":["string","null"]},"neighbourhood":{"type":["string","null"]},"gettingAround":{"type":["string","null"]},"guestAccess":{"type":["string","null"]},"distances":{"type":"array","items":{"$ref":"#/components/schemas/PropertyDistance"}},"updatedAt":{"type":"string"}},"required":["id","propertyId","slug","introText","heroPhotoId","sortOrder","isPublished","theSpace","neighbourhood","gettingAround","guestAccess","distances","updatedAt"],"additionalProperties":false,"description":"A property shown on the booking website."},"SiteResponse":{"type":"object","properties":{"site":{"$ref":"#/components/schemas/Site"}},"required":["site"],"additionalProperties":false},"SiteOk":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"SiteCustomDomainResponse":{"type":"object","properties":{"domain":{"$ref":"#/components/schemas/SiteCustomDomain"}},"required":["domain"],"additionalProperties":false},"SiteCustomDomain":{"type":"object","properties":{"domain":{"type":["string","null"]},"txtName":{"type":["string","null"]},"txtValue":{"type":["string","null"]},"verifiedAt":{"description":"When control of the zone was last PROVEN. Null while a claim is unproven — an unproven domain serves nothing. This is an observation with a date, not a permanent fact: domains change hands, and re-verifying is always allowed.","type":["string","null"]}},"required":["domain","txtName","txtValue","verifiedAt"],"additionalProperties":false,"description":"A tenant's own domain for their booking website, and its DNS-TXT ownership proof."},"SitePropertyResponse":{"type":"object","properties":{"property":{"$ref":"#/components/schemas/SiteProperty"}},"required":["property"],"additionalProperties":false},"RemoveSitePropertyResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"ListSiteRoomContentResponse":{"type":"object","properties":{"rooms":{"type":"array","items":{"$ref":"#/components/schemas/SiteRoomContent"}}},"required":["rooms"],"additionalProperties":false},"SiteRoomContent":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"listingTypeName":{"type":"string"},"displayName":{"type":["string","null"]},"tagline":{"type":["string","null"]},"body":{"type":["string","null"]},"equipment":{"type":"array","items":{"type":"string"}},"sleeping":{"type":"array","items":{"$ref":"#/components/schemas/SleepingArrangement"}},"heroPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sellOnline":{"type":"boolean"},"updatedAt":{"type":"string"}},"required":["id","listingTypeId","listingTypeName","displayName","tagline","body","equipment","sleeping","heroPhotoId","sortOrder","sellOnline","updatedAt"],"additionalProperties":false,"description":"An operator's own copy for one room type."},"SiteRoomContentResponse":{"type":"object","properties":{"room":{"$ref":"#/components/schemas/SiteRoomContent"}},"required":["room"],"additionalProperties":false},"RemoveSiteRoomContentResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"ListSitePromoCodesResponse":{"type":"object","properties":{"promoCodes":{"type":"array","items":{"$ref":"#/components/schemas/SitePromoCode"}}},"required":["promoCodes"],"additionalProperties":false},"SitePromoCode":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"code":{"type":"string"},"label":{"type":["string","null"]},"kind":{"type":"string","enum":["percent","fixed"]},"pct":{"type":["string","null"]},"amountMinor":{"type":["string","null"]},"startsOn":{"type":["string","null"]},"endsOn":{"type":["string","null"]},"minNights":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"minTotalMinor":{"type":["string","null"]},"maxRedemptions":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"isActive":{"type":"boolean"},"redemptions":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","label","kind","pct","amountMinor","startsOn","endsOn","minNights","minTotalMinor","maxRedemptions","isActive","redemptions"],"additionalProperties":false,"description":"A promo code on the booking website."},"SitePromoCodeResponse":{"type":"object","properties":{"promoCode":{"$ref":"#/components/schemas/SitePromoCode"}},"required":["promoCode"],"additionalProperties":false},"RemoveSitePromoCodeResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"ListSitePagesResponse":{"type":"object","properties":{"pages":{"type":"array","items":{"$ref":"#/components/schemas/SitePage"}}},"required":["pages"],"additionalProperties":false},"SitePage":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"path":{"type":"string"},"kind":{"type":"string","enum":["content","legal","contact"]},"title":{"type":"string"},"seoTitle":{"type":["string","null"]},"seoDescription":{"type":["string","null"]},"ogPhotoId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"showInNav":{"type":"boolean"},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isPublished":{"type":"boolean"},"updatedAt":{"type":"string"}},"required":["id","path","kind","title","seoTitle","seoDescription","ogPhotoId","showInNav","sortOrder","isPublished","updatedAt"],"additionalProperties":false,"description":"An operator-authored page on the booking site."},"SitePageResponse":{"type":"object","properties":{"page":{"$ref":"#/components/schemas/SitePage"}},"required":["page"],"additionalProperties":false},"SitePageDetailResponse":{"type":"object","properties":{"page":{"$ref":"#/components/schemas/SitePage"},"blocks":{"type":"array","items":{"$ref":"#/components/schemas/SiteBlock"}}},"required":["page","blocks"],"additionalProperties":false},"SiteBlock":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"kind":{"type":"string","enum":["rich_text","feature_cards","faq","gallery","steps","cta","poi_grid"]},"payload":{},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isPublished":{"type":"boolean"},"updatedAt":{"type":"string"}},"required":["id","kind","payload","sortOrder","isPublished","updatedAt"],"additionalProperties":false,"description":"One typed content block on a booking-site page."},"DeleteSitePageResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"ListSiteCollectionsResponse":{"type":"object","properties":{"collections":{"type":"array","items":{"$ref":"#/components/schemas/SiteCollection"}}},"required":["collections"],"additionalProperties":false},"SiteCollection":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"introText":{"type":["string","null"]},"seoDescription":{"type":["string","null"]},"heroPhotoId":{"type":["string","null"]},"filter":{},"sortOrder":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"showInNav":{"type":"boolean"},"isPublished":{"type":"boolean"},"updatedAt":{"type":"string"},"propertyCount":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","slug","title","introText","seoDescription","heroPhotoId","filter","sortOrder","showInNav","isPublished","updatedAt","propertyCount"],"additionalProperties":false},"SiteCollectionResponse":{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/SiteCollection"}},"required":["collection"],"additionalProperties":false},"DeleteSiteCollectionResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"SiteBlockResponse":{"type":"object","properties":{"block":{"$ref":"#/components/schemas/SiteBlock"}},"required":["block"],"additionalProperties":false},"TaxRuleView":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"code":{"type":"string"},"name":{"type":"string"},"basis":{"type":"string","enum":["percent_of_base","per_night","per_person_per_night","per_stay"]},"rateBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Basis points (1900 = 19%). NULL on the fixed bases."},"amountMinor":{"anyOf":[{"type":"string","pattern":"^\\d+$","description":"Integer MINOR units as a string — never a float."},{"type":"null"}]},"currency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]},"inclusive":{"type":"boolean","description":"Is the rate already INSIDE the quoted price? EU consumer pricing is inclusive; US occupancy tax is added at checkout. The same rate gives different money either way."},"appliesTo":{"type":"array","items":{"type":"string","enum":["accommodation","cleaning","fees"]}},"sequence":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"compound":{"type":"boolean"},"glAccountCode":{"type":"string","enum":["2420","2430"]},"effectiveFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date, YYYY-MM-DD."},"effectiveTo":{"anyOf":[{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date, YYYY-MM-DD."},{"type":"null"}],"description":"NULL ⇒ this rule is the one currently in force for its code and scope."},"propertyId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"NULL ⇒ the workspace-wide rule. A property rule REPLACES it, never stacks."},"propertyName":{"type":["string","null"]},"isActive":{"type":"boolean"}},"required":["id","code","name","basis","rateBp","amountMinor","currency","inclusive","appliesTo","sequence","compound","glAccountCode","effectiveFrom","effectiveTo","propertyId","propertyName","isActive"],"additionalProperties":false},"BookingTaxView":{"type":"object","properties":{"bookingId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"currency":{"type":"string","minLength":3,"maxLength":3},"assessedOn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Civil date, YYYY-MM-DD."},"lines":{"type":"array","items":{"$ref":"#/components/schemas/BookingTaxLineView"}},"inclusiveTaxMinor":{"type":"string","pattern":"^\\d+$","description":"Tax CARVED OUT of the quoted price — already inside what the guest was told."},"exclusiveTaxMinor":{"type":"string","pattern":"^\\d+$","description":"Tax ADDED to the quoted price."},"totalTaxMinor":{"type":"string","pattern":"^\\d+$","description":"Integer MINOR units as a string — never a float."},"grandTotalMinor":{"type":"string","pattern":"^\\d+$","description":"What the guest pays in total."},"netRevenueMinor":{"type":"string","pattern":"^\\d+$","description":"What the operator may recognise as income once the tax is carved out."}},"required":["bookingId","currency","assessedOn","lines","inclusiveTaxMinor","exclusiveTaxMinor","totalTaxMinor","grandTotalMinor","netRevenueMinor"],"additionalProperties":false},"BookingTaxLineView":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"basis":{"type":"string","enum":["percent_of_base","per_night","per_person_per_night","per_stay"]},"rateBp":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"inclusive":{"type":"boolean"},"baseMinor":{"type":"string","pattern":"^\\d+$","description":"Integer MINOR units as a string — never a float."},"taxMinor":{"type":"string","pattern":"^\\d+$","description":"Integer MINOR units as a string — never a float."},"glAccountCode":{"type":"string","enum":["2420","2430"]}},"required":["code","name","basis","rateBp","inclusive","baseMinor","taxMinor","glAccountCode"],"additionalProperties":false},"PostBookingTaxResponse":{"type":"object","properties":{"journalEntryId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"postedMinor":{"type":"string","pattern":"^\\d+$","description":"Integer MINOR units as a string — never a float."},"currency":{"anyOf":[{"type":"string","minLength":3,"maxLength":3},{"type":"null"}]}},"required":["journalEntryId","postedMinor","currency"],"additionalProperties":false},"ListTenantSettingsResponse":{"type":"object","properties":{"settings":{"type":"array","items":{"$ref":"#/components/schemas/TenantSettingRow"}}},"required":["settings"],"additionalProperties":false},"TenantSettingRow":{"type":"object","properties":{"key":{"type":"string"},"kind":{"type":"string"},"label":{"type":"string"},"help":{"type":"string"},"value":{"anyOf":[{"type":"string","maxLength":200},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"fallback":{"anyOf":[{"type":"string","maxLength":200},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"editable":{"type":"boolean"},"enumValues":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"min":{"type":["number","null"]},"max":{"type":["number","null"]}},"required":["key","kind","label","help","value","fallback","editable","enumValues","min","max"],"additionalProperties":false},"SetTenantSettingResponse":{"type":"object","properties":{"key":{"type":"string"},"value":{"anyOf":[{"type":"string","maxLength":200},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"changed":{"type":"boolean"}},"required":["key","value","changed"],"additionalProperties":false},"RecordPageViewsResponse":{"type":"object","properties":{"recorded":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Views persisted (a repeat ordinal is a no-op)."},"dropped":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Views whose path matched no served route template, so nothing was stored."}},"required":["recorded","dropped"],"additionalProperties":false},"TermsStatusResponse":{"type":"object","properties":{"owed":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["customer_terms","workspace_user_terms"]},"version":{"type":"string"},"title":{"type":"string"},"path":{"type":"string"}},"required":["key","version","title","path"],"additionalProperties":false}}},"required":["owed"],"additionalProperties":false},"AcceptTermsResponse":{"type":"object","properties":{"accepted":{"type":"array","items":{"type":"string","enum":["customer_terms","workspace_user_terms"]}}},"required":["accepted"],"additionalProperties":false},"ListContentTranslationsResponse":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/ContentTranslationEntry"}}},"required":["entries"],"additionalProperties":false},"ContentTranslationEntry":{"type":"object","properties":{"entityType":{"type":"string"},"entityId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"field":{"type":"string"},"label":{"type":"string"},"source":{"type":"string"},"locale":{"type":"string","enum":["ar","de","es","fr","it","pt","ru","tr","ur","zh"]},"text":{"type":["string","null"]},"origin":{"anyOf":[{"type":"string","enum":["machine","manual"]},{"type":"null"}]},"stale":{"type":"boolean"}},"required":["entityType","entityId","field","label","source","locale","text","origin","stale"],"additionalProperties":false,"description":"One translatable text and its translation."},"ContentTranslationResponse":{"type":"object","properties":{"entry":{"$ref":"#/components/schemas/ContentTranslationEntry"}},"required":["entry"],"additionalProperties":false},"RemoveContentTranslationResponse":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false},"ApiKeysPage":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}},"grantableScopes":{"type":"array","items":{"type":"string"}}},"required":["keys","grantableScopes"],"additionalProperties":false},"ApiKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"displayPrefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"createdBy":{"type":"string"},"createdAt":{"type":"string"},"expiresAt":{"type":["string","null"]},"lastUsedAt":{"type":["string","null"]},"revokedAt":{"type":["string","null"]},"status":{"type":"string","enum":["active","expired","revoked"]}},"required":["id","name","displayPrefix","scopes","createdBy","createdAt","expiresAt","lastUsedAt","revokedAt","status"],"additionalProperties":false},"CreatedApiKey":{"type":"object","properties":{"key":{"$ref":"#/components/schemas/ApiKey"},"token":{"type":"string","description":"The whole key. Shown once; store it now."}},"required":["key","token"],"additionalProperties":false},"WebhooksPage":{"type":"object","properties":{"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"catalog":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"group":{"type":"string","enum":["bookings","payments","guests","housekeeping","inventory","messaging","finance"]}},"required":["type","group"],"additionalProperties":false}}},"required":["endpoints","catalog"],"additionalProperties":false},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"url":{"type":"string"},"eventTypes":{"type":"array","items":{"type":"string"}},"omitPersonal":{"type":"boolean"},"active":{"type":"boolean"},"keyHint":{"type":"string"},"createdAt":{"type":"string"},"lastDeliveryAt":{"type":["string","null"]},"lastDeliveryStatus":{"anyOf":[{"type":"string","enum":["pending","succeeded","failed"]},{"type":"null"}]},"failedLast24h":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","url","eventTypes","omitPersonal","active","keyHint","createdAt","lastDeliveryAt","lastDeliveryStatus","failedLast24h"],"additionalProperties":false},"WebhookWithSecret":{"type":"object","properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpoint"},"signingKey":{"type":"string","description":"Shown once; store it now."}},"required":["endpoint","signingKey"],"additionalProperties":false},"IntegrationId":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["id"],"additionalProperties":false},"WebhookDeliveriesPage":{"type":"object","properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"more":{"type":"boolean"}},"required":["deliveries","more"],"additionalProperties":false},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"endpointId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"eventType":{"type":"string"},"status":{"type":"string","enum":["pending","succeeded","failed"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"nextAttemptAt":{"type":["string","null"]},"lastAttemptAt":{"type":["string","null"]},"responseStatus":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"responseExcerpt":{"type":["string","null"]},"error":{"type":["string","null"]},"durationMs":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"redeliveryOf":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"createdAt":{"type":"string"},"payload":{}},"required":["id","endpointId","eventType","status","attempts","nextAttemptAt","lastAttemptAt","responseStatus","responseExcerpt","error","durationMs","redeliveryOf","createdAt"],"additionalProperties":false},"AccountingExportPage":{"type":"object","properties":{"currency":{"type":"string"},"accounts":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"}},"required":["code","name","type"],"additionalProperties":false}},"mappings":{"type":"array","items":{"type":"object","properties":{"target":{"type":"string","enum":["xero","quickbooks"]},"accountCode":{"type":"string"},"externalCode":{"type":"string"},"taxRate":{"type":["string","null"]}},"required":["target","accountCode","externalCode","taxRate"],"additionalProperties":false}},"exports":{"type":"array","items":{"$ref":"#/components/schemas/AccountingExport"}}},"required":["currency","accounts","mappings","exports"],"additionalProperties":false},"AccountingExport":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"target":{"type":"string","enum":["xero","quickbooks"]},"periodFrom":{"type":"string"},"periodTo":{"type":"string"},"currency":{"type":"string"},"journals":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lines":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unmappedCodes":{"type":"array","items":{"type":"string"}},"heldBackJournals":{"type":"array","items":{"type":"string"}},"fileName":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","target","periodFrom","periodTo","currency","journals","lines","unmappedCodes","heldBackJournals","fileName","createdAt"],"additionalProperties":false},"AccountMappingsChanged":{"type":"object","properties":{"changed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["changed"],"additionalProperties":false},"CreatedAccountingExport":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"target":{"type":"string","enum":["xero","quickbooks"]},"periodFrom":{"type":"string"},"periodTo":{"type":"string"},"currency":{"type":"string"},"journals":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lines":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"unmappedCodes":{"type":"array","items":{"type":"string"}},"heldBackJournals":{"type":"array","items":{"type":"string"}},"fileName":{"type":"string"},"createdAt":{"type":"string"},"unbalancedJournals":{"type":"array","items":{"type":"string"}}},"required":["id","target","periodFrom","periodTo","currency","journals","lines","unmappedCodes","heldBackJournals","fileName","createdAt","unbalancedJournals"],"additionalProperties":false},"AccountingExportFile":{"type":"object","properties":{"fileName":{"type":"string"},"content":{"type":"string"}},"required":["fileName","content"],"additionalProperties":false},"PushDevicesPage":{"type":"object","properties":{"devices":{"type":"array","items":{"$ref":"#/components/schemas/PushDevice"}},"vapidPublicKey":{"description":"The applicationServerKey; null when push is not configured.","type":["string","null"]}},"required":["devices","vapidPublicKey"],"additionalProperties":false},"PushDevice":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"deviceLabel":{"type":["string","null"]},"categories":{"type":"array","items":{"type":"string","enum":["bookings","guests","housekeeping","finance","channels","system"]}},"lastSuccessAt":{"type":["string","null"]},"failureCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdAt":{"type":"string"}},"required":["id","deviceLabel","categories","lastSuccessAt","failureCount","createdAt"],"additionalProperties":false}}}}