Skip to content

Reference

Sandbox

The same API, a test key, a property no channel ever sees. Push, read, and have us send you the OTA booking webhooks on demand.

What it is

The property owner creates a sandbox from a real property in Admin → Developers → API keys (or Channels → Integrations). It is a copy of that property's room types and rate plans on a new property that is never connected to a channel manager or an OTA. Keys minted on it start with zsk_test_ and work only there; a live key never reaches it. Nothing you do on the sandbox is billed, pushed to a channel, or visible to a guest.

Key
zsk_test_…, the same shape and the same scopes as a live key, minted by the owner on the sandbox.
Property
A copy of the owner's real property: the same room types, rate plans, units and rates; GET /catalog gives you its ids.
Pushes
Every route behaves as in production. A push lands in our record and stops: GET /sync reports IN_SYNC and GET /batches/{batchId} reports landed within a minute, through the same code path as a live property. GET /property says sandbox: true.
Bookings
POST /sandbox/bookings simulates an OTA booking end to end — the booking, the sandbox's availability moved down, the inventory event, and the REAL channel.booking.created webhook to every endpoint registered on the sandbox. POST /sandbox/bookings/{bookingId}/cancel does the same for a cancellation. A live key gets 403 SANDBOX_ONLY.
Limits
The same budgets as production (one sandbox per owner, at most five keys). Nothing you do there is billed or pushed to a channel.
Going live
Ask the owner for a zsk_live_ key on the real property, swap the key, keep the code.

How to test an integration

  1. 1

    Ask the owner for a sandbox and a test key

    They press Create sandbox on the API keys screen, then Create key on the sandbox with the channel-manager scopes. The key is shown once and starts with zsk_test_.
  2. 2

    Register your webhook endpoint on the sandbox

    The owner adds your URL under the sandbox's webhooks and gives you its signing secret. Every simulated booking reaches it as the production payload, signed the same way, with mode: "live".
  3. 3

    Push and read as in production

    GET /property answers sandbox: true. A PUT lands in our record; GET /sync reports IN_SYNC and GET /batches/{batchId} reports landed within a minute.
  4. 4

    Have us send you an OTA booking

    POST /sandbox/bookings creates a channel booking on the sandbox: the booking, its nights taken from the room type's availability, and the real channel.booking.created webhook. Cancel it with POST /sandbox/bookings/{bookingId}/cancel and receive channel.booking.cancelled.
  5. 5

    Go live

    Ask the owner for a zsk_live_ key on the real property, swap the key, keep the code.

The sandbox routes

Three routes exist only on a test key; a live key answers 403 SANDBOX_ONLY. Everything else on this site works on the sandbox unchanged.

Base URL https://api.zimmerstack.com/api/v1/connect-api/v1

A simulated booking

shell
curl -X POST https://api.zimmerstack.com/api/v1/connect-api/v1/sandbox/bookings \
  -H "Authorization: Bearer zsk_test_…" \
  -H "Content-Type: application/json" \
  -d '{"roomTypeId":412,"checkIn":"2026-12-05","nights":2,"rooms":1,"adults":2,"guestName":"Asha Verma","otaName":"Booking.com","paidByOta":false}'

The answer, and what your webhook endpoint receives seconds later:

JSON
{
  "bookingId": 90311,
  "reference": "SBX-9001-MH3K2Q7A",
  "channelBookingId": "sbx-1f6d0c2e-7b53-4a0e-9c5a-2d8f3b1e4c70",
  "otaName": "Booking.com",
  "status": "UPCOMING",
  "guestName": "Asha Verma",
  "checkIn": "2026-12-05",
  "checkOut": "2026-12-07",
  "nights": 2,
  "rooms": 1,
  "roomTypeId": 412,
  "nightlyRate": 4500,
  "total": 9000,
  "currency": "INR",
  "paidByOta": false,
  "oversold": false,
  "createdAt": "2026-10-30T12:00:00.000Z",
  "webhook": {
    "eventType": "channel.booking.created",
    "queued": true
  }
}

Routes, samples, limits and codes on this page come from the API's public contract, read live, Sat, 31 Oct 2026 04:48:12 UTC.