Skip to content

Start

Quickstart

A key from the owner, one request, and the answer that tells you it landed. Ten minutes.

  1. 1

    Get a key from the property owner

    The owner creates it in Admin → Developers → API keys (or Channels → Integrations) and picks its scopes: the channel-manager pair for a PMS, the booking pair for a booking engine. Ask them to add your servers' public addresses to the key's allowlist. The key is shown once; it starts with zsk_live_.
  2. 2

    Ask who you are

    GET /property works for every key and echoes its scopes and the products the property runs. GET /catalog gives the numeric room-type and rate-plan ids every write uses. Never guess an id.
  3. 3

    Send one write

    A PMS pushes an availability range (PUT /availability) and polls GET /sync. A booking engine posts one booking (POST /bookings) and gets 201 with the PMS reference.

Who am I?

curl
curl "https://api.zimmerstack.com/api/v1/connect-api/v1/property" \
  -H "Authorization: Bearer $ZIMMERSTACK_CONNECT_KEY"
# → 200 { "id": 61, "name": "…", "timezone": "Asia/Kolkata", "currency": "INR",
#         "scopes": ["bookings:read", "bookings:write"], "products": { "channelManager": true, "pms": true }, … }

A booking engine: post one booking

One entry in rooms per room. You price the stay; send the nightly rate you charged. externalReference is your reservation id and makes retries safe: the same value again returns the same booking with 200.

curl
curl -X POST "https://api.zimmerstack.com/api/v1/connect-api/v1/bookings" \
  -H "Authorization: Bearer $ZIMMERSTACK_CONNECT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"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"}'
# → 201 { "bookingId": 48213, "reference": "SB-7KQ2MX9D", "status": "UPCOMING",
#         "inventory": { "eventRecorded": true, "channelManager": true, "pushedBy": "inventory-drain" }, … }
Request body, pretty
{
  "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"
}

A PMS: push an availability range

curl
curl -X PUT "https://api.zimmerstack.com/api/v1/connect-api/v1/availability" \
  -H "Authorization: Bearer $ZIMMERSTACK_CONNECT_KEY" \
  -H "Content-Type: application/json" \
  -H "x-idempotency-key: $(uuidgen | tr -d -)" \
  -d '{"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}]}'
# → 202 { "batchId": "…", "acceptedCells": 30, "noopCells": 0, "poll": "…/batches/…" }

curl "https://api.zimmerstack.com/api/v1/connect-api/v1/sync" -H "Authorization: Bearer $ZIMMERSTACK_CONNECT_KEY"
# → { "inventory": { "state": "IN_SYNC", … }, "rates": { "dirtyCells": 0, … } }

Node, no SDK

node 18+
const BASE = "https://api.zimmerstack.com/api/v1/connect-api/v1";
const KEY = process.env.ZIMMERSTACK_CONNECT_KEY;

async function call(method, path, body) {
  const res = await fetch(BASE + path, {
    method,
    headers: { authorization: `Bearer ${KEY}`, "content-type": "application/json" },
    body: body === undefined ? undefined : JSON.stringify(body),
  });
  if (res.status === 429) {
    const wait = Number(res.headers.get("retry-after") ?? "5");
    await new Promise((r) => setTimeout(r, wait * 1000));
    return call(method, path, body); // the same request, after Retry-After
  }
  const json = await res.json();
  if (!res.ok) throw new Error(`${res.status} ${json.data?.code}: ${json.message}`);
  return json.data;
}

const property = await call("GET", "/property");
const booking = await call("POST", "/bookings", {/* see the Bookings page */});

Facts on this page (routes, samples, limits, codes) come from the API's public contract read live, Tue, 20 Oct 2026 13:10:40 GMT.