{"openapi":"3.1.0","info":{"title":"MyRentalCalendar Partner API","version":"1.0.0","description":"Read and write your own agency data. Every request authenticates with an API key you create in the agency portal; each key carries explicit scopes.\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)`."},"servers":[{"url":"https://api.myrentalcalendar.com/partner/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Introspection","description":"What this key is"},{"name":"Units","description":"The agency's apartments"},{"name":"Availability","description":"Which nights can be sold"},{"name":"Pricing","description":"What a stay costs"},{"name":"Bookings","description":"Reading, creating and cancelling stays"},{"name":"Guests","description":"Guest master data"}],"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"]},"Unit":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string","description":"Stable address of the unit","example":"marina-loft-2br"},"name":{"type":"string"},"status":{"type":"string","example":"published"},"city":{"type":"string","nullable":true},"area":{"type":"string","nullable":true},"building":{"type":"string","nullable":true},"bedrooms":{"type":"number"},"beds":{"type":"number"},"bathrooms":{"type":"number"},"maxGuests":{"type":"number"},"sizeSqm":{"type":"number","nullable":true},"basePrice":{"type":"number","description":"Nightly base price in minor units"},"cleaningFee":{"type":"number"},"minStay":{"type":"number"},"checkinTime":{"type":"string"},"checkoutTime":{"type":"string"},"instantBook":{"type":"boolean"}},"required":["id","slug","name","status","city","area","building","bedrooms","beds","bathrooms","maxGuests","sizeSqm","basePrice","cleaningFee","minStay","checkinTime","checkoutTime","instantBook"]},"Booking":{"type":"object","properties":{"id":{"type":"string"},"unitSlug":{"type":"string"},"unitName":{"type":"string"},"type":{"type":"string","example":"guest"},"status":{"type":"string","example":"confirmed"},"source":{"type":"string","example":"partner"},"arrival":{"type":"string"},"departure":{"type":"string"},"nights":{"type":"number"},"adults":{"type":"number"},"children":{"type":"number"},"totalAmount":{"type":"number","description":"Minor units of the agency currency"}},"required":["id","unitSlug","unitName","type","status","source","arrival","departure","nights","adults","children","totalAmount"]},"CreateBooking":{"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"},"status":{"type":"string","enum":["draft","option","confirmed"],"default":"confirmed","description":"`draft` and `option` are holds that release themselves"},"adults":{"type":"integer","minimum":1,"maximum":20,"default":2},"children":{"type":"integer","minimum":0,"maximum":10,"default":0},"extraBed":{"type":"boolean","default":false},"sourceRef":{"type":"string","nullable":true,"maxLength":120,"description":"Your own reference; returned on reads"},"notes":{"type":"string","nullable":true,"maxLength":2000},"holdHours":{"type":"integer","nullable":true,"minimum":1,"maximum":2160},"guest":{"type":"object","nullable":true,"properties":{"firstName":{"type":"string","maxLength":80},"lastName":{"type":"string","maxLength":80},"email":{"type":"string","nullable":true,"format":"email"},"phone":{"type":"string","nullable":true,"maxLength":60},"nationality":{"type":"string","nullable":true,"maxLength":60}}}},"required":["unit","arrival","departure"]},"Guest":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"nationality":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","firstName","lastName","email","phone","nationality","createdAt"]},"FeeType":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","description":"Shown to the guest verbatim"},"kind":{"type":"string","enum":["fixed","percent"]},"amount":{"type":"number","nullable":true},"pct":{"type":"number","nullable":true},"includesWeeklyCleaning":{"type":"boolean"}},"required":["id","label","kind","amount","pct","includesWeeklyCleaning"]}},"parameters":{}},"paths":{"/me":{"get":{"tags":["Introspection"],"summary":"Who this key belongs to","description":"The only route without a scope requirement: every valid key may ask what it is. Usually the first call an integration makes — it answers which agency, which rights and how much budget without a support ticket.","responses":{"200":{"description":"The agency, the key and its budgets","content":{"application/json":{"schema":{"type":"object","properties":{"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","read:bookings","read:guests","write:bookings"]}},"createdAt":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true}},"required":["id","name","prefix","scopes","createdAt","expiresAt"]},"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":["tenant","key","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, or the key 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":"List all units","description":"Every unit of the agency except archived ones, ordered by name. Draft units are included.","responses":{"200":{"description":"All units","content":{"application/json":{"schema":{"type":"object","properties":{"units":{"type":"array","items":{"$ref":"#/components/schemas/Unit"}}},"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, or the key 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 unit in full detail","parameters":[{"schema":{"type":"string","example":"marina-loft-2br"},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"The unit","content":{"application/json":{"schema":{"type":"object","properties":{"unit":{"$ref":"#/components/schemas/Unit"}},"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, or the key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No unit with that slug","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":["Availability"],"summary":"Blocked nights of a unit","description":"Nights that cannot be sold in `[from, to)` — real stays plus the cleaning block after a checkout. A date absent from the list is bookable. At most 366 days per request.","parameters":[{"schema":{"type":"string","example":"marina-loft-2br"},"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 in the range","content":{"application/json":{"schema":{"type":"object","properties":{"unit":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"blockedNights":{"type":"array","items":{"type":"string"},"example":["2027-04-06","2027-04-07"]}},"required":["unit","from","to","blockedNights"]}}}},"400":{"description":"Missing parameters, or a range that is 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, or the key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No unit with that slug","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"}}}}}}},"/quote":{"post":{"tags":["Pricing"],"summary":"Price a stay with the live engine","description":"The same engine the agency's own portal and website use, so the number you show is the number that will be invoiced. Also your availability and minimum-stay check.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"unit":{"type":"string","minLength":1},"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"}},"required":["unit","arrival","departure"]}}}},"responses":{"200":{"description":"The priced stay","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean"},"instantBook":{"type":"boolean"},"currency":{"type":"string"},"quote":{"type":"object","properties":{"nights":{"type":"number"},"currency":{"type":"string"},"total":{"type":"number"},"lines":{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}}},"required":["nights","currency","total","lines"]}},"required":["available","instantBook","currency","quote"]}}}},"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, or the key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No unit with that slug","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Below the effective minimum stay; carries `minStay`","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":["Bookings"],"summary":"List bookings","description":"Booking rows without guest personal data — those need the separate `read:guests` scope.","parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Bookings with departure ≥ from"},"required":false,"name":"from","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Bookings with arrival ≤ to"},"required":false,"name":"to","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","description":"Unit slug"},"required":false,"name":"unit","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"description":"Older alias for pageSize"},"required":false,"name":"limit","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 bookings","content":{"application/json":{"schema":{"type":"object","properties":{"bookings":{"type":"array","items":{"$ref":"#/components/schemas/Booking"}},"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"]}}}},"400":{"description":"A date parameter is not YYYY-MM-DD","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, or the key 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":["Bookings"],"summary":"Create a booking","description":"Runs the same gauntlet as the agency's own portal — minimum stay, cleaning block, announced extensions, then the hard night guard. **There is no price field**: the total comes from the pricing engine, because an invoice has to be able to explain every number it carries.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBooking"}}}},"responses":{"201":{"description":"The created booking","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"}},"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, or the key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No unit with that slug","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`BOOKING_CONFLICT`, `TURNOVER_BLOCK_CONFLICT` or `EXPECTED_EXTENSION_CONFLICT`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Below the effective minimum stay; carries `minStay`","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":["Bookings"],"summary":"One booking","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The booking","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"}},"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, or the key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No booking with that id in this agency","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}/cancel":{"post":{"tags":["Bookings"],"summary":"Cancel a booking","description":"Releases the nights and keeps the record with your reason. Cancelling something already cancelled answers 200 with the unchanged booking, so a retry after a timeout is safe.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","nullable":true,"maxLength":255}}}}}},"responses":{"200":{"description":"The cancelled booking","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"allOf":[{"$ref":"#/components/schemas/Booking"},{"nullable":true}]}},"required":["booking"]}}}},"400":{"description":"Malformed body","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, or the key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No booking with that id in this agency","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"}}}}}}},"/guests":{"get":{"tags":["Guests"],"summary":"List guest records","description":"Guest master data. Identity documents captured at check-in are encrypted, deleted on a retention schedule and never available here.","parameters":[{"schema":{"type":"string","description":"Applied from 2 characters"},"required":false,"name":"search","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 guests","content":{"application/json":{"schema":{"type":"object","properties":{"guests":{"type":"array","items":{"$ref":"#/components/schemas/Guest"}},"page":{"type":"integer","example":1},"pageSize":{"type":"integer","example":100},"totalItems":{"type":"integer","example":428},"pageCount":{"type":"integer","example":5}},"required":["guests","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, or the key 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"}}}}}}},"/guests/{id}":{"get":{"tags":["Guests"],"summary":"One guest with their stays","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The guest and references to their stays","content":{"application/json":{"schema":{"type":"object","properties":{"guest":{"allOf":[{"$ref":"#/components/schemas/Guest"},{"type":"object","properties":{"stays":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"unitSlug":{"type":"string"},"arrival":{"type":"string"},"departure":{"type":"string"},"status":{"type":"string"}},"required":["id","unitSlug","arrival","departure","status"]}}},"required":["stays"]}]}},"required":["guest"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, or the key lacks the scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No guest with that id in this agency","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"}}}}}}},"/fee-types":{"get":{"tags":["Pricing"],"summary":"The agency's active fee catalogue","description":"What a quote can draw its surcharge lines from. Inactive fee types are not returned.","responses":{"200":{"description":"Active fee types","content":{"application/json":{"schema":{"type":"object","properties":{"feeTypes":{"type":"array","items":{"$ref":"#/components/schemas/FeeType"}}},"required":["feeTypes"]}}}},"401":{"description":"Missing, unknown, revoked or expired key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan does not include API access, or the key 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"}}}}}}}}}