{"openapi":"3.1.0","info":{"title":"ZimmerStack Connect API","version":"v1","description":"Two integrations, one key format. CHANNEL MANAGER (scopes ari:*): your PMS pushes availability, rates and restrictions; ZimmerStack fans them out to every connected OTA, and OTA bookings reach you through the outbound webhooks (GET /api/v1/public/webhooks/contract). PMS (scopes bookings:*): your OWN booking engine hands the reservation your website sold to the ZimmerStack PMS; inventory and the channels update exactly as for a front-desk booking. A channel-manager-only tenant has no booking endpoints on purpose: a walk-in in its PMS becomes an absolute availability count here.","contact":{"name":"ZimmerStack support","email":"support@zimmerstack.com"}},"servers":[{"url":"https://api.zimmerstack.com","description":"production"}],"x-zimmerstack":{"auth":{"scheme":"Authorization: Bearer zsk_live_…","keyShape":"zsk_live_ + 43 base64url characters; shown once at creation; one key = one property","never":["query string","x-api-key","user-api-key"],"scopes":[{"scope":"ari:read","does":"Read availability, rates, restrictions and sync state from our record"},{"scope":"ari:write","does":"Set availability, rates and restrictions (pushed to every connected channel)"},{"scope":"bookings:read","does":"Read bookings this key created"},{"scope":"bookings:write","does":"Create and cancel bookings in the PMS (inventory updates and reaches the channels)"},{"scope":"bookings:payments","does":"Record a payment on a booking it creates (needs bookings:write)"}],"scopeRule":"A key holds the scopes the owner granted at creation (editable later without rotating). Every route names the one scope it needs; a key without it is 403 SCOPE_MISSING. bookings:payments needs bookings:write. GET /property echoes this key's scopes.","allowlist":"Optional per key: up to 20 IPv4/IPv6 addresses or CIDR ranges. Set it to your servers' egress addresses: a request from anywhere else is 403 IP_NOT_ALLOWED, counts against the address's authentication budget, and is shown to the owner."},"dates":"YYYY-MM-DD, calendar dates in the property's timezone (GET /property); a stay occupies [checkIn, checkOut) — the checkout day is not a night","money":"rates are SENT in major units with the property's currency and RETURNED in minor units (rateMinor); stored as whole major units","writes":"absolute values, last write wins within a request, unchanged cells are dropped before anything is written","limits":{"requestsPerMinute":120,"writesPerMinute":30,"propertyRequestsPerMinute":300,"propertyWritesPerMinute":60,"propertyCellsPerMinute":20000,"ipRequestsPerMinute":240,"maxUpdatesPerRequest":1000,"maxCellsPerRequest":5000,"maxBodyBytes":1048576,"horizonDays":365,"bookingsPerMinute":20,"propertyBookingsPerMinute":40,"propertyBookingsPerDay":500,"maxNightsPerBooking":90},"bookings":{"who":"Hotels that run the ZimmerStack PMS and their OWN booking engine: hand us the reservation your website sold and it lands in the PMS exactly as a front-desk booking — guest, folio, inventory, channels.","pricing":"You price the stay. Send the nightly rate you charged per room; we store it and never re-quote. currency must equal the property's.","inventory":"Availability is checked inside the booking transaction under the property's inventory lock (a sold-out night is 409 NO_AVAILABILITY, nothing written). The inventory event commits with the booking; the drain pushes the new counts to every connected channel within seconds.","idempotency":"externalReference is YOUR reservation id and is unique per property: the same value again returns the same booking with HTTP 200 and replay: true. Use it on every retry.","payments":"A payment is recorded only when the key holds bookings:payments and never above the stay total. Nothing collected = omit payment; the desk collects at check-in.","guest":"By default the guest hears from YOUR site only; the owner can switch on our confirmation per property (admin → Developers → Settings).","cancel":"POST /bookings/{bookingId}/cancel cancels the whole booking and re-opens its nights on the channels; a booking already checked in is 409 BOOKING_NOT_CANCELLABLE. Date or room changes: cancel and re-create (a modify endpoint is planned).","scope":"A key reads and cancels only bookings the API created on its property; front-desk and OTA bookings are never visible (BOOKING_NOT_FOUND)."},"rateLimits":{"window":"60 s sliding, shared by every API machine; counters are exact, not per machine","scopes":[{"scope":"ip","perMinute":240,"counts":"every request from one address, checked before the key is read"},{"scope":"ip-auth","perMinute":20,"counts":"401 answers to one address; after that the address is refused before any lookup"},{"scope":"requests","perMinute":120,"counts":"every request on one key"},{"scope":"writes","perMinute":30,"counts":"PUT requests on one key"},{"scope":"property","perMinute":300,"counts":"every request on all of a property's keys together (five keys are not five budgets)"},{"scope":"property-writes","perMinute":60,"counts":"PUT requests on all of a property's keys together"},{"scope":"cells","perMinute":20000,"counts":"cells a property's writes name after range expansion, charged before anything is read or written"},{"scope":"bookings","perMinute":20,"counts":"POST /bookings on one key"},{"scope":"property-bookings","perMinute":40,"counts":"POST /bookings on all of a property's keys together"},{"scope":"property-bookings-day","perMinute":500,"counts":"POST /bookings per property per ROLLING 24 HOURS (not per minute); the owner can raise it per property"},{"scope":"global","perMinute":3000,"counts":"every request on the Connect API, all keys and addresses"}],"headers":{"RateLimit-Policy":"on every answer, one quoted policy per key scope — \"key\";q=120;w=60, \"key-writes\";q=30;w=60","RateLimit":"on every answer, what is left and when it refills — \"key\";r=117;t=42, \"key-writes\";r=29;t=42","Retry-After":"on every 429, whole seconds to wait; the body's data.scope says which budget refused"},"onRefusal":"429 RATE_LIMITED. Wait Retry-After, then resend the same request. Never retry in a tight loop; never retry any other 4xx.","tooLarge":"413 when the JSON body exceeds 1048576 bytes; split the updates array","pace":["Batch: one PUT per resource carrying ranges (dateFrom..dateTo, optional days) — a 365-night calendar for three plans is a handful of updates, not a thousand","Send on change, not on a timer: unchanged cells are dropped and cost nothing, but they still spend your request budget","Read RateLimit on every answer and slow down when r approaches 0, instead of waiting for a 429","Reuse x-idempotency-key on a retry so a timed-out request can never land twice","Poll GET /batches/{batchId} and GET /sync no more than every 15 s; the push to the channels is asynchronous and bounded by the channel manager's own budget"],"channelManager":{"whyAsynchronous":"Your 202 means the cells are in our record. Pushing them to the channel manager is paced by its budget — ten rate/restriction reads a minute for the whole account and a per-property write budget — so a full calendar takes minutes, never seconds, and is never lost.","whatWeDo":"We coalesce your cells into the fewest channel-manager calls, drop what did not change, pace every call, stop before the channel manager's last token, and back off on its Retry-After — you never have to think about its limits, only about ours."}},"postman":{"collection":"/api/v1/public/connect-api/postman","environment":"/api/v1/public/connect-api/postman?environment=1","note":"A Postman v2.1 collection generated from this contract: import both, paste your key into the environment's apiKey, and run the folders top to bottom."},"idempotency":{"header":"x-idempotency-key","retentionDays":7},"errorCodes":["API_KEY_INVALID","API_KEY_REVOKED","CONNECT_API_NOT_CONFIGURED","IP_NOT_ALLOWED","SCOPE_MISSING","PROPERTY_UNAVAILABLE","CHANNEL_MANAGER_DISABLED","PMS_NOT_AVAILABLE","VALIDATION","RANGE_INVALID","HORIZON","TOO_MANY_UPDATES","TOO_MANY_CELLS","UNKNOWN_ROOM_TYPE","UNKNOWN_RATE_PLAN","CURRENCY_MISMATCH","RATE_LIMITED","NOTHING_ACCEPTED","BATCH_NOT_FOUND","IDEMPOTENCY_KEY_INVALID","IDEMPOTENCY_KEY_REUSED","IDEMPOTENCY_IN_FLIGHT","STAY_INVALID","UNKNOWN_ROOM_TYPE_FOR_PLAN","OCCUPANCY_EXCEEDED","NO_AVAILABILITY","EXTERNAL_REFERENCE_REUSED","PAYMENT_NOT_ALLOWED","PAYMENT_EXCEEDS_TOTAL","BOOKING_NOT_FOUND","BOOKING_NOT_CANCELLABLE","MODULE_NOT_ENTITLED"],"samples":{"availabilityWrite":{"updates":[{"roomTypeId":412,"dateFrom":"2026-11-01","dateTo":"2026-11-30","available":5},{"roomTypeId":412,"dateFrom":"2026-11-14","dateTo":"2026-11-14","available":2}]},"ratesWrite":{"updates":[{"ratePlanId":901,"dateFrom":"2026-11-01","dateTo":"2027-03-31","rate":"4500.00","currency":"INR"},{"ratePlanId":901,"dateFrom":"2026-11-01","dateTo":"2027-03-31","days":["fr","sa"],"rate":5200,"currency":"INR"}]},"restrictionsWrite":{"updates":[{"ratePlanId":901,"dateFrom":"2026-12-24","dateTo":"2026-12-26","minStayArrival":2,"closedToArrival":false},{"ratePlanId":901,"dateFrom":"2026-12-31","dateTo":"2026-12-31","stopSell":true}]},"bookingCreate":{"externalReference":"WEB-2026-000123","checkIn":"2026-12-20","checkOut":"2026-12-23","currency":"INR","guest":{"name":"Asha Verma","phone":"+919876543210","email":"asha@example.com","notes":"Late arrival, after 22:00"},"rooms":[{"roomTypeId":412,"ratePlanId":901,"adults":2,"children":1,"nightlyRate":"4500.00"},{"roomTypeId":412,"ratePlanId":901,"adults":2,"nightlyRate":"4500.00"}],"payment":{"amount":"9000.00","method":"ONLINE","reference":"pay_QwErTy123"},"notes":"Promo WINTER10 applied on the website"},"bookingCancel":{"reason":"Guest cancelled on the website"},"bookingView":{"bookingId":48213,"reference":"SB-7KQ2MX9D","externalReference":"WEB-2026-000123","status":"UPCOMING","checkIn":"2026-12-20","checkOut":"2026-12-23","nights":3,"currency":"INR","totalAmount":"27000.00","totalPaid":"9000.00","balanceDue":"18000.00","guest":{"name":"Asha Verma","phone":"+919876543210","email":"asha@example.com"},"rooms":[{"bookingRoomId":90001,"roomTypeId":412,"ratePlanId":null,"mealPlan":"CP","adults":2,"children":1,"nightlyRate":"4500.00","status":"UPCOMING"},{"bookingRoomId":90002,"roomTypeId":412,"ratePlanId":null,"mealPlan":"CP","adults":2,"children":0,"nightlyRate":"4500.00","status":"UPCOMING"}],"inventory":{"eventRecorded":true,"channelManager":true,"pushedBy":"inventory-drain"},"replay":false,"createdAt":"2026-10-20T09:14:03.201Z","cancelledAt":null},"writeAccepted":{"batchId":"7f1d2c4e-5a6b-4c8d-9e0f-112233445566","resource":"rates","requestedCells":151,"acceptedCells":43,"noopCells":108,"rejected":[],"pushedBy":"ari-projector","poll":"/api/v1/connect-api/v1/batches/7f1d2c4e-5a6b-4c8d-9e0f-112233445566"},"batchPending":{"batchId":"7f1d2c4e-5a6b-4c8d-9e0f-112233445566","resource":"rates","createdAt":"2026-10-12T09:14:03.201Z","requestedCells":151,"acceptedCells":43,"noopCells":108,"rejected":[],"status":"pending","pendingCells":12,"lastError":null},"errors":{"API_KEY_INVALID":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}},"API_KEY_REVOKED":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_REVOKED"}},"IP_NOT_ALLOWED":{"statuscode":403,"message":"This API key may not be used from this address. The property owner restricts it to an allowlist.","data":{"code":"IP_NOT_ALLOWED"}},"SCOPE_MISSING":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}},"PROPERTY_UNAVAILABLE":{"statuscode":409,"message":"This property is not available to the API any more. Contact the property owner.","data":{"code":"PROPERTY_UNAVAILABLE"}},"CHANNEL_MANAGER_DISABLED":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}},"PMS_NOT_AVAILABLE":{"statuscode":409,"message":"This property runs the channel manager only; there is no PMS to put a booking in.","data":{"code":"PMS_NOT_AVAILABLE"}},"VALIDATION":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}},"HORIZON":{"statuscode":400,"message":"updates[0]: 2028-01-01 is beyond the horizon (last writable night is 2027-10-12, today + 365 days)","data":{"code":"HORIZON"}},"TOO_MANY_CELLS":{"statuscode":400,"message":"a request may name at most 5000 cells (entity × night); split the calendar into several requests","data":{"code":"TOO_MANY_CELLS"}},"UNKNOWN_RATE_PLAN":{"statuscode":400,"message":"rate plan(s) 77 do not belong to this property (see GET /catalog)","data":{"code":"UNKNOWN_RATE_PLAN","details":{"ratePlanIds":[77]}}},"CURRENCY_MISMATCH":{"statuscode":400,"message":"rates must be sent in INR (got EUR)","data":{"code":"CURRENCY_MISMATCH","details":{"expected":"INR","got":"EUR"}}},"RATE_LIMITED":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}},"NOTHING_ACCEPTED":{"statuscode":422,"message":"exceptions are switched off for this property — move the base rate instead","data":{"code":"NOTHING_ACCEPTED","details":{"rejected":[{"cells":151,"error":"exceptions are switched off for this property — move the base rate instead"}]}}},"BATCH_NOT_FOUND":{"statuscode":404,"message":"Batch not found.","data":{"code":"BATCH_NOT_FOUND"}},"STAY_INVALID":{"statuscode":400,"message":"checkIn 2026-10-01 is in the past (today at the property is 2026-10-20)","data":{"code":"STAY_INVALID","details":{"today":"2026-10-20"}}},"OCCUPANCY_EXCEEDED":{"statuscode":400,"message":"rooms[0]: Deluxe takes at most 3 adults (got 4)","data":{"code":"OCCUPANCY_EXCEEDED","details":{"index":0,"roomTypeId":412,"maxAdults":3}}},"NO_AVAILABILITY":{"statuscode":409,"message":"room type 412 has 0 left on 2026-12-21; 1 requested","data":{"code":"NO_AVAILABILITY","details":{"roomTypeId":412,"date":"2026-12-21","available":0,"requested":1}}},"PAYMENT_NOT_ALLOWED":{"statuscode":403,"message":"This API key may not record payments. The property owner grants the bookings:payments scope.","data":{"code":"PAYMENT_NOT_ALLOWED","details":{"needed":"bookings:payments"}}},"PAYMENT_EXCEEDS_TOTAL":{"statuscode":400,"message":"payment.amount 30000.00 exceeds the stay total 27000.00","data":{"code":"PAYMENT_EXCEEDS_TOTAL","details":{"amount":"30000.00","total":"27000.00"}}},"BOOKING_NOT_FOUND":{"statuscode":404,"message":"Booking not found.","data":{"code":"BOOKING_NOT_FOUND"}},"BOOKING_NOT_CANCELLABLE":{"statuscode":409,"message":"Booking already checked in. Ask the hotel to handle it at the desk.","data":{"code":"BOOKING_NOT_CANCELLABLE"}},"MODULE_NOT_ENTITLED":{"statuscode":402,"message":"This property's plan does not include the PMS.","data":{"code":"MODULE_NOT_ENTITLED","details":{"module":"PMS"}}},"IDEMPOTENCY_KEY_REUSED":{"statuscode":409,"code":"IDEMPOTENCY_KEY_REUSED","message":"This idempotency key was already used with a different request body."}}}},"paths":{"/api/v1/connect-api/v1/property":{"get":{"summary":"The property this key is for","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Property"}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/catalog":{"get":{"summary":"Room types and rate plans with the numeric ids every write uses","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Catalog"}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/availability":{"get":{"summary":"Availability as our record holds it","description":"Served from our record, never from the channel manager.","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"description":"Default: today in the property's timezone"},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"description":"Default: from + 30 days; at most 500 days after from"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailabilityRead"}}}},"400":{"description":"Bad range (data.code RANGE_INVALID)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}},"put":{"summary":"Set absolute availability","description":"Each update sets the ABSOLUTE number of rooms for sale for one room type over a date range. Lands in our record and rides the inventory drain to the channels.","parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{10,64}$"},"description":"Optional. Same key + same body within 7 days replays the stored answer (X-Idempotent-Replay: true); same key + different body is refused (409 IDEMPOTENCY_KEY_REUSED)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailabilityWrite"},"example":{"updates":[{"roomTypeId":412,"dateFrom":"2026-11-01","dateTo":"2026-11-30","available":5},{"roomTypeId":412,"dateFrom":"2026-11-14","dateTo":"2026-11-14","available":2}]}}}},"responses":{"202":{"description":"Accepted. The cells that differed from our record are written and queued; the push to the channels is asynchronous (typically seconds, minutes under load, bounded by the channel manager's budget, never lost). Poll `poll` or GET /sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteAccepted"},"example":{"batchId":"7f1d2c4e-5a6b-4c8d-9e0f-112233445566","resource":"rates","requestedCells":151,"acceptedCells":43,"noopCells":108,"rejected":[],"pushedBy":"ari-projector","poll":"/api/v1/connect-api/v1/batches/7f1d2c4e-5a6b-4c8d-9e0f-112233445566"}}}},"400":{"description":"data.code is one of VALIDATION | RANGE_INVALID | HORIZON | TOO_MANY_UPDATES | TOO_MANY_CELLS | UNKNOWN_ROOM_TYPE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"413":{"description":"Body larger than 1048576 bytes (x-zimmerstack.limits.maxBodyBytes); nothing was read"},"422":{"description":"Every group was refused by the property's rate policy; data.details.rejected says why","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":422,"message":"exceptions are switched off for this property — move the base rate instead","data":{"code":"NOTHING_ACCEPTED","details":{"rejected":[{"cells":151,"error":"exceptions are switched off for this property — move the base rate instead"}]}}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/rates":{"get":{"summary":"Rates as our record holds them (minor units)","description":"Served from our record, never from the channel manager.","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"description":"Default: today in the property's timezone"},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"description":"Default: from + 30 days; at most 500 days after from"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatesRead"}}}},"400":{"description":"Bad range (data.code RANGE_INVALID)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}},"put":{"summary":"Set nightly sell prices","description":"Each update sets the price of one rate plan over a date range, optionally masked to weekdays (`days`). `currency` must equal the property's. Lands in our record and rides the ARI projector to the channels.","parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{10,64}$"},"description":"Optional. Same key + same body within 7 days replays the stored answer (X-Idempotent-Replay: true); same key + different body is refused (409 IDEMPOTENCY_KEY_REUSED)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatesWrite"},"example":{"updates":[{"ratePlanId":901,"dateFrom":"2026-11-01","dateTo":"2027-03-31","rate":"4500.00","currency":"INR"},{"ratePlanId":901,"dateFrom":"2026-11-01","dateTo":"2027-03-31","days":["fr","sa"],"rate":5200,"currency":"INR"}]}}}},"responses":{"202":{"description":"Accepted. The cells that differed from our record are written and queued; the push to the channels is asynchronous (typically seconds, minutes under load, bounded by the channel manager's budget, never lost). Poll `poll` or GET /sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteAccepted"},"example":{"batchId":"7f1d2c4e-5a6b-4c8d-9e0f-112233445566","resource":"rates","requestedCells":151,"acceptedCells":43,"noopCells":108,"rejected":[],"pushedBy":"ari-projector","poll":"/api/v1/connect-api/v1/batches/7f1d2c4e-5a6b-4c8d-9e0f-112233445566"}}}},"400":{"description":"data.code is one of VALIDATION | RANGE_INVALID | HORIZON | TOO_MANY_UPDATES | TOO_MANY_CELLS | UNKNOWN_RATE_PLAN | CURRENCY_MISMATCH","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"413":{"description":"Body larger than 1048576 bytes (x-zimmerstack.limits.maxBodyBytes); nothing was read"},"422":{"description":"Every group was refused by the property's rate policy; data.details.rejected says why","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":422,"message":"exceptions are switched off for this property — move the base rate instead","data":{"code":"NOTHING_ACCEPTED","details":{"rejected":[{"cells":151,"error":"exceptions are switched off for this property — move the base rate instead"}]}}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/restrictions":{"get":{"summary":"Restrictions as our record holds them","description":"null = we hold no opinion for that field on that night.","parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"description":"Default: today in the property's timezone"},{"name":"to","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"description":"Default: from + 30 days; at most 500 days after from"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestrictionsRead"}}}},"400":{"description":"Bad range (data.code RANGE_INVALID)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}},"put":{"summary":"Set stay restrictions","description":"Each update sets ANY subset of stopSell, closedToArrival, closedToDeparture, minStayArrival, minStayThrough, maxStay for one rate plan over a date range; fields you omit are left as they are.","parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{10,64}$"},"description":"Optional. Same key + same body within 7 days replays the stored answer (X-Idempotent-Replay: true); same key + different body is refused (409 IDEMPOTENCY_KEY_REUSED)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestrictionsWrite"},"example":{"updates":[{"ratePlanId":901,"dateFrom":"2026-12-24","dateTo":"2026-12-26","minStayArrival":2,"closedToArrival":false},{"ratePlanId":901,"dateFrom":"2026-12-31","dateTo":"2026-12-31","stopSell":true}]}}}},"responses":{"202":{"description":"Accepted. The cells that differed from our record are written and queued; the push to the channels is asynchronous (typically seconds, minutes under load, bounded by the channel manager's budget, never lost). Poll `poll` or GET /sync.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteAccepted"},"example":{"batchId":"7f1d2c4e-5a6b-4c8d-9e0f-112233445566","resource":"rates","requestedCells":151,"acceptedCells":43,"noopCells":108,"rejected":[],"pushedBy":"ari-projector","poll":"/api/v1/connect-api/v1/batches/7f1d2c4e-5a6b-4c8d-9e0f-112233445566"}}}},"400":{"description":"data.code is one of VALIDATION | RANGE_INVALID | HORIZON | TOO_MANY_UPDATES | TOO_MANY_CELLS | UNKNOWN_RATE_PLAN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"413":{"description":"Body larger than 1048576 bytes (x-zimmerstack.limits.maxBodyBytes); nothing was read"},"422":{"description":"Every group was refused by the property's rate policy; data.details.rejected says why","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":422,"message":"exceptions are switched off for this property — move the base rate instead","data":{"code":"NOTHING_ACCEPTED","details":{"rejected":[{"cells":151,"error":"exceptions are switched off for this property — move the base rate instead"}]}}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/sync":{"get":{"summary":"Has what you sent reached the channels?","description":"Poll this instead of asking the channel manager: inventory pipe state, rate cells still queued, the projector's last outcome and the newest batch still pending.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncStatus"}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/bookings":{"get":{"summary":"Bookings the API created on this property, newest first","description":"Scope bookings:read. Only bookings a key of this property created; front-desk and OTA bookings are never listed.","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Created on or after this instant; default the last 7 days"},{"name":"externalReference","in":"query","required":false,"schema":{"type":"string","maxLength":64},"description":"Only the booking with your reservation id"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100},"description":"Default 50"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingsList"}}}},"400":{"description":"Bad query (data.code VALIDATION)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"updates[0].available: Expected number, received string","data":{"code":"VALIDATION","details":[{"path":["updates",0,"available"],"message":"Expected number, received string"}]}}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}},"post":{"summary":"Create a booking in the PMS from your own booking engine","description":"Scope bookings:write (+ bookings:payments to record a payment). One entry in `rooms` per room. The stay is checked for availability under the property's inventory lock and written with its inventory event in one transaction; the channels update within seconds. A repeated externalReference answers 200 with the same booking (replay: true). 1–90 nights, arrival from today to today + horizonDays, in the property's timezone.","parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{10,64}$"},"description":"Optional on top of externalReference: same key + same body within 7 days replays the stored answer."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingCreate"},"example":{"externalReference":"WEB-2026-000123","checkIn":"2026-12-20","checkOut":"2026-12-23","currency":"INR","guest":{"name":"Asha Verma","phone":"+919876543210","email":"asha@example.com","notes":"Late arrival, after 22:00"},"rooms":[{"roomTypeId":412,"ratePlanId":901,"adults":2,"children":1,"nightlyRate":"4500.00"},{"roomTypeId":412,"ratePlanId":901,"adults":2,"nightlyRate":"4500.00"}],"payment":{"amount":"9000.00","method":"ONLINE","reference":"pay_QwErTy123"},"notes":"Promo WINTER10 applied on the website"}}}},"responses":{"200":{"description":"Already created by an earlier call with this externalReference (replay: true)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"201":{"description":"Created. The booking is in the PMS; inventory.pushedBy says how the channels learn.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"},"example":{"bookingId":48213,"reference":"SB-7KQ2MX9D","externalReference":"WEB-2026-000123","status":"UPCOMING","checkIn":"2026-12-20","checkOut":"2026-12-23","nights":3,"currency":"INR","totalAmount":"27000.00","totalPaid":"9000.00","balanceDue":"18000.00","guest":{"name":"Asha Verma","phone":"+919876543210","email":"asha@example.com"},"rooms":[{"bookingRoomId":90001,"roomTypeId":412,"ratePlanId":null,"mealPlan":"CP","adults":2,"children":1,"nightlyRate":"4500.00","status":"UPCOMING"},{"bookingRoomId":90002,"roomTypeId":412,"ratePlanId":null,"mealPlan":"CP","adults":2,"children":0,"nightlyRate":"4500.00","status":"UPCOMING"}],"inventory":{"eventRecorded":true,"channelManager":true,"pushedBy":"inventory-drain"},"replay":false,"createdAt":"2026-10-20T09:14:03.201Z","cancelledAt":null}}}},"400":{"description":"data.code is one of VALIDATION | CURRENCY_MISMATCH | STAY_INVALID | UNKNOWN_ROOM_TYPE | UNKNOWN_RATE_PLAN | UNKNOWN_ROOM_TYPE_FOR_PLAN | OCCUPANCY_EXCEEDED | PAYMENT_EXCEEDS_TOTAL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":400,"message":"checkIn 2026-10-01 is in the past (today at the property is 2026-10-20)","data":{"code":"STAY_INVALID","details":{"today":"2026-10-20"}}}}}},"401":{"description":"Missing, malformed, unknown or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"402":{"description":"The property's plan does not carry the PMS","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":402,"message":"This property's plan does not include the PMS.","data":{"code":"MODULE_NOT_ENTITLED","details":{"module":"PMS"}}}}}},"403":{"description":"SCOPE_MISSING (no bookings:write), IP_NOT_ALLOWED, or PAYMENT_NOT_ALLOWED (a payment without bookings:payments)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key may not record payments. The property owner grants the bookings:payments scope.","data":{"code":"PAYMENT_NOT_ALLOWED","details":{"needed":"bookings:payments"}}}}}},"409":{"description":"NO_AVAILABILITY (the night and the count are in details; nothing was written), PROPERTY_UNAVAILABLE, PMS_NOT_AVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"room type 412 has 0 left on 2026-12-21; 1 requested","data":{"code":"NO_AVAILABILITY","details":{"roomTypeId":412,"date":"2026-12-21","available":0,"requested":1}}}}}},"413":{"description":"Body larger than 1048576 bytes (x-zimmerstack.limits.maxBodyBytes); nothing was read"},"429":{"description":"data.scope is bookings · property-bookings · property-bookings-day (a rolling day) or one of the request budgets; honour Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/bookings/{bookingId}":{"get":{"summary":"One booking the API created","parameters":[{"name":"bookingId","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"},"example":{"bookingId":48213,"reference":"SB-7KQ2MX9D","externalReference":"WEB-2026-000123","status":"UPCOMING","checkIn":"2026-12-20","checkOut":"2026-12-23","nights":3,"currency":"INR","totalAmount":"27000.00","totalPaid":"9000.00","balanceDue":"18000.00","guest":{"name":"Asha Verma","phone":"+919876543210","email":"asha@example.com"},"rooms":[{"bookingRoomId":90001,"roomTypeId":412,"ratePlanId":null,"mealPlan":"CP","adults":2,"children":1,"nightlyRate":"4500.00","status":"UPCOMING"},{"bookingRoomId":90002,"roomTypeId":412,"ratePlanId":null,"mealPlan":"CP","adults":2,"children":0,"nightlyRate":"4500.00","status":"UPCOMING"}],"inventory":{"eventRecorded":true,"channelManager":true,"pushedBy":"inventory-drain"},"replay":false,"createdAt":"2026-10-20T09:14:03.201Z","cancelledAt":null}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"404":{"description":"No such booking on this property, or not one the API created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":404,"message":"Booking not found.","data":{"code":"BOOKING_NOT_FOUND"}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/bookings/{bookingId}/cancel":{"post":{"summary":"Cancel a booking the API created; its nights re-open on the channels","description":"Scope bookings:write. Idempotent: an already-cancelled booking answers 200 with replay: true. A booking the desk has checked in is 409 BOOKING_NOT_CANCELLABLE.","parameters":[{"name":"bookingId","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingCancel"},"example":{"reason":"Guest cancelled on the website"}}}},"responses":{"200":{"description":"Cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"401":{"description":"Missing, malformed, unknown or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks bookings:write, or the address is outside the allowlist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"404":{"description":"No such booking on this property, or not one the API created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":404,"message":"Booking not found.","data":{"code":"BOOKING_NOT_FOUND"}}}}},"409":{"description":"Checked in or otherwise not cancellable from the API; PROPERTY_UNAVAILABLE; PMS_NOT_AVAILABLE","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"Booking already checked in. Ask the hotel to handle it at the desk.","data":{"code":"BOOKING_NOT_CANCELLABLE"}}}}},"429":{"description":"A request budget was exhausted; honour Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}},"/api/v1/connect-api/v1/batches/{batchId}":{"get":{"summary":"One accepted write and whether it has landed","parameters":[{"name":"batchId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchStatus"},"example":{"batchId":"7f1d2c4e-5a6b-4c8d-9e0f-112233445566","resource":"rates","createdAt":"2026-10-12T09:14:03.201Z","requestedCells":151,"acceptedCells":43,"noopCells":108,"rejected":[],"status":"pending","pendingCells":12,"lastError":null}}}},"401":{"description":"Missing, malformed, unknown or revoked key (data.code API_KEY_INVALID | API_KEY_REVOKED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":401,"message":"Unauthorized","data":{"code":"API_KEY_INVALID"}}}}},"403":{"description":"The key lacks the scope this route needs (SCOPE_MISSING, details.needed / details.held), or the request came from outside the key's address allowlist (IP_NOT_ALLOWED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":403,"message":"This API key does not have the bookings:write scope. The property owner grants scopes when creating or editing a key.","data":{"code":"SCOPE_MISSING","details":{"needed":"bookings:write","held":["ari:read","ari:write"]}}}}}},"404":{"description":"No such batch on this property","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":404,"message":"Batch not found.","data":{"code":"BATCH_NOT_FOUND"}}}}},"409":{"description":"The property is deleted or demo (PROPERTY_UNAVAILABLE); on an ARI route its channel manager is off (CHANNEL_MANAGER_DISABLED); on a booking route it has no PMS (PMS_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":409,"message":"This property's channel manager is switched off, so writes would not reach any channel. Contact the property owner.","data":{"code":"CHANNEL_MANAGER_DISABLED"}}}}},"429":{"description":"A budget was exhausted — data.scope names it (ip · ip-auth · requests · writes · property · property-writes · cells · global); honour Retry-After and pace on the RateLimit header (x-zimmerstack.rateLimits)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"statuscode":429,"message":"Too many requests on this API key. Slow down and retry after the Retry-After interval.","data":{"code":"RATE_LIMITED","scope":"writes","retryAfterSeconds":17}}}}}}}}},"components":{"securitySchemes":{"connectApiKey":{"type":"http","scheme":"bearer","bearerFormat":"zsk_live_…"}},"schemas":{"Error":{"type":"object","properties":{"statuscode":{"type":"integer"},"message":{"type":"string","description":"Human-readable, may change; branch on data.code"},"data":{"type":"object","properties":{"code":{"type":"string","enum":["API_KEY_INVALID","API_KEY_REVOKED","CONNECT_API_NOT_CONFIGURED","IP_NOT_ALLOWED","SCOPE_MISSING","PROPERTY_UNAVAILABLE","CHANNEL_MANAGER_DISABLED","PMS_NOT_AVAILABLE","VALIDATION","RANGE_INVALID","HORIZON","TOO_MANY_UPDATES","TOO_MANY_CELLS","UNKNOWN_ROOM_TYPE","UNKNOWN_RATE_PLAN","CURRENCY_MISMATCH","RATE_LIMITED","NOTHING_ACCEPTED","BATCH_NOT_FOUND","IDEMPOTENCY_KEY_INVALID","IDEMPOTENCY_KEY_REUSED","IDEMPOTENCY_IN_FLIGHT","STAY_INVALID","UNKNOWN_ROOM_TYPE_FOR_PLAN","OCCUPANCY_EXCEEDED","NO_AVAILABILITY","EXTERNAL_REFERENCE_REUSED","PAYMENT_NOT_ALLOWED","PAYMENT_EXCEEDS_TOTAL","BOOKING_NOT_FOUND","BOOKING_NOT_CANCELLABLE","MODULE_NOT_ENTITLED"]},"details":{}},"required":["code"],"additionalProperties":false}},"required":["statuscode","message","data"],"additionalProperties":false},"Property":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"timezone":{"type":"string","description":"IANA; every date in this API is a calendar date in this zone"},"currency":{"type":"string","description":"ISO 4217; every rate must be sent in it"},"inventoryScope":{"type":"string","enum":["PMS_CM","CM_ONLY","PMS_CUTOVER","OWNER_SITE"]},"horizonDays":{"type":"integer","description":"last writable night = today + horizonDays"},"ariAuthoritative":{"type":"boolean"},"scopes":{"type":"array","items":{"type":"string"},"description":"what THIS key may do: ari:read · ari:write · bookings:read · bookings:write · bookings:payments"},"products":{"type":"object","properties":{"channelManager":{"type":"boolean","description":"the ARI routes need it"},"pms":{"type":"boolean","description":"the booking routes need it"}},"required":["channelManager","pms"],"additionalProperties":false},"limits":{"type":"object","properties":{"requestsPerMinute":{"type":"integer"},"writesPerMinute":{"type":"integer"},"maxUpdatesPerRequest":{"type":"integer"},"maxCellsPerRequest":{"type":"integer"},"bookingsPerMinute":{"type":"integer"}},"required":["requestsPerMinute","writesPerMinute","maxUpdatesPerRequest","maxCellsPerRequest","bookingsPerMinute"],"additionalProperties":false},"sync":{"type":"object","properties":{"state":{"type":"string","enum":["IN_SYNC","PENDING","OUT_OF_SYNC","DISABLED"]},"pendingCells":{"type":"integer"}},"required":["state","pendingCells"],"additionalProperties":false}},"required":["id","name","timezone","currency","inventoryScope","horizonDays","ariAuthoritative","scopes","products","limits","sync"],"additionalProperties":false},"Catalog":{"type":"object","properties":{"currency":{"type":"string"},"roomTypes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"maxAdults":{"anyOf":[{"type":"integer"},{"type":"null"}]},"maxChildren":{"anyOf":[{"type":"integer"},{"type":"null"}]},"roomKind":{"type":"string"}},"required":["id","name","maxAdults","maxChildren","roomKind"],"additionalProperties":false}},"ratePlans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"roomTypeId":{"type":"integer"},"name":{"type":"string"},"mealPlan":{"anyOf":[{"type":"string","enum":["EP","CP","MAP","AP"]},{"type":"null"}]},"occupancy":{"anyOf":[{"type":"integer"},{"type":"null"}]},"currency":{"type":"string"},"refundable":{"type":"boolean"}},"required":["id","roomTypeId","name","mealPlan","occupancy","currency","refundable"],"additionalProperties":false}}},"required":["currency","roomTypes","ratePlans"],"additionalProperties":false},"RangeQuery":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"default: today in the property's timezone"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"default: from + 30 days; at most 500 days after from"}},"additionalProperties":false},"AvailabilityRead":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"cells":{"type":"array","items":{"type":"object","properties":{"roomTypeId":{"type":"integer"},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"available":{"type":"integer"}},"required":["roomTypeId","date","available"],"additionalProperties":false}}},"required":["from","to","cells"],"additionalProperties":false},"AvailabilityWrite":{"type":"object","properties":{"updates":{"type":"array","items":{"type":"object","properties":{"roomTypeId":{"type":"integer","exclusiveMinimum":0,"description":"ZimmerStack room type id (GET /catalog)"},"dateFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"dateTo":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"available":{"type":"integer","minimum":0,"maximum":10000,"description":"ABSOLUTE count of rooms of this type for sale on each night of the range"}},"required":["roomTypeId","dateFrom","dateTo","available"],"additionalProperties":false},"minItems":1}},"required":["updates"],"additionalProperties":false},"RatesRead":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"currency":{"type":"string"},"cells":{"type":"array","items":{"type":"object","properties":{"ratePlanId":{"type":"integer"},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"rateMinor":{"type":"integer","description":"MINOR units (paise, cents)"},"source":{"type":"string","enum":["MANUAL","BASE","ENGINE","CHANNEX_SEED","PLAN_DEFAULT","STANDING"]}},"required":["ratePlanId","date","rateMinor","source"],"additionalProperties":false}}},"required":["from","to","currency","cells"],"additionalProperties":false},"RatesWrite":{"type":"object","properties":{"updates":{"type":"array","items":{"type":"object","properties":{"ratePlanId":{"type":"integer","exclusiveMinimum":0,"description":"ZimmerStack rate plan id (GET /catalog)"},"dateFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"dateTo":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"days":{"type":"array","items":{"type":"string","enum":["mo","tu","we","th","fr","sa","su"],"description":"mo tu we th fr sa su"},"maxItems":7},"rate":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^\\d+(\\.\\d{1,2})?$"}],"description":"Nightly sell price in MAJOR units (e.g. 4500 or \"4500.00\"); rounded to a whole major unit"},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"ISO 4217; must equal the property's currency (GET /property)"}},"required":["ratePlanId","dateFrom","dateTo","rate","currency"],"additionalProperties":false},"minItems":1}},"required":["updates"],"additionalProperties":false},"RestrictionsRead":{"type":"object","properties":{"from":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"to":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"cells":{"type":"array","items":{"type":"object","properties":{"ratePlanId":{"type":"integer"},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"stopSell":{"type":["boolean","null"]},"closedToArrival":{"type":["boolean","null"]},"closedToDeparture":{"type":["boolean","null"]},"minStayArrival":{"anyOf":[{"type":"integer"},{"type":"null"}]},"minStayThrough":{"anyOf":[{"type":"integer"},{"type":"null"}]},"maxStay":{"anyOf":[{"type":"integer"},{"type":"null"}]}},"required":["ratePlanId","date","stopSell","closedToArrival","closedToDeparture","minStayArrival","minStayThrough","maxStay"],"additionalProperties":false}}},"required":["from","to","cells"],"additionalProperties":false},"RestrictionsWrite":{"type":"object","properties":{"updates":{"type":"array","items":{"type":"object","properties":{"ratePlanId":{"type":"integer","exclusiveMinimum":0,"description":"ZimmerStack rate plan id (GET /catalog)"},"dateFrom":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"dateTo":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"days":{"type":"array","items":{"type":"string","enum":["mo","tu","we","th","fr","sa","su"],"description":"mo tu we th fr sa su"},"maxItems":7},"stopSell":{"type":"boolean"},"closedToArrival":{"type":"boolean"},"closedToDeparture":{"type":"boolean"},"minStayArrival":{"type":"integer","minimum":1,"maximum":365},"minStayThrough":{"type":"integer","minimum":1,"maximum":365},"maxStay":{"type":"integer","minimum":0,"maximum":365}},"required":["ratePlanId","dateFrom","dateTo"],"additionalProperties":false},"minItems":1}},"required":["updates"],"additionalProperties":false},"WriteAccepted":{"type":"object","properties":{"batchId":{"type":"string","format":"uuid"},"resource":{"type":"string","enum":["availability","rates","restrictions"]},"requestedCells":{"type":"integer","description":"distinct cells after per-request coalescing (last write wins)"},"acceptedCells":{"type":"integer","description":"cells that differed from our record and were written; they will be pushed"},"noopCells":{"type":"integer","description":"cells that already held the requested value; nothing written, nothing pushed"},"rejected":{"type":"array","items":{"type":"object","properties":{"cells":{"type":"integer"},"error":{"type":"string"}},"required":["cells","error"],"additionalProperties":false},"description":"groups our record refused (e.g. a plan whose policy forbids exceptions)"},"pushedBy":{"type":"string","enum":["inventory-drain","ari-projector"]},"poll":{"type":"string","description":"GET path to watch this batch land"}},"required":["batchId","resource","requestedCells","acceptedCells","noopCells","rejected","pushedBy","poll"],"additionalProperties":false},"BatchStatus":{"type":"object","properties":{"batchId":{"type":"string","format":"uuid"},"resource":{"type":"string","enum":["availability","rates","restrictions"]},"createdAt":{"type":"string"},"requestedCells":{"type":"integer"},"acceptedCells":{"type":"integer"},"noopCells":{"type":"integer"},"rejected":{"type":"array","items":{"type":"object","properties":{"cells":{"type":"integer"},"error":{"type":"string"}},"required":["cells","error"],"additionalProperties":false}},"status":{"type":"string","enum":["landed","pending","failed"]},"pendingCells":{"type":"integer"},"lastError":{"type":["string","null"]}},"required":["batchId","resource","createdAt","requestedCells","acceptedCells","noopCells","rejected","status","pendingCells","lastError"],"additionalProperties":false},"SyncStatus":{"type":"object","properties":{"propertyId":{"type":"integer"},"ariAuthoritative":{"type":"boolean","description":"false = nothing is pushed; ask ZimmerStack support"},"inventory":{"type":"object","properties":{"state":{"type":"string","enum":["IN_SYNC","PENDING","OUT_OF_SYNC","DISABLED"]},"pendingCells":{"type":"integer"},"lastOkAt":{"type":["string","null"]},"lastError":{"type":["string","null"]},"outOfSyncSince":{"type":["string","null"]}},"required":["state","pendingCells","lastOkAt","lastError","outOfSyncSince"],"additionalProperties":false},"rates":{"type":"object","properties":{"dirtyCells":{"type":"integer","description":"rate/restriction cells waiting for the projector"},"lastPushAt":{"type":["string","null"]},"lastErrorAt":{"type":["string","null"]},"lastError":{"type":["string","null"]}},"required":["dirtyCells","lastPushAt","lastErrorAt","lastError"],"additionalProperties":false},"newestPendingBatch":{"anyOf":[{"type":"object","properties":{"batchId":{"type":"string","format":"uuid"},"resource":{"type":"string","enum":["availability","rates","restrictions"]},"createdAt":{"type":"string"},"requestedCells":{"type":"integer"},"acceptedCells":{"type":"integer"},"noopCells":{"type":"integer"},"rejected":{"type":"array","items":{"type":"object","properties":{"cells":{"type":"integer"},"error":{"type":"string"}},"required":["cells","error"],"additionalProperties":false}},"status":{"type":"string","enum":["landed","pending","failed"]},"pendingCells":{"type":"integer"},"lastError":{"type":["string","null"]}},"required":["batchId","resource","createdAt","requestedCells","acceptedCells","noopCells","rejected","status","pendingCells","lastError"],"additionalProperties":false},{"type":"null"}]}},"required":["propertyId","ariAuthoritative","inventory","rates","newestPendingBatch"],"additionalProperties":false},"BookingCreate":{"type":"object","properties":{"externalReference":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$","description":"Your own reservation id; unique per property; a retried POST with the same value returns the same booking"},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Exclusive: the checkout day is not a night"},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"ISO 4217; must equal the property's (GET /property)"},"guest":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":120,"description":"Full name as the guest typed it"},"phone":{"allOf":[{"type":"string"},{"type":"string","pattern":"^\\+?\\d{7,15}$"}],"description":"Guest phone, digits with an optional leading +"},"email":{"type":"string","format":"email","maxLength":254},"notes":{"type":"string","maxLength":2000}},"required":["name","phone"],"additionalProperties":false},"rooms":{"type":"array","items":{"type":"object","properties":{"roomTypeId":{"type":"integer","exclusiveMinimum":0,"description":"ZimmerStack room type id (GET /catalog)"},"ratePlanId":{"type":"integer","exclusiveMinimum":0},"adults":{"type":"integer","minimum":1,"maximum":20},"children":{"type":"integer","minimum":0,"maximum":10},"nightlyRate":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^\\d+(\\.\\d{1,2})?$"}],"description":"Nightly sell price in MAJOR units (e.g. 4500 or \"4500.00\"); rounded to a whole major unit"}},"required":["roomTypeId","adults","nightlyRate"],"additionalProperties":false},"minItems":1,"maxItems":20},"payment":{"type":"object","properties":{"amount":{"anyOf":[{"type":"number","minimum":0},{"type":"string","pattern":"^\\d+(\\.\\d{1,2})?$"}],"description":"Nightly sell price in MAJOR units (e.g. 4500 or \"4500.00\"); rounded to a whole major unit"},"method":{"type":"string","enum":["ONLINE","CARD","UPI","NETBANKING","CASH"],"description":"How you collected it"},"reference":{"type":"string","maxLength":120}},"required":["amount","method"],"additionalProperties":false},"notes":{"type":"string","maxLength":2000}},"required":["externalReference","checkIn","checkOut","currency","guest","rooms"],"additionalProperties":false},"BookingCancel":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}},"additionalProperties":false},"BookingsQuery":{"type":"object","properties":{"since":{"type":"string","format":"date-time"},"externalReference":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9][A-Za-z0-9._:-]*$","description":"Your own reservation id; unique per property; a retried POST with the same value returns the same booking"},"limit":{"type":"integer","minimum":1,"maximum":100}},"additionalProperties":false},"Booking":{"type":"object","properties":{"bookingId":{"type":"integer"},"reference":{"type":"string"},"externalReference":{"type":["string","null"]},"status":{"type":"string","enum":["UPCOMING","INHOUSE","COMPLETED","CANCELLED","NOSHOW"]},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"nights":{"type":"integer"},"currency":{"type":"string"},"totalAmount":{"type":"string","description":"MAJOR units, two decimals: the whole stay"},"totalPaid":{"type":"string","description":"MAJOR units, two decimals: collected so far"},"balanceDue":{"type":"string","description":"MAJOR units, two decimals: owed at the hotel"},"guest":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":["string","null"]}},"required":["name","phone","email"],"additionalProperties":false},"rooms":{"type":"array","items":{"type":"object","properties":{"bookingRoomId":{"type":"integer"},"roomTypeId":{"type":"integer"},"ratePlanId":{"anyOf":[{"type":"integer"},{"type":"null"}]},"mealPlan":{"type":"string","enum":["EP","CP","MAP","AP"]},"adults":{"type":"integer"},"children":{"type":"integer"},"nightlyRate":{"type":"string","description":"MAJOR units, two decimals"},"status":{"type":"string","enum":["UPCOMING","CHECKEDIN","CHECKEDOUT","CANCELLED","NOSHOW"]}},"required":["bookingRoomId","roomTypeId","ratePlanId","mealPlan","adults","children","nightlyRate","status"],"additionalProperties":false}},"inventory":{"type":"object","properties":{"eventRecorded":{"type":"boolean"},"channelManager":{"type":"boolean","description":"false = this property has no channel manager; nothing is pushed"},"pushedBy":{"type":"string","const":"inventory-drain"}},"required":["eventRecorded","channelManager","pushedBy"],"additionalProperties":false},"replay":{"type":"boolean"},"createdAt":{"type":"string"},"cancelledAt":{"type":["string","null"]}},"required":["bookingId","reference","externalReference","status","checkIn","checkOut","nights","currency","totalAmount","totalPaid","balanceDue","guest","rooms","inventory","replay","createdAt","cancelledAt"],"additionalProperties":false},"BookingsList":{"type":"object","properties":{"since":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"bookingId":{"type":"integer"},"reference":{"type":"string"},"externalReference":{"type":["string","null"]},"status":{"type":"string","enum":["UPCOMING","INHOUSE","COMPLETED","CANCELLED","NOSHOW"]},"checkIn":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"checkOut":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Hotel-local calendar date, YYYY-MM-DD"},"nights":{"type":"integer"},"currency":{"type":"string"},"totalAmount":{"type":"string","description":"MAJOR units, two decimals: the whole stay"},"totalPaid":{"type":"string","description":"MAJOR units, two decimals: collected so far"},"balanceDue":{"type":"string","description":"MAJOR units, two decimals: owed at the hotel"},"guest":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":["string","null"]}},"required":["name","phone","email"],"additionalProperties":false},"rooms":{"type":"array","items":{"type":"object","properties":{"bookingRoomId":{"type":"integer"},"roomTypeId":{"type":"integer"},"ratePlanId":{"anyOf":[{"type":"integer"},{"type":"null"}]},"mealPlan":{"type":"string","enum":["EP","CP","MAP","AP"]},"adults":{"type":"integer"},"children":{"type":"integer"},"nightlyRate":{"type":"string","description":"MAJOR units, two decimals"},"status":{"type":"string","enum":["UPCOMING","CHECKEDIN","CHECKEDOUT","CANCELLED","NOSHOW"]}},"required":["bookingRoomId","roomTypeId","ratePlanId","mealPlan","adults","children","nightlyRate","status"],"additionalProperties":false}},"inventory":{"type":"object","properties":{"eventRecorded":{"type":"boolean"},"channelManager":{"type":"boolean","description":"false = this property has no channel manager; nothing is pushed"},"pushedBy":{"type":"string","const":"inventory-drain"}},"required":["eventRecorded","channelManager","pushedBy"],"additionalProperties":false},"replay":{"type":"boolean"},"createdAt":{"type":"string"},"cancelledAt":{"type":["string","null"]}},"required":["bookingId","reference","externalReference","status","checkIn","checkOut","nights","currency","totalAmount","totalPaid","balanceDue","guest","rooms","inventory","replay","createdAt","cancelledAt"],"additionalProperties":false}}},"required":["since","items"],"additionalProperties":false}}}}