Skip to content
Dashboard

Entity scopes

Guest-portal content in SuiteOp is written once and switched on where it applies. An entity’s scopes are the properties it reaches, through four routes: individual properties, property groups, tags and guest portals. The four entity-scope operations read and change those routes for one entity at a time. Every field is listed on the operation’s page in the API Reference.

OperationRequestPermission
listEntityScopesGET /entity-scopesview_properties
addEntityScopesPOST /entity-scopes/addmodify_properties
removeEntityScopesPOST /entity-scopes/removemodify_properties
updateEntityScopesPOST /entity-scopesmodify_properties

Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions. Writing the scopes of a manual, guide_list or portal_fee_product also needs modify_guides; without it the write returns 403 authorization_error.

Every call names the entity with entityId and entityType. There is no autodetection, so the type must match the ID.

entityTypeWhat it isWhere the ID comes from
upsellA paid add-on in the guest storelistUpsells, createUpsell
manualA house manual articlelistPortalManuals
precheck_stepA pre-check-in steplistPrecheckSteps
portal_settingsA guest portallistPortals
guide_listA guest-portal guide listlistGuideLists
eventAn event, managed in the appNo public operation returns these IDs
portal_fee_productA mandatory fee charged at pre-check-in, managed in the appNo public operation returns these IDs

manual, portal_settings and portal_fee_product can’t be scoped to guest portals: a non-empty portalSettingsIds for any of them is rejected with 400 validation_error (message validation.unsupported_scope_type_for_entity). For a guest portal, the property route is the portal assignment itself: scoping a portal to a property makes it that property’s portal, the same as assignPortalToProperty. A replace that leaves a property out of a portal’s propertyIds takes that portal off the property.

A flat portal_fee_product that has never been scoped charges wherever its pre-check-in step applies. Scopes then work the opposite way to other entities:

  • Adding its first scope narrows it to that scope.
  • Emptying it widens it again. Removing its last scope, or replacing its scopes with nothing, puts it back to charging wherever its step applies.
  • A fee emptied by a deletion stays off. When its scopes disappear because the property, group or tag was deleted, it charges nowhere until you scope it again.

listEntityScopes returns four empty arrays in every one of these cases, so it can’t tell you which one a fee is in.

GET /entity-scopes takes entityId and entityType as query parameters and returns all four routes. It isn’t paginated.

Terminal window
curl "https://api-us.suiteop.com/api/v1/entity-scopes?entityType=upsell&entityId=3f2b1d9e-7a4c-4b2e-8f61-0c9d2e5a7b18" \
-H "Authorization: Bearer sk_live_your_key_here"
{
"data": {
"propertyIds": ["9a3d7e40-2c1b-4f8e-a6d5-3b7c9e0f1a24"],
"propertyGroupIds": [],
"tagIds": ["5e8a1c3d-7b2f-4a9e-8d6c-1f0e3b5a7c92"],
"portalSettingsIds": []
},
"meta": { "requestId": "…" }
}

addEntityScopes and removeEntityScopes change only the IDs you send and keep everything else. Prefer them over updateEntityScopes: you don’t need to read or resend the current set.

Terminal window
curl -X POST https://api-us.suiteop.com/api/v1/entity-scopes/add \
-H "Authorization: Bearer sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"entityType": "upsell",
"entityId": "3f2b1d9e-7a4c-4b2e-8f61-0c9d2e5a7b18",
"propertyGroupIds": ["2e6d0f5b-8a1c-4d3e-9b7f-6c0a2e4d8f13"]
}'

Both answer with the entity’s resulting scopes, in the same four-array shape listEntityScopes returns:

{
"data": {
"propertyIds": ["9a3d7e40-2c1b-4f8e-a6d5-3b7c9e0f1a24"],
"propertyGroupIds": ["2e6d0f5b-8a1c-4d3e-9b7f-6c0a2e4d8f13"],
"tagIds": ["5e8a1c3d-7b2f-4a9e-8d6c-1f0e3b5a7c92"],
"portalSettingsIds": []
},
"meta": { "requestId": "…" }
}
  • Send at least one ID. Omit the arrays you aren’t changing. A request whose arrays are all empty or missing returns 400 validation_error with validation.entity_scope_delta_empty in details.issues (the top-level message is the generic input-validation one).
  • Safe to retry. Adding an ID the entity already has, or removing one it doesn’t have, succeeds without change.
  • IDs must be yours. On add, a property, group, tag or portal from another organization returns 400 validation_error with the message validation.scope_ids_not_in_org; details names the kind and the IDs. Remove doesn’t check: an ID the entity doesn’t hold is ignored.

updateEntityScopes (POST /entity-scopes) replaces the entity’s whole scope set with what you send, across all four routes, and answers { "success": true }.

Terminal window
curl -X POST https://api-us.suiteop.com/api/v1/entity-scopes \
-H "Authorization: Bearer sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"entityType": "precheck_step",
"entityId": "8d2e4f60-1b3a-4c7d-9e25-0f6a8b1c3d47",
"propertyIds": [],
"propertyGroupIds": ["2e6d0f5b-8a1c-4d3e-9b7f-6c0a2e4d8f13"],
"tagIds": [],
"portalSettingsIds": []
}'
  • Unknown keys are rejected with 400 validation_error, so a misspelled propertyIDs fails instead of silently clearing the property route.
  • IDs from another organization return 400 validation_error (validation.scope_ids_not_in_org), as on add.
  • An entityId that doesn’t exist in your organization, or doesn’t match entityType, returns 404 not_found_error on every write.

An sk_ API key acts across the whole organization. An OAuth token carries the property access of the member who authorized it (see Members), and for such a token:

  • The entity itself must be visible to the member, or the write returns 404.
  • On add and replace, a property ID outside their access, or a group, tag or portal that covers any property outside it, returns 404, the same answer as an ID that doesn’t exist.
  • On remove, a scope ID outside their access is ignored: the request succeeds and that assignment stays in place. Removing it needs a credential that can reach it, such as an sk_ key.
  • updateEntityScopes replaces only the scopes within their access. Scopes they can’t reach are kept.
  • listEntityScopes, add and remove return only the scopes the member can see, so the response can be smaller than the stored set.
  • Scopes are separate from the entity. createUpsell, createPrecheckStep and updatePortalManual don’t set scopes; add them after creating the entity. createPortalManual can seed one property scope with propertyId.
  • Retries on replace aren’t harmless. Resending a stale updateEntityScopes body after someone else changed the scopes overwrites their change. Add and remove don’t have this problem.
  • Send an Idempotency-Key on these POSTs when you retry automatically, so a replayed request returns the original response (see Idempotency).
  • Workflow scopes are different. Which properties an automation runs on is set with set_workflow_scopes, not with these operations.