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.
| Operation | Request | Permission |
|---|---|---|
listEntityScopes | GET /entity-scopes | view_properties |
addEntityScopes | POST /entity-scopes/add | modify_properties |
removeEntityScopes | POST /entity-scopes/remove | modify_properties |
updateEntityScopes | POST /entity-scopes | modify_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 or guide_list also needs modify_guides; without it the write returns 403 authorization_error.
Entity types
Section titled “Entity types”Every call names the entity with entityId and entityType. There is no autodetection, so the type must match the ID.
entityType | What it is | Where the ID comes from |
|---|---|---|
upsell | A paid add-on in the guest store | listUpsells, createUpsell |
manual | A house manual article | listPortalManuals |
precheck_step | A pre-check-in step | listPrecheckSteps |
portal_settings | A guest portal | listPortals |
guide_list | A guide list, managed in the app | No public operation returns these IDs |
event | An event, managed in the app | No public operation returns these IDs |
manual and portal_settings can’t be scoped to guest portals: a non-empty portalSettingsIds for either 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.
Reading the current scopes
Section titled “Reading the current scopes”GET /entity-scopes takes entityId and entityType as query parameters and returns all four routes. It isn’t paginated.
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": "…" }}Adding and removing scopes
Section titled “Adding and removing scopes”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.
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_errorwithvalidation.entity_scope_delta_emptyindetails.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_errorwith the messagevalidation.scope_ids_not_in_org;detailsnames the kind and the IDs. Remove doesn’t check: an ID the entity doesn’t hold is ignored.
Replacing every scope
Section titled “Replacing every scope”updateEntityScopes (POST /entity-scopes) replaces the entity’s whole scope set with what you send, across all four routes, and answers { "success": true }.
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 misspelledpropertyIDsfails 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
entityIdthat doesn’t exist in your organization, or doesn’t matchentityType, returns404 not_found_erroron every write.
Property-limited callers
Section titled “Property-limited callers”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. updateEntityScopesreplaces 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.
Pitfalls
Section titled “Pitfalls”- Scopes are separate from the entity.
createUpsell,createPrecheckStepandupdatePortalManualdon’t set scopes; add them after creating the entity.createPortalManualcan seed one property scope withpropertyId. - Retries on replace aren’t harmless. Resending a stale
updateEntityScopesbody after someone else changed the scopes overwrites their change. Add and remove don’t have this problem. - Send an
Idempotency-Keyon thesePOSTs 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.