Reservations
A reservation is one guest stay at a property. This guide covers the reservation operations most integrations need. Every field and filter is listed on the operation’s page in the API Reference.
| Operation | Request | Permission |
|---|---|---|
listReservations | GET /reservations | view_reservations |
getReservation | GET /reservations/{id} | view_reservations |
createReservation | POST /reservations | modify_reservations |
updateReservation | PATCH /reservations/{id} | modify_reservations |
updateCheckInState | POST /reservations/{id}/check-in-state | modify_reservations |
Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions.
Listing reservations
Section titled “Listing reservations”GET /reservations is paginated (default limit 20, maximum 100). Rows are ordered by the resolved check-in, ascending, which can differ from the checkIn returned.
curl "https://api-us.suiteop.com/api/v1/reservations?statuses=confirmed&dateFrom=2026-07-05T00:00:00.000Z&dateTo=2026-07-11T00:00:00.000Z&dateType=check_in" \ -H "Authorization: Bearer sk_live_your_key_here"const params = new URLSearchParams({ dateFrom: '2026-07-05T00:00:00.000Z', dateTo: '2026-07-11T00:00:00.000Z', dateType: 'check_in',})params.append('statuses', 'confirmed')params.append('statuses', 'reserved')
const res = await fetch(`https://api-us.suiteop.com/api/v1/reservations?${params}`, { headers: { Authorization: `Bearer ${process.env.SUITEOP_API_KEY}` },})const { data, meta } = await res.json()console.log(`${data.length} of ${meta.pagination.total} stays`)Useful filters:
| Filter | Notes |
|---|---|
statuses | Booking status, e.g. confirmed or canceled. Omit it and cancelled and declined stays are included |
checkInStates | not_checked_in, checked_in, checked_out |
dateFrom, dateTo | ISO 8601 instants, e.g. 2026-07-05T00:00:00.000Z. Only the UTC date is used, as a calendar day at the property, so an offset counts after conversion: 2026-07-05T00:00:00+02:00 is July 4. Both ends are inclusive |
dateType | Which date the window applies to: check_in (default), check_out, booked_date, or stay_date (any overlap). check_in/check_out use the actual time once checkInState confirms it, else the override, else the scheduled time. Ignored without a window |
propertyIds, propertyGroupIds | Repeat the key for several values |
bookingSourceIds, integrationAccountId | Narrow by booking source or by connected PMS account |
codeStatuses | Door-code provisioning state, e.g. active, pending, failed |
verificationStatuses | Guest verification: verified, review, pending, decline, unknown |
search | Case- and accent-insensitive match on guest name, guest email, confirmation code and PMS reservation ID |
Each row carries fields such as id, guestFirstName, guestLastName, checkIn, checkOut, nightCount, confirmationCode, status, checkInState, codeStatus, totalPriceCents, propertyId, propertyName and verificationStatus. GET /reservations/{id} returns the whole stay, including the price breakdown (subtotalCents, totalFeeCents, totalTaxCents, totalDiscountCents), currency and the actual checkedInAt / checkedOutAt times. Amounts are integers in the currency’s minor unit (cents). It also returns:
isReturningGuest:truewhen the storedisReturningflag from the PMS is set, or when the same guest (matched byguestIdonly, never by email or name) has another booking in your organization with an earlier check-in whose status isn’tcanceled,declined,expired,inquiryorblocked.isReturningalone is only the PMS’s flag.pmsUnderlyingProvider: the PMS the customer actually connected. It equalspmsProviderfor a direct integration; for a reservation synced through an aggregator such as Calry it is the upstream product (for examplehostifyorownerrez). When the upstream product isn’t known it falls back topmsProvider, so it can still readcalry. It isnullfor a reservation with no PMS, and it is only computed here: list rows and create or update responses may leave the key out. Keep filtering onpmsProvider, which is unchanged.
checkIn and checkOut are the stored values, so a stay your PMS sent as a bare date reads as midnight UTC. To show or compare stay times, both the list and getReservation (not the create or update response) add two computed pairs:
displayCheckInAt/displayCheckOutAt: the instant to show. The recorded arrival or departure oncecheckInStateconfirms it, else the override set on the stay, else the scheduled time. A date-only scheduled time is placed at the property’s default check-in or check-out hour in its time zone.scheduledCheckInAt/scheduledCheckOutAt: what the stay was booked for, placed the same way, ignoring overrides and recorded times. Compare it with the display pair to tell whether a boundary moved off schedule.
Creating a reservation
Section titled “Creating a reservation”Only for stays booked outside your PMS. Reservations owned by a connected PMS reach SuiteOp through that integration’s own sync.
propertyId, checkIn and checkOut are required:
curl -X POST https://api-us.suiteop.com/api/v1/reservations \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Idempotency-Key: 8f14e45f-ceea-467f-a0e6-7d1b2c3a4b5c" \ -H "Content-Type: application/json" \ -d '{ "propertyId": "9a3d7e40-…", "checkIn": "2026-07-05", "checkOut": "2026-07-08", "guestFirstName": "Ana", "guestLastName": "García", "guestEmail": "ana@example.com", "guestPhone": "+34 612 345 678", "guestCount": 2 }'The response is 201 with the created reservation in data, including its id, nightCount and confirmationCode.
Field notes:
- Dates: a bare day such as
2026-07-05is placed at the property’s own check-in (or check-out) hour in its timezone. A full instant such as2026-07-05T15:00:00Zis stored exactly as given. statusdefaults toconfirmed. Onlyconfirmed,reservedandawaiting_paymentopen guest verification and schedule the property to flip to occupied at check-in and dirty at check-out.inquiry,blockedand the terminal statuses record the stay without either.guestPhoneis normalized to E.164. A number without a country code is read as a US number, so send international numbers in full.confirmationCodeis stored as given. Omit it and SuiteOp generates one shaped likeSO-AB1C2D3E4F. It is not checked for uniqueness.- Also accepted:
externalReservationId,bookingSourceId,sourceText,pmsProviderandsubtotalCents.
Updating a reservation
Section titled “Updating a reservation”PATCH /reservations/{id} takes the fields to change inside a data object: dates, guest details, guestCount, confirmationCode, externalReservationId, etaCheckIn, etaCheckOut, propertyId, sourceText and subtotalCents.
curl -X PATCH https://api-us.suiteop.com/api/v1/reservations/4e2a… \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"data": {"checkOut": "2026-07-09", "guestCount": 3}}'guestCount: null clears the party size; leaving guestCount out keeps it.
Changing a date recounts the nights and re-times any door codes already provisioned for the stay — unless the same call also changes propertyId, which skips the re-time. The booking status and the checkInState can’t be set here.
Checking guests in and out
Section titled “Checking guests in and out”POST /reservations/{id}/check-in-state records an arrival or departure. checkInState and occupancyMethod are both required:
curl -X POST https://api-us.suiteop.com/api/v1/reservations/4e2a…/check-in-state \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"checkInState": "checked_in", "occupancyMethod": "dashboard"}'- The flow runs one way:
not_checked_in→checked_in→checked_out, or straight fromnot_checked_intochecked_out. Any other move, including repeating the current state, is rejected. - Checking in marks the property occupied. Checking out marks it dirty and resets its inspection, unless another guest is still checked in there. A failed inspection is never overwritten.
- Checking in a stay that isn’t confirmed yet, such as an
inquiry, is rejected with400when its dates overlap another active or checked-in stay at the same property, since checking in would double-book those nights. Stays synced from a PMS are never refused. occupancyMethodrecords how the change happened:dashboard,guest_portal,smart_lock,remote_controlorworkflow_action. It doesn’t trigger anything.- If the stay requires a check-in review, check-in is rejected until you send
acknowledgeCheckInReview: true.