Migrating from PMS v1 to Quendoo Connect
You are integrated with Quendoo through the legacy
apc-integrator.php — the URL is api.quendoo.com/api/pms/v1/*,
authentication is by api_key query param, and every response is
wrapped in the shape {data|message} documented on the PMS v1
facade page. This page is the map from
that world to the modern QC surface at /v1/qc/*.
You do not have to migrate today. Every PMS v1 method is either running through the facade in shadow (byte-parity) or still routed to legacy verbatim. Your integration keeps working. This page is for partners who want to actively pick up the parts QC does better — better auth, better idempotency, better scoping, better error shapes, first-class configuration surfaces.
What actually changes
| PMS v1 | Quendoo Connect | |
|---|---|---|
| Base URL | api.quendoo.com/api/pms/v1/* |
api.quendoo.com/v1/qc/* |
| Auth | ?api_key=… (query string) |
OAuth 2.0 client credentials → Authorization: Bearer <jwt> |
| Response shape | {data, message} or the legacy per-method blob |
Uniform `{status: "ok" |
| Errors | English sentence per method (byte-strict) | Stable machine keys (errors.qc.*) with HTTP status |
| Idempotency | none | Idempotency-Key header, 24 h window |
| Property scoping | implicit — one api_key = one property | explicit — every URL carries {external_property_id} |
| Rate limits | none surfaced | per-client per-bucket, X-RateLimit-* headers |
| Webhooks | none | first-class signed webhooks + subscriptions |
| Docs versioning | none — endpoint bytes = docs | /v1/qc/openapi.yaml machine-readable, changelog by date |
Endpoint map
Everything you can do today has a QC equivalent. Some are direct 1-for-1s; some replace one PMS v1 call with a small set of narrower QC endpoints (usually a good trade — you push what you actually changed, not the whole world).
Availability & inventory
| PMS v1 | QC | Notes |
|---|---|---|
Availability/updateAvailability |
POST /v1/qc/properties/{ext}/inventory/availability |
Same "sellable capacity" semantics; body is JSON per date not the values[] batch. Pair with the restrictions + rates endpoints if you also push those. |
Availability/getAvailability |
GET /v1/qc/properties/{ext}/availability?from=&to= |
Same rooms → dates → free-capacity int shape. |
Bookings
| PMS v1 | QC | Notes |
|---|---|---|
Booking/getBookings |
GET /v1/qc/properties/{ext}/bookings?revisions=1 |
Modern revisions feed; poll or subscribe to booking.* webhooks as an accelerator. |
Booking/ackBooking |
POST /v1/qc/bookings/{id}/ack |
Same revision-matching, better error surface. |
Booking/postRoomAssignment |
POST /v1/qc/bookings/{id}/room-assignment |
Room number + self-check-in code, same annotations. |
Property & catalogue
| PMS v1 | QC | Notes |
|---|---|---|
Property/postExternalPropertyData |
Split — PATCH /v1/qc/properties/{ext} with partner_code / partner_name for the property; per-resource partner_code on POST /room_types, POST /rate_plans, POST /extra_services; and a group-level POST /catalogue-sync job for full replacements. |
The single "give me everything" snapshot becomes per-entity CRUD; you can now push a single renamed room without re-uploading the whole catalogue. Bed layout note: legacy postExternalPropertyData carried the room's bed-type mapping too. QC does not expose a bed-layout write endpoint, BUT per_person / per_occupancy rate plans no longer need a dashboard step — POST /rate_plans accepts sell_type and auto-derives the occupancy vocabulary from each room's existing bed capacity. See per-person pairs are set at rate-plan create time. Custom per-room bed layouts remain a dashboard-only concern. |
Property/getRoomsDetails |
GET /v1/qc/properties/{ext}/room_types + .../room_types/{id} |
Same fields, richer per-room shape (occupancy bounds, partner code roundtrip). |
Property/getPropertySettings |
Split across the resource endpoints — /rooms, /rate_plans, /extra_services, /meal_plans, /bed_types, /booking_buttons, /payment_methods. |
You get to cache per-resource with the Last-Modified / ETag semantics QC does support. |
Property/getBookingOffers |
No direct QC replacement yet — same-shape method on the facade. | Live cut-over per api_user via qc_v1_cutover; live once the shadow score is 0. |
Concrete migration — start with these three moves
- Get an OAuth client. Ask us via the support portal — we mint
client_id/client_secretand grant a scope set matched to your current api_key. First call:POST /v1/qc/oauth/token→ JWT you use asAuthorization: Bearer …. Tokens last 1 h; refresh from the same call. - Read the property once.
GET /v1/qc/propertiesreturns every property you can now see. Cache theexternal_property_id(a UUID) — every subsequent call takes it in the URL. If your PMS's own id is unique per property, push it once viaPATCH /v1/qc/properties/{ext}aspartner_code; from then on you can use your id as the URL segment. See bidirectional-id contract. - Repoint one endpoint. Availability pushes are the safest
first move — same request cadence, same response contract. Add
Idempotency-Key: <uuid>to every write; the second identical call replays the first response for 24 h.
Everything else (bookings, catalogue, configuration writes) can follow at your own pace. The two APIs run in parallel indefinitely.
Things you get for free
- First-class configuration surfaces. Extras, promotions, payment policies, cancellation policies, content pages, booking buttons, gallery — every dashboard-editable surface is now CRUD. A partner PMS can onboard a hotel end-to-end. See configuration concepts.
- Signed webhooks. Lose polling for state you don't want to poll for. See webhooks.
- Stable error keys.
errors.qc.*never change meaning; log matchers keep working across a decade. See error dictionary. - Idempotent writes by design. See the SLA's idempotency window.
- An OpenAPI spec you can generate an SDK from.
/v1/qc/openapi.yaml.
Things that stay the same
- The pricing engine. The same math answers a public-widget
search, a QC search, a PMS v1
getBookingOffers, an admin quote-tool. No PMS-vs-widget drift. - The property model. Rooms, rate plans, calendars, guests, extras, promotions — all the same primitives. The URL surface changes, the domain does not.
- Legacy contracts. PMS v1 stays online with byte-parity through the facade. See the PMS v1 facade page for the cutover lifecycle.
FAQ
"Can I use PMS v1 and QC on the same property at the same time?"
Yes — they read/write the same underlying data, so a updateAvailability
push and a POST /v1/qc/.../inventory/availability push land in
one calendar. Do not race two writers on the same
(room, date) — QC has idempotency, PMS v1 does not, and the
last-write-wins rule applies.
"Will PMS v1 ever be shut off?"
Not before 2027-08-01 at the earliest, and only after every
method's shadow-diff score is zero for 90 consecutive days. You
will get a Sunset header on affected endpoints ≥ 6 months
before it happens. See the SLA's
sunset & versioning block.
"Will my api_key still work after I get an OAuth client?"
Yes — the two auth modes co-exist. You can migrate one endpoint at
a time.