Skip to content
Dashboard

Property groups

A property group is a building or portfolio that properties are collected into. It carries settings shared by all of its properties, such as how guests receive building access codes and whether the properties need an inspection. This guide covers the five property group operations. Every field is listed on the operation’s page in the API Reference.

OperationRequestPermission
listPropertyGroupsGET /property-groupsview_properties
getPropertyGroupGET /property-groups/{id}view_properties
createPropertyGroupPOST /property-groupsmodify_properties
updatePropertyGroupPATCH /property-groups/{id}modify_properties
setPropertyGroupDefaultPaymentAccountPOST /property-groups/{id}/default-payment-accountmodify_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.

The API can’t delete a group. It also can’t add properties to a group or remove them from this side: a property joins or leaves a group through updateProperty with propertyGroupId.

GET /property-groups is paginated (default and maximum limit 200) and ordered by name.

Terminal window
curl "https://api-us.suiteop.com/api/v1/property-groups?nameContains=riva" \
-H "Authorization: Bearer sk_live_your_key_here"
  • nameContains is a case-insensitive substring of the group name. Unlike the property list, % and _ act as wildcards here, and accents are not folded, so Riviere does not match Rivière.
  • writableOnly=true keeps only the groups whose every property the caller holds. It changes nothing for an sk_ API key, which has access to every property. An OAuth token carries its member’s property access, so for it the list can shrink. For a token whose member has access to only some properties, it also leaves out empty groups: a group you have just created appears once it contains a property that member can access.

List rows carry id, name, codeDisplay, isInspectionRequired and createdAt. The id is what listProperties, listInstructions and createInstruction accept as propertyGroupId. To see which properties belong to a group, call GET /properties?propertyGroupId=….

GET /property-groups/{id} adds isAccessLabelVisible, shareGroupCodes and updatedAt. A group in another organization is reported as not found.

POST /property-groups takes a name and nothing else about the group. The group starts empty. Set its building access code afterwards with updatePropertyGroup.

const res = await fetch('https://api-us.suiteop.com/api/v1/property-groups', {
method: 'POST',
headers: {
Authorization: 'Bearer sk_live_your_key_here',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'Riva Tower', addToAllMembers: true }),
})
const { data } = await res.json() // data.id is the new group
  • name must be unique among the organization’s groups. A name already in use returns 409 conflict_error. Call listPropertyGroups first to see whether a group already fits.
  • addToAllMembers=true gives every currently active member access to the new group, so nobody loses sight of its properties. Members added later are not covered. It defaults to false.

POST /property-groups/{id}/default-payment-account sets the account that guest charges at the group’s properties use when neither the charge nor the property names one. It comes after a property’s own default and before the organization’s. The body, the response and the rules match the property operation:

Terminal window
curl -X POST https://api-us.suiteop.com/api/v1/property-groups/5c1e7a92-3b4d-4f6e-8a0b-1c2d3e4f5a6b/default-payment-account \
-H "Authorization: Bearer sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"paymentAccountId": null}'
  • Because it re-routes money for every property in the group, you need access to all of them. Otherwise the call returns 404 not_found_error.
  • getPropertyGroup, createPropertyGroup and updatePropertyGroup return the group’s defaultPaymentAccountId, or null when it inherits the organization’s.

PATCH /property-groups/{id} takes a data object. Send only the fields you are changing.

Terminal window
curl -X PATCH "https://api-us.suiteop.com/api/v1/property-groups/8d7c6b5a-4e3f-4a2b-9c1d-0e9f8a7b6c5d" \
-H "Authorization: Bearer sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"data": {"isInspectionRequired": true}}'
  • name: a new name, unique in the organization, or the update returns 409 conflict_error.
  • isInspectionRequired: true requires an inspection on the group’s properties.
  • codeDisplay: how guests receive the building access code. dynamic generates one per stay, fixed uses one building code and import takes the code from your PMS. null unsets it.
  • entryCode: the static building access code, for example "4821#", up to 50 characters. It is trimmed before it is saved. While codeDisplay is unset, the group’s properties use the code as a fixed building code (codeDisplay still reads null) — except a property that sets its own building code type, or overrides the group’s code. null clears it.
  • codeConfirmationKey: the keypad key a guest presses to confirm the building code, for example "#", up to 8 characters. Guests see it beside the building code; it isn’t the code itself. null clears it.
  • isAccessLabelVisible: shows or hides the custom access label (accessLabel) on the guest portal.
  • checkInDescription: the group-wide check-in summary guests read, plain text or HTML, 1 to 20,000 characters.
  • accessLabel: the short custom access label guests see while isAccessLabelVisible is true, 1 to 200 characters.
  • internalAccessNotes: staff-only access notes, never shown to guests, 1 to 20,000 characters.

The three texts are plain English. Each one you send overwrites the English source and re-translates the organization’s other languages. The response returns all three as English text, or null to a caller who holds no property in the group. Step-by-step guidance belongs in check-in instructions instead.

entryCode and codeConfirmationKey are write-only: the response leaves them out, as every read does. Keep your own record of what you set.

Any other field in data is rejected with 400 validation_error rather than ignored. That includes shareGroupCodes, which decides whether overlapping stays share one entrance code on a physical lock. You can read it from getPropertyGroup, but it can only be changed in the app.