Properties
A property is one rental unit. Its record holds the unit’s details, door-code and guest-portal settings, and four operational status tracks: readiness, cleaning, inspection and maintenance. This guide covers the property operations most integrations need. Every field and filter is listed on the operation’s page in the API Reference.
| Operation | Request | Permission |
|---|---|---|
listProperties | GET /properties | view_properties |
getProperty | GET /properties/{id} | view_properties |
updateProperty | PATCH /properties/{id} | modify_properties |
updatePropertyStatus | POST /properties/{id}/status | modify_properties |
assignPortalToProperty | POST /properties/{propertyId}/assign-portal | modify_properties |
listPropertyTags | GET /properties/{propertyId}/tags | view_properties |
listUpsellsByProperty | GET /properties/{propertyId}/upsells | view_properties |
listPortalManualsByProperty | GET /properties/{propertyId}/portal-manuals | view_guides |
setPropertyDefaultPaymentAccount | POST /properties/{id}/default-payment-account | modify_properties and manage_payments |
Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions. Properties can’t be created or deleted through the API.
Listing properties
Section titled “Listing properties”GET /properties is paginated (default limit 50, maximum 500). Rows are ordered by the unit’s nickname, or its name where it has no nickname.
curl "https://api-us.suiteop.com/api/v1/properties?cleaningStatuses=dirty&readinessStatuses=not_ready&limit=100" \ -H "Authorization: Bearer sk_live_your_key_here"Filters combine with AND. Each status filter matches any of the values you give; repeat the key for several values.
| Filter | Notes |
|---|---|
readinessStatuses | ready, not_ready, occupied, unknown. Derived from the other three tracks plus whether a guest is checked in |
cleaningStatuses | clean, dirty, unknown. occupied is deprecated and only matches legacy rows |
inspectionStatuses | inspected, not_inspected, failed_inspection, inspection_waived |
maintenanceStatuses | normal, attention_needed, blocked. Derived from open maintenance tasks |
nameContains | Case- and accent-insensitive match on name, nickname, city or state. Matched literally: % and _ are not wildcards |
propertyGroupId | Only properties in this group. ungroupedOnly=true keeps only ungrouped ones, and is ignored when propertyGroupId is set |
excludePropertyGroupId | Drops properties already in this group, keeping ungrouped ones |
propertyIds, tagIds | Restrict to these IDs, or to properties carrying at least one of these tags (listTags) |
includeDisabled | Disabled properties are hidden by default |
archivedOnly | Returns only archived properties, those deleted in the dashboard. No single call returns archived and live properties together |
Each row carries fields such as id, name, nickname, unitNumber, city, state, countryCode, bedroomCount, bathroomCount, maxGuests, propertyGroupId, ownerId, portalSettingsId, isDisabled and the four status fields.
GET /properties/{id} returns the record, including the address, timezone, default check-in and check-out hours, wifiName, codeDisplay, the guest-portal flags and internalAccessNotes. A property outside the caller’s reach returns 404.
Secrets are write-only. wifiPassword, codeEntryKey, codeValidationKey, groupCodeEntryKey and groupCodeValidationKey can be set with updateProperty but no operation returns them.
GET /properties/{id} also does not return these writable fields: description, houseRules, checkInDescription, customAddress, addressOverride, isUnitCodeDisabled, isWifiHidden, defaultCheckInMinute and defaultCheckOutMinute. Keep your own copy if you need to read them back.
Updating a property
Section titled “Updating a property”PATCH /properties/{id} takes the fields to change inside a data object. Fields you leave out keep their current value; most nullable fields take null to clear them.
curl -X PATCH https://api-us.suiteop.com/api/v1/properties/9a3d7e40-… \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"data": {"wifiName": "Loft-Guest", "wifiPassword": "sunny-2026", "maxGuests": 4}}'The response is the updated property, without the secrets.
Field notes:
-
Guest texts:
description,houseRulesandcheckInDescriptiontake plain English text. It overwrites the English copy, and the organization’s other languages then follow from it. OnlycheckInDescriptionhas a length limit, 150 characters. The response returnsdescriptionId,houseRulesIdandcheckInDescriptionId, translation IDs rather than text. Resending the stored text or an empty string changes nothing; to clear one, set its…Idfield tonull. -
Shared guest texts: several properties can point at the same text record, for example units set up as copies of one another. Writing
houseRules,checkInDescriptionordescriptionedits that record in place, so it changes the text for every property sharing it.getPropertyreturnshouseRulesSharedWithCount,checkInDescriptionSharedWithCountanddescriptionSharedWithCount: how many other properties share each record (0when it’s this unit’s own or unset). To give this unit its own copy, first send the…Idfield asnullin one call, then send the text in a second call. -
holdAccessUntilPmsPaid: trueholds the guest’s check-in instructions, door codes and device controls until the PMS reports the reservation fully paid. Only an explicit unpaid report from the PMS holds a stay, and the hold applies to verified guests too. It never holds a stay the PMS has once reported fully paid, even if a balance appears later, nor one whose guest has arrived: checked in by staff or the PMS, or a successful door unlock attributed to that stay alone. A check-in set through the guest portal or a workflow does not count. The flag has an effect only once SuiteOp staff turn on the organization’s PMS-paid hold feature, which is off by default; until then it is saved but ignored. -
propertyGroupIdmoves the unit to another group, or ungroups it withnull. If the unit has no default payment account of its own, it collects payments through its group’s, so a move that changes which account collects them also needsmanage_payments. Without it the request returns403and nothing moves. Someone withmanage_paymentscan first set the unit’s own default payment account so the move doesn’t change it. -
ownerIdlinks the unit to one of the organization’s owner records, andnullunassigns it. Owners are managed in the app; the API can’t list or create them. -
isUnitCodeDisabled: truerevokes the unit door code, not just hides it. Managed codes on the unit’s lock are retired and a delete is requested, including for guests mid-stay, though some codes can survive. The building code is unaffected. Set it back tofalseto resume. -
Clearing the address:
streetAddress,city,state,postalCode,countryCodeandformattedAddresseach takenullto clear them. Guest surfaces fall back toformattedAddresswhen the structured fields are incomplete, so to wipe an address completely, sendnullforformattedAddressand every structured field (andlatitudeandlongitudeto drop the map pin, which leaves the timezone as it is). An empty string forformattedAddressis stored as entered, not treated as a clear.{"data": {"streetAddress": null,"city": null,"state": null,"postalCode": null,"countryCode": null,"formattedAddress": null,"latitude": null,"longitude": null}} -
groupCheckInDescriptionOverrideIdlinks the unit’s own building check-in summary, shown to guests instead of its group’s whileisCodeOverrideFixedistrue. Like the other…Idfields it’s the ID of an existing translation record, not text; read the text withgetTranslationEntries(see Translations). If that record is empty, guests see the group’s summary.nullunlinks it.getPropertyand the update response return it. -
customAddressis the address shown to guests on the portal and in automated email instead of the real one.addressOverrideis not an address: it’s anhttpsURL that replaces the map link behind the address. -
timezoneis re-resolved from the coordinates when you send bothlatitudeandlongitudewithout atimezone. -
coverImageUrl: replacing or clearing it deletes the previously stored file. -
reviewRequestOverridesreplaces the whole per-channel map with what you send. -
orderTasksByElements: trueorders the unit’s task checklists by its element order (each area, then its items) instead of the task template’s section order. A change re-orders the unit’s tasks that haven’t started and hold no recorded work. -
Operational status and the assigned portal can’t be changed here. Use
updatePropertyStatusandassignPortalToProperty.
Setting cleaning and inspection status
Section titled “Setting cleaning and inspection status”POST /properties/{id}/status sets one of the two declarable tracks. field, value and trigger are required:
curl -X POST https://api-us.suiteop.com/api/v1/properties/9a3d7e40-…/status \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"field": "cleaningStatus", "value": "clean", "trigger": "cleaning_declared"}'fieldiscleaningStatus(valuesclean,dirty,unknown) orinspectionStatus(valuesinspected,not_inspected,failed_inspection,inspection_waived). A value from the other field’s set is rejected.- Either write recomputes readiness. Sending the current value writes nothing.
triggerrecords why the status changed; it doesn’t perform the named action. Usecleaning_declaredorinspection_declaredfor an outcome a person declared. Withcheckoutorreservation_cancelled, the write is skipped while another guest is still checked in. PassreservationIdto exclude that stay from the check.- Maintenance and readiness can’t be set: a
fieldofmaintenanceStatusorreadinessStatusis rejected with400 validation_errorrather than saved. Maintenance follows open maintenance tasks, and readiness follows reservations and these writes.
The response is the full property, not the status change.
Assigning a guest portal
Section titled “Assigning a guest portal”POST /properties/{propertyId}/assign-portal puts an existing guest portal on one property:
curl -X POST https://api-us.suiteop.com/api/v1/properties/9a3d7e40-…/assign-portal \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"portalSettingsId": "c41e…"}'portalSettingsId is the id returned by listPortals. Pass null to leave the property without a portal. The portal must belong to your organization. An OAuth token limited to some properties can only assign a portal it can already see, the organization’s default portal, or a portal serving no property; anything else returns 403.
Reading what a property carries
Section titled “Reading what a property carries”Three reads resolve what is attached to one property. None is paginated.
GET /properties/{propertyId}/tagsreturns the property’s tags asidandtitle. UselistTagsfor every tag in the organization.GET /properties/{propertyId}/upsellsreturns the upsells that reach the property directly, through its group, through its guest portal or through a tag, deduplicated.assignmentLevelsays which route applied. Archived upsells are left out. Titles aren’t included; callgetUpsellfor those.GET /properties/{propertyId}/portal-manualsneedsview_guides. It returns the house manuals assigned directly, through the group or through a tag, including inactive ones and without applying visibility rules, so it’s a superset of what a guest sees.
For a property outside your reach, the upsell and manual lists come back empty rather than as a 404.
Default payment account
Section titled “Default payment account”A guest charge that doesn’t name its own payment account, such as an upsell or a pre-check-in fee, waiver or deposit with no account pinned, is charged through the first of these that is set:
- the property’s default payment account,
- its property group’s default,
- the organization’s active default account.
POST /properties/{id}/default-payment-account sets the property’s default. It needs both modify_properties and manage_payments:
curl -X POST https://api-us.suiteop.com/api/v1/properties/9a3d7e40-5b6c-4d7e-8f90-1a2b3c4d5e6f/default-payment-account \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"paymentAccountId": "3f2b7a10-5c4d-4e8f-9a1b-6c2d3e4f5a60"}'{ "data": { "id": "9a3d7e40-5b6c-4d7e-8f90-1a2b3c4d5e6f", "defaultPaymentAccountId": "3f2b7a10-5c4d-4e8f-9a1b-6c2d3e4f5a60" }, "meta": { "requestId": "…" }}paymentAccountIdis required. Use anidfromlistPaymentAccounts. An inactive account, or one from another organization, returns404 not_found_error. So does a property outside your reach.nullclears the default, and the property inherits its group’s or the organization’s again. A clear succeeds even when nothing is left to inherit. It is refused with400 validation_erroronly when it would leave an active Screen & Protect check that charges a damage waiver with no account to charge.getPropertyreturnsdefaultPaymentAccountId: the property’s own setting, not the account that applies.nullmeans it inherits.- A default whose account stops taking money doesn’t fall through. If the account is switched off in the SuiteOp app, every property and group default pointing at it is cleared, so they inherit again. If it goes inactive any other way, for example when the provider disconnects it, charges that resolve to it are blocked until you set another default.