Organization and lookups
These read-only operations give you values that other operations need: your organization’s temperature unit, the payment accounts a paid upsell can charge against, the tag IDs that filters and scopes take, and the icon names and stock photos a cover can use. None of them changes anything. Every field is listed on the operation’s page in the API Reference.
| Operation | Request | Permission |
|---|---|---|
getOrganization | GET /organization | view_organization |
listPaymentAccounts | GET /payment-accounts | view_payments |
listTags | GET /tags | view_properties |
listPropertyTags | GET /properties/{propertyId}/tags | view_properties |
searchCoverIcons | GET /cover-icons | None |
searchStockPhotos | GET /stock-photos | None |
Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions. All six are also tools on the MCP server, under the same names.
Organization
Section titled “Organization”GET /organization returns the organization your credential acts in. It takes no ID and no parameters, and it can’t reach another organization.
curl https://api-us.suiteop.com/api/v1/organization \ -H "Authorization: Bearer sk_live_your_key_here"{ "data": { "id": "9e4b1c27-3f8a-4d6e-b2c5-7a0f1e9d3b84", "name": "Riva Stays", "slug": "riva-stays", "timezone": "Europe/Paris", "region": "eu", "temperatureUnit": "celsius", "createdAt": "2024-02-11T08:15:42.000Z" }, "meta": { "requestId": "3f1c9a52-…" }}temperatureUnitiscelsiusorfahrenheit, and defaults tofahrenheit.setDeviceTemperaturereads every number you send in this unit, and no other operation returns it.timezoneis an IANA name such asEurope/Paris, ornullwhen the organization has none set. It isn’t the timezone a unit runs on: timezones and check-in hours are set per property, so read them withgetProperty.regionis the data-residency region:us,euorapac. It is fixed when the organization is created and matches the base URL you call.
Billing, branding, check-in and door-code settings aren’t returned, and nothing on the organization can be changed through the API.
Payment accounts
Section titled “Payment accounts”GET /payment-accounts lists the processor accounts your organization can charge guests against. It takes no parameters and is not paginated or sorted. Inactive accounts are included.
curl https://api-us.suiteop.com/api/v1/payment-accounts \ -H "Authorization: Bearer sk_live_your_key_here"{ "data": [ { "id": "3f2b7a10-5c4d-4e8f-9a1b-6c2d3e4f5a60", "nickname": "Riva EUR", "provider": "stripe", "currencyCode": "eur", "isActive": true }, { "id": "7a1c9e42-0b3d-4f6a-8e2c-5d9b1f7a3c08", "nickname": "Old USD account", "provider": "guesty_pay", "currencyCode": "usd", "isActive": false } ], "meta": { "requestId": "3f1c9a52-…" }}provideris currentlystripe,guesty_payorjuspay.currencyCodeis the currency the account settles in, as a lowercase code such asusdoreur. Match it to the price you set.isActivetells you whether the account can still take money. Only pin an active one.- Which account is the organization’s default isn’t returned. To use the default, leave
paymentAccountIdout of the upsell.
Accounts are connected by an operator in the SuiteOp app, never through the API. Use an account’s id as paymentAccountId on upsells, and for the waiver, deposit and fee fields of a pre-check-in step, where an unknown, inactive or other-organization ID returns 404.
A tag is a free-form label an operator puts on properties, such as “Beachfront”. Tags belong to the organization, not to one property. Tag IDs are what listProperties and listPrecheckSteps filter on with tagIds, and what the entity-scope operations take to reach every property carrying a tag. listTags is the only way to list every tag; listPropertyTags gives the tags on one property.
Tags can’t be created, renamed, deleted or attached to a property through the API. To scope an upsell, manual, step or portal to a tag, see Entity scopes.
Listing every tag
Section titled “Listing every tag”GET /tags is paginated, but with its own defaults: limit is 1 to 500 and defaults to 100, and offset defaults to 0. Rows are ordered by title, with the ID breaking ties so paging is stable. Deleted tags are left out, and so is their count in total.
curl "https://api-us.suiteop.com/api/v1/tags?nameContains=beach&limit=50" \ -H "Authorization: Bearer sk_live_your_key_here"{ "data": [ { "id": "c8e2f1a4-6b3d-4e9a-8f2c-1d7b5a9e3c60", "title": "Beachfront", "createdAt": "2025-05-02T13:20:08.000Z", "updatedAt": "2025-05-02T13:20:08.000Z" } ], "meta": { "requestId": "3f1c9a52-…", "pagination": { "total": 1, "limit": 50, "offset": 0 } }}nameContainsis a case-insensitive substring of the title.%and_are matched literally, not as wildcards.writableOnly=truekeeps only tags whose every property the caller can access, which are the tags the caller can scope an entity to. It changes nothing for an API key.- Titles aren’t unique, so two tags can share one. Tell them apart by
id.
To read every tag, page until you have total rows:
const base = 'https://api-us.suiteop.com/api/v1'const headers = { Authorization: 'Bearer sk_live_your_key_here' }
const tags: { id: string; title: string }[] = []let offset = 0for (;;) { const res = await fetch(`${base}/tags?limit=500&offset=${offset}`, { headers }) if (!res.ok) throw new Error(`listTags failed: ${res.status}`) const { data, meta } = await res.json() tags.push(...data) offset += data.length if (data.length === 0 || offset >= meta.pagination.total) break}
const beachfront = tags.filter((t) => t.title === 'Beachfront').map((t) => t.id)Tags on one property
Section titled “Tags on one property”GET /properties/{propertyId}/tags returns the tags on one property as id and title, ordered by title. It is a plain array with no paging and no filters. A property with no tags returns [].
curl https://api-us.suiteop.com/api/v1/properties/5d1e8b3a-2c7f-4a9e-b6d0-8f3c1a7e2b94/tags \ -H "Authorization: Bearer sk_live_your_key_here"{ "data": [ { "id": "c8e2f1a4-6b3d-4e9a-8f2c-1d7b5a9e3c60", "title": "Beachfront" }, { "id": "1b7d3e9f-4a2c-4f8e-9d6b-0c5a8e2f7d13", "title": "Pet friendly" } ], "meta": { "requestId": "3f1c9a52-…" }}propertyId must be a UUID, or the request returns 400. A property that doesn’t exist, belongs to another organization or is outside an OAuth user’s access also returns 200 with [], not 404. Check the ID with getProperty if an empty list is surprising.
Cover icons and stock photos
Section titled “Cover icons and stock photos”House manuals and upsells take a cover: an icon name or a photo URL. These two searches supply them. Neither needs a permission, so any valid key can call them, including one that only holds modify_guides.
GET /cover-iconssearches the icon namesiconNameaccepts.query(up to 64 characters) is trimmed and matched case-insensitively anywhere in the name; omit it to get the start of the catalogue.limitis 1 to 100 (default 25), andtotalcounts every match before the limit. The catalogue is the same for every organization.GET /stock-photossearches Unsplash.queryis required (1 to 200 characters),perPageis 1 to 30 (default 20) andpage1 to 100 (default 1). Each item carriesimageUrl,thumbnailUrl,description(can benull),photographerNameandphotographerUrl, withtotalandtotalPagesalongside. SaveimageUrlas the cover:thumbnailUrlis for previews, and its use isn’t reported to Unsplash. Where stock search isn’t configured, it returns503.
Both return their results as data.items with data.total (and data.totalPages for photos), not meta.pagination.
How covers are set, with full request and response examples, is in House Manuals and Upsells.
Property-limited OAuth tokens
Section titled “Property-limited OAuth tokens”API keys reach every property. An OAuth token acts with its user’s access, so when that user is limited to some properties:
getOrganization,listPaymentAccounts,searchCoverIconsandsearchStockPhotosbehave as they do for an API key.listTagsstill returns every tag in the organization unless you passwritableOnly=true.listPropertyTagsreturns[]for a property the user can’t access.