Skip to content

Changelog

This page tracks changes to the public /v1 API.

Live today:

  • GET /v1/ping — liveness check.
  • GET /v1/availability — resource availability by date range and party size.
  • GET /v1/resources, GET /v1/resources/{id} — resource, room-type, and rate-plan read.
  • GET/PUT /v1/resources/{id}/rates, GET/PUT /v1/resources/{id}/restrictions — rate and restriction management.
  • POST /v1/rates/bulk — set a nightly rate and/or a restriction across a date range for many resources of the same room type in one call (sk_ only).
  • GET /v1/metrics/summary — revenue and occupancy for a date range, defaulting to the current calendar month (sk_ and an operator session only — it’s money, so pk_ can never call it). Powers the dashboard’s Today screen.
  • GET /v1/resources/{id}/calendar — per-day availability, price hint, and restrictions over a date range. See Calendar and iCal feeds.
  • GET /v1/feeds/{token}.ics and the feed-token endpoints (/v1/resources/{id}/feed-tokens) — iCal export of confirmed bookings and synced external blocks. Not available yet: these answer 503 channel_unavailable. See Calendar and iCal feeds.
  • iCal import — pulling an OTA’s calendar in as external blocks. Not available yet: it does not run.
  • GET /v1/resources/{id}/slots — bookable start times of an hourly space for one local date and one duration (sk_, pk_, and operator session). See Hourly spaces and services.
  • POST /v1/quotes — priced, signed, 15-minute quotes.
  • POST /v1/holds/{id}/otp, POST /v1/holds/{id}/otp/verify — guest email verification.
  • POST /v1/holds, POST /v1/holds/{id}/confirm — hold creation and confirmation. Confirming a hold requires a succeeded card payment — see Holds and confirmation.
  • POST /v1/holds/{id}/payment-intent — creates a Stripe PaymentIntent for a held reservation, for a server-side integration using Stripe.js or Stripe Elements directly (sk_ only).
  • POST /v1/holds/{id}/checkout-session — creates a Stripe-hosted Checkout Session for a held reservation and returns a redirect URL (sk_ and pk_); this is what the embeddable widget uses to take payment.
  • Card payment (Stripe) is live: both the server-side PaymentIntent flow and the widget’s hosted-checkout flow confirm a reservation automatically once Stripe reports a succeeded payment.
  • GET /v1/bookings — a cursor-paginated list of bookings (sk_ with bookings:read, or an operator session).
  • GET/PATCH/DELETE /v1/bookings/{id} — booking read, transition, and cancellation (sk_ only).
  • POST /v1/bookings — an operator creates a booking. Send Idempotency-Key. With paidOffline: true the booking is confirmed at once. Without it, the booking is held and the response carries a Stripe checkoutUrl to send to the guest (sk_ with bookings:write, or an operator session).
  • GET/POST /v1/webhook-endpoints, DELETE /v1/webhook-endpoints/{id} — outbound webhooks. See Webhooks.
  • POST /v1/bookings/{id}/refunds — full or partial refund of a booking’s succeeded payment (sk_ with payment:refund:create, or an operator session — never pk_, the same “no money” rule as everywhere else). See Refund a booking.
  • The embeddable widget — a full booking flow: availability, quote, hold, and payment through a Stripe-hosted checkout page. See Embed the widget. A live demo runs at /widget-demo/.
  • The embeddable availability calendar — a separate, smaller, read-only widget: availability and a per-night price hint for one resource, no booking flow, pk_-authed, no PII. See Embed the calendar. A live demo runs at /calendar-demo/.
  • The dashboard’s Today screen now leads with a revenue, occupancy, and bookings-this-month summary, alongside Payments, API Keys, the widget configurator (which now generates both the booking widget’s snippet and the calendar embed’s), and Settings — all live for operators.
  • GET/POST /v1/channel-connections, DELETE /v1/channel-connections/{id} — configure a channel. POST is discriminated on channel: ical takes a feedUrl, booking_com a hotelCode, agoda a list of propertyIds. An OTA connection is created pending and activates once credentials are stored.
  • PUT /v1/channel-connections/{id}/credentials — store or rotate an OTA client id + secret. Write-only by design: the secret is encrypted at rest and the response contains only a summary (client id, key version, last updated). There is no endpoint that returns it, and there will not be one. Returns 503 if the deployment has no encryption key configured, rather than storing the secret in plaintext.
  • GET/POST /v1/channel-connections/{id}/listings, PATCH /v1/channel-connections/{id}/listings/{listingId} — map one of your resources to the channel’s own property / room-type / rate-plan ids. A resource with no mapping is invisible to that channel; nothing is ever guessed for you.
  • GET/PATCH /v1/channel/conflicts — the double-booking queue and its resolution.

All channel endpoints are sk_ or operator-session only. A publishable (pk_) key can never call them — this is inventory and credential surface.

A rental vertical layered on the same resource model — daily/weekly/monthly tiered pricing and allocating one of several interchangeable units instead of one specific room. See Rent out equipment through the API.

  • POST /v1/room-types — create a room type; vertical: "equipment" makes it a rental model. GET /v1/room-types lists your models (cursor-paginated, optional ?vertical= filter) — including ones created before you’ve added units. POST /v1/resources — add a physical unit under a room type. All sk_ or operator-session only.
  • GET/PUT /v1/rate-plans/{id}/rental-tiers — read and set the daily / weekly / monthly price tiers on a rate plan. A longer tier may never cost more per day than a shorter one (422 invalid_tiers).
  • POST /v1/quotes/rental — a priced, signed rental quote over a whole-day date range, quoted against the room type (the engine picks the cheapest whole-block cover of the duration and reports the free-unit count). Separate from the lodging POST /v1/quotes.
  • POST /v1/holds gains an optional, rental-only delivery object (address required; deliveryAt/collectionAt informational). The engine allocates a free unit at hold time; 409 no_unit_available if the fleet sold out between quote and hold.
  • The embeddable widget has a rental mode (data-mode="rental") — a date-range picker over the tiered price with an optional delivery field.
  • The operator dashboard has an Equipment inventory screen for setting all of this up without the API.

Payment is still the same one-time full charge as lodging. A refundable security/damage deposit and recurring billing for long rentals are not shipped — see the caution in the guide.

This changelog starts recording dated entries once the API reaches its first tagged release.