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

  1. Get an OAuth client. Ask us via the support portal — we mint client_id / client_secret and grant a scope set matched to your current api_key. First call: POST /v1/qc/oauth/token → JWT you use as Authorization: Bearer …. Tokens last 1 h; refresh from the same call.
  2. Read the property once. GET /v1/qc/properties returns every property you can now see. Cache the external_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 via PATCH /v1/qc/properties/{ext} as partner_code; from then on you can use your id as the URL segment. See bidirectional-id contract.
  3. 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

Things that stay the same

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.