{"openapi":"3.1.0","info":{"title":"MyRentalCalendar Landlord API","version":"1.0.0","description":"Your apartments, as your managing agency runs them: occupancy without guest names, your statement and payouts, running costs, the paperwork the office released to you, and the conversation with the office. Every request authenticates with an API key you create in your landlord portal; the key is bound to you, so there is nothing to select — every answer is about your units.\n\nAmounts are integers in the agency currency's minor unit. Dates are ISO `YYYY-MM-DD`, and a stay is the half-open range `[arrival, departure)`. Every error carries a stable `code` and a readable `title`."},"servers":[{"url":"https://api.myrentalcalendar.com/partner/v1/landlord","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Introspection","description":"What this key is"},{"name":"Units","description":"Your apartments and their anonymised occupancy"},{"name":"Blocks","description":"Own use and blocks — the one thing you write on the calendar"},{"name":"Finance","description":"Statement, payouts, invoices"},{"name":"Costs","description":"Running costs of your apartments"},{"name":"Documents","description":"Contracts, permits, statements"},{"name":"Messages","description":"Talking to the office"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your API key: `Authorization: Bearer hr_live_…`"}},"schemas":{"Error":{"type":"object","properties":{"code":{"type":"string","description":"Stable identifier — branch on this","example":"NOT_FOUND"},"title":{"type":"string","description":"Human-readable explanation — log this"}},"required":["code","title"]},"LandlordUnit":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string","example":"marina-loft-2br"},"name":{"type":"string"},"status":{"type":"string"},"city":{"type":"string","nullable":true},"area":{"type":"string","nullable":true},"building":{"type":"string","nullable":true},"address":{"type":"string","nullable":true},"bedrooms":{"type":"number"},"beds":{"type":"number"},"bathrooms":{"type":"number"},"maxGuests":{"type":"number"},"sizeSqm":{"type":"number","nullable":true},"checkinTime":{"type":"string"},"checkoutTime":{"type":"string"},"petsAllowed":{"type":"boolean"},"tourUrl":{"type":"string","nullable":true},"coverPhoto":{"type":"string","nullable":true,"description":"Relative to the API host"},"tenure":{"type":"object","properties":{"sharePct":{"type":"number"},"commissionPct":{"type":"number","nullable":true,"description":"The agency fee that applies to this tenure"},"validFrom":{"type":"string"},"validTo":{"type":"string","nullable":true,"description":"Exclusive; null = open-ended"},"current":{"type":"boolean","description":"Held today"}},"required":["sharePct","commissionPct","validFrom","validTo","current"]}},"required":["id","slug","name","status","city","area","building","address","bedrooms","beds","bathrooms","maxGuests","sizeSqm","checkinTime","checkoutTime","petsAllowed","tourUrl","coverPhoto","tenure"]},"LandlordBooking":{"type":"object","properties":{"id":{"type":"string"},"unitSlug":{"type":"string"},"unitName":{"type":"string"},"type":{"type":"string","description":"guest, owner_stay, maintenance or block","example":"guest"},"status":{"type":"string"},"source":{"type":"string"},"arrival":{"type":"string"},"departure":{"type":"string"},"nights":{"type":"number"},"adults":{"type":"number"},"children":{"type":"number"},"totalAmount":{"type":"number","description":"Gross amount of the stay in minor units; 0 for blocks"},"currency":{"type":"string"},"earlyCheckin":{"type":"string","nullable":true},"lateCheckout":{"type":"string","nullable":true},"cleanedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","unitSlug","unitName","type","status","source","arrival","departure","nights","adults","children","totalAmount","currency","earlyCheckin","lateCheckout","cleanedAt","createdAt"]},"CreateBlock":{"type":"object","properties":{"unit":{"type":"string","minLength":1,"example":"marina-loft-2br"},"arrival":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"departure":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"type":{"type":"string","enum":["owner_stay","block"],"default":"owner_stay","description":"`owner_stay` = you are using it yourself, `block` = keep it off the market"},"notes":{"type":"string","nullable":true,"maxLength":2000}},"required":["unit","arrival","departure"]},"LandlordStatement":{"type":"object","properties":{"owner":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"]},"currency":{"type":"string"},"totals":{"type":"object","properties":{"gross":{"type":"number"},"agencyFees":{"type":"number"},"ownerShare":{"type":"number"},"ownerCosts":{"type":"number"},"agencyCoveredCosts":{"type":"number"},"netRent":{"type":"number"},"paidOut":{"type":"number"},"openBalance":{"type":"number"}},"required":["gross","agencyFees","ownerShare","ownerCosts","agencyCoveredCosts","netRent","paidOut","openBalance"]},"revenue":{"type":"object","additionalProperties":{"nullable":true},"description":"`lines` per stay and `byUnit` subtotals"},"costs":{"type":"object","additionalProperties":{"nullable":true},"description":"`lines`, `byCategory`, `ownerTotal`, `agencyCoveredTotal`"},"payouts":{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}},"kpis":{"type":"object","additionalProperties":{"nullable":true}}},"required":["owner","period","currency","totals","revenue","costs","payouts","kpis"]},"Payout":{"type":"object","properties":{"id":{"type":"string"},"bookingId":{"type":"string"},"unitSlug":{"type":"string"},"unitName":{"type":"string"},"arrival":{"type":"string"},"departure":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string"},"paidOn":{"type":"string"},"reference":{"type":"string","nullable":true}},"required":["id","bookingId","unitSlug","unitName","arrival","departure","amount","currency","paidOn","reference"]},"LandlordInvoice":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"issuedOn":{"type":"string"},"total":{"type":"number"},"currency":{"type":"string"},"bookingId":{"type":"string"},"unitSlug":{"type":"string"},"unitName":{"type":"string"},"arrival":{"type":"string"},"departure":{"type":"string"}},"required":["id","number","kind","status","issuedOn","total","currency","bookingId","unitSlug","unitName","arrival","departure"]},"LandlordCost":{"type":"object","properties":{"id":{"type":"string"},"unitSlug":{"type":"string"},"unitName":{"type":"string"},"categoryId":{"type":"string","nullable":true},"category":{"type":"string"},"categoryGroup":{"type":"string"},"label":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string"},"recurrence":{"type":"string","enum":["one_time","monthly","quarterly","yearly"]},"monthlyEquivalent":{"type":"number"},"startDate":{"type":"string"},"endDate":{"type":"string","nullable":true},"chargedTo":{"type":"string","enum":["owner","agency"],"description":"`owner` reduces your payout; `agency` is shown for transparency"},"source":{"type":"string","enum":["agency","owner"],"description":"Who recorded the row"},"notes":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","unitSlug","unitName","categoryId","category","categoryGroup","label","amount","currency","recurrence","monthlyEquivalent","startDate","endDate","chargedTo","source","notes","createdAt"]},"LandlordCostCategory":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"label":{"type":"string"},"group":{"type":"string"},"defaultRecurrence":{"type":"string"},"ownerEditable":{"type":"boolean","description":"May you book rows in it? The agency's own lines are not yours"},"hint":{"type":"string","nullable":true}},"required":["id","key","label","group","defaultRecurrence","ownerEditable","hint"]},"CreateCost":{"type":"object","properties":{"unit":{"type":"string","minLength":1,"example":"marina-loft-2br"},"categoryId":{"type":"string","minLength":36,"maxLength":36},"label":{"type":"string","minLength":2,"maxLength":160},"amount":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Minor units per occurrence"},"recurrence":{"type":"string","enum":["one_time","monthly","quarterly","yearly"],"default":"one_time"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"endDate":{"type":"string","nullable":true,"pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"notes":{"type":"string","nullable":true,"maxLength":500}},"required":["unit","categoryId","label","amount","startDate"]},"LandlordDocument":{"type":"object","properties":{"id":{"type":"string"},"unitId":{"type":"string","nullable":true,"description":"null = concerns the whole relationship"},"unitName":{"type":"string","nullable":true},"title":{"type":"string"},"category":{"type":"string","enum":["contract","permit","statement","invoice","insurance","handover","other"]},"fileName":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":"number"},"uploadedBy":{"type":"string","enum":["agency","owner"]},"validUntil":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","unitId","unitName","title","category","fileName","mimeType","sizeBytes","uploadedBy","validUntil","notes","createdAt"]},"Thread":{"type":"object","properties":{"id":{"type":"string"},"unitId":{"type":"string","nullable":true},"unitName":{"type":"string","nullable":true},"subject":{"type":"string"},"status":{"type":"string","enum":["open","closed"]},"openedBy":{"type":"string","enum":["agency","owner"]},"unread":{"type":"number","description":"Messages from the office you have not read"},"lastMessageAt":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","unitId","unitName","subject","status","openedBy","unread","lastMessageAt","createdAt"]},"Message":{"type":"object","properties":{"id":{"type":"string"},"authorSide":{"type":"string","enum":["agency","owner"]},"authorName":{"type":"string"},"body":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","authorSide","authorName","body","createdAt"]},"NewThread":{"type":"object","properties":{"subject":{"type":"string","minLength":1,"maxLength":200},"body":{"type":"string","minLength":1,"maxLength":20000},"unit":{"type":"string","nullable":true,"description":"Unit slug the conversation is about"}},"required":["subject","body"]}},"parameters":{}},"paths":{"/me":{"get":{"tags":["Introspection"],"summary":"Who this key belongs to","description":"No scope needed. Answers which agency manages the apartments, which landlord this key is bound to, what the key may do and how much budget is left — wire this up first.","responses":{"200":{"description":"The agency, the key, its binding and its budgets","content":{"application/json":{"schema":{"type":"object","properties":{"audience":{"type":"string","enum":["agency","landlord","cleaning"],"description":"Which door this key opens"},"tenant":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"currency":{"type":"string","example":"AED"},"timezone":{"type":"string","example":"Asia/Dubai"}},"required":["id","name","slug","currency","timezone"]},"key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true},"prefix":{"type":"string","nullable":true},"scopes":{"type":"array","items":{"type":"string","enum":["read:units","read:availability","read:rates","write:rates","read:bookings","read:guests","write:bookings","read:requests","read:tasks","write:tasks","read:finance","read:housekeeping","read:landlords","read:costs","landlord:read:units","landlord:read:finance","landlord:read:costs","landlord:write:costs","landlord:write:blocks","landlord:read:documents","landlord:messages","cleaning:read:jobs","cleaning:write:reports"]}},"createdAt":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true}},"required":["id","name","prefix","scopes","createdAt","expiresAt"]},"landlord":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Landlord keys: whose apartments and figures this key sees"},"cleaningCompany":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Cleaning keys: whose jobs this key sees"},"rateLimit":{"type":"object","properties":{"requestsPerMinute":{"type":"number"},"sharedWith":{"type":"array","items":{"type":"string"}}},"required":["requestsPerMinute","sharedWith"]},"quota":{"type":"object","properties":{"month":{"type":"string","example":"2026-08"},"used":{"type":"number"},"quota":{"type":"number"},"remaining":{"type":"number"},"resetsAt":{"type":"string"}},"required":["month","used","quota","remaining","resetsAt"]}},"required":["audience","tenant","key","landlord","cleaningCompany","rateLimit","quota"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/units":{"get":{"tags":["Units"],"summary":"My units","description":"Every apartment you hold or held, with the tenure that ties it to you. Former units stay listed with `tenure.current = false` so your history keeps reading.","responses":{"200":{"description":"Your units","content":{"application/json":{"schema":{"type":"object","properties":{"units":{"type":"array","items":{"$ref":"#/components/schemas/LandlordUnit"}}},"required":["units"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/units/{slug}":{"get":{"tags":["Units"],"summary":"One of my units","parameters":[{"schema":{"type":"string"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"The unit","content":{"application/json":{"schema":{"type":"object","properties":{"unit":{"$ref":"#/components/schemas/LandlordUnit"}},"required":["unit"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not one of your units","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/availability":{"get":{"tags":["Units"],"summary":"Blocked nights of one of my units","description":"Nights that are taken in `[from, to)` — stays, own use, blocks and the cleaning block after a checkout. At most 366 days.","parameters":[{"schema":{"type":"string"},"required":true,"name":"unit","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"required":true,"name":"to","in":"query"}],"responses":{"200":{"description":"Blocked nights","content":{"application/json":{"schema":{"type":"object","properties":{"unit":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"blockedNights":{"type":"array","items":{"type":"string"}}},"required":["unit","from","to","blockedNights"]}}}},"400":{"description":"Range negative or over 366 days","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not one of your units","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/bookings":{"get":{"tags":["Units"],"summary":"Stays on my units","description":"Anonymised occupancy inside your tenure: dates, party size, status and gross amount — never a guest's name. Stays are attributed by arrival date, so a stay that arrived before you bought the unit belongs to the seller.","parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Stays with departure ≥ from"},"required":false,"name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Stays with arrival ≤ to"},"required":false,"name":"to","in":"query"},{"schema":{"type":"string","description":"Unit slug"},"required":false,"name":"unit","in":"query"},{"schema":{"type":"integer","minimum":1,"description":"1-based page number"},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"1–200, default 100"},"required":false,"name":"pageSize","in":"query"}],"responses":{"200":{"description":"One page of stays","content":{"application/json":{"schema":{"type":"object","properties":{"bookings":{"type":"array","items":{"$ref":"#/components/schemas/LandlordBooking"}},"page":{"type":"integer","example":1},"pageSize":{"type":"integer","example":100},"totalItems":{"type":"integer","example":428},"pageCount":{"type":"integer","example":5}},"required":["bookings","page","pageSize","totalItems","pageCount"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/bookings/{id}":{"get":{"tags":["Units"],"summary":"One stay on my units","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The stay","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/LandlordBooking"}},"required":["booking"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such stay inside your tenure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/blocks":{"post":{"tags":["Blocks"],"summary":"Block dates on one of my units","description":"Own use or a block — the only thing a landlord writes on the calendar. Only units you hold today, only dates inside your tenure, and never over an existing stay. The block is confirmed immediately and carries no price.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBlock"}}}},"responses":{"201":{"description":"The created block","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/LandlordBooking"}},"required":["booking"]}}}},"400":{"description":"Malformed body, or departure not after arrival","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not one of your current units","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The nights are taken; carries `conflict`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/blocks/{id}":{"delete":{"tags":["Blocks"],"summary":"Remove one of my future blocks","description":"Releases the nights of an own-use stay or block that has not started yet. Guest stays are not yours to touch and answer 404. Removing twice is not an error.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Removed (or already gone)","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such block of yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/statement":{"get":{"tags":["Finance"],"summary":"My statement for a period","description":"The same statement the portal and the printed PDF show: revenue per stay with the agency fee, running costs, payouts, open balance and the non-revenue facts (cancellations, complaints, own use).","parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"required":true,"name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"ISO date","example":"2027-04-05"},"required":true,"name":"to","in":"query"}],"responses":{"200":{"description":"The statement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LandlordStatement"}}}},"400":{"description":"`from` after `to`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/payouts":{"get":{"tags":["Finance"],"summary":"Payouts to me","description":"Every transfer the agency recorded to you, newest first, with the stay it settles.","parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Paid on or after"},"required":false,"name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Paid on or before"},"required":false,"name":"to","in":"query"}],"responses":{"200":{"description":"Your payouts","content":{"application/json":{"schema":{"type":"object","properties":{"payouts":{"type":"array","items":{"$ref":"#/components/schemas/Payout"}}},"required":["payouts"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invoices":{"get":{"tags":["Finance"],"summary":"Invoices for stays on my units","description":"The guest invoices issued for stays inside your tenure — number, date, total, status. No guest billing data; the document itself stays with the agency.","responses":{"200":{"description":"The invoices","content":{"application/json":{"schema":{"type":"object","properties":{"invoices":{"type":"array","items":{"$ref":"#/components/schemas/LandlordInvoice"}}},"required":["invoices"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/costs":{"get":{"tags":["Costs"],"summary":"Running costs of my units","description":"What the apartments cost each month and who carries which line — as the portal shows it. Categories the agency keeps internal are not listed, except where a row is deducted from your payout.","parameters":[{"schema":{"type":"string","description":"Unit slug"},"required":false,"name":"unit","in":"query"}],"responses":{"200":{"description":"Cost rows and monthly totals","content":{"application/json":{"schema":{"type":"object","properties":{"costs":{"type":"array","items":{"$ref":"#/components/schemas/LandlordCost"}},"monthly":{"type":"object","properties":{"owner":{"type":"number"},"agency":{"type":"number"}},"required":["owner","agency"],"description":"Recurring load per month, you vs. the agency"},"currency":{"type":"string"}},"required":["costs","monthly","currency"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Costs"],"summary":"Record a cost on one of my units","description":"Your DEWA bill, your insurance premium. Always charged to you and marked as your entry; only categories the agency opened to landlords are accepted.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCost"}}}},"responses":{"201":{"description":"The recorded cost","content":{"application/json":{"schema":{"type":"object","properties":{"cost":{"$ref":"#/components/schemas/LandlordCost"}},"required":["cost"]}}}},"400":{"description":"Malformed body or impossible dates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown unit or category","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/cost-categories":{"get":{"tags":["Costs"],"summary":"Categories I may book against","responses":{"200":{"description":"Visible categories; `ownerEditable` marks the bookable ones","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"$ref":"#/components/schemas/LandlordCostCategory"}}},"required":["categories"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/costs/{id}":{"delete":{"tags":["Costs"],"summary":"Remove a cost I recorded","description":"Only rows you recorded yourself (`source = owner`) can be removed here; the agency's bookkeeping answers 404.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Removed","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such cost of yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/documents":{"get":{"tags":["Documents"],"summary":"My documents","description":"The paperwork the office released to you — contracts, permits, statements, insurance — plus your own uploads. Metadata only; the bytes come from the download route.","parameters":[{"schema":{"type":"string","description":"Unit slug"},"required":false,"name":"unit","in":"query"}],"responses":{"200":{"description":"Your documents","content":{"application/json":{"schema":{"type":"object","properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/LandlordDocument"}}},"required":["documents"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/documents/{id}/download":{"get":{"tags":["Documents"],"summary":"Download a document","description":"The file itself, as an attachment. Never cached by intermediaries — a management contract does not belong in a shared cache.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The file","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such document of yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/messages":{"get":{"tags":["Messages"],"summary":"My conversations with the office","responses":{"200":{"description":"Threads, newest activity first","content":{"application/json":{"schema":{"type":"object","properties":{"threads":{"type":"array","items":{"$ref":"#/components/schemas/Thread"}},"unread":{"type":"number"}},"required":["threads","unread"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Messages"],"summary":"Open a conversation with the office","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewThread"}}}},"responses":{"201":{"description":"The new thread's id","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}},"400":{"description":"Subject or message empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not one of your units","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/messages/{id}":{"get":{"tags":["Messages"],"summary":"One conversation with its messages","description":"Reading marks the office's messages in it as read.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The conversation","content":{"application/json":{"schema":{"type":"object","properties":{"thread":{"$ref":"#/components/schemas/Thread"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}},"required":["thread","messages"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such conversation of yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/messages/{id}/replies":{"post":{"tags":["Messages"],"summary":"Reply in a conversation","description":"A reply reopens a closed thread — the office closes what it considers done, and you writing again clearly does not.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":20000}},"required":["body"]}}}},"responses":{"201":{"description":"The new message's id","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}},"400":{"description":"The message is empty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, the key belongs to another door, or it lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such conversation of yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-minute budget or monthly quota exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}