This guide explains how to read and update category-level rates and restrictions.
Reading Rates and Restrictions¶
Rates and Restrictions are scoped to a category and a specific date. While category filter can be skipped, a date range for rates and restrictions is mandatory. Rates can be ready by using the Category.defaultPrices
field, for example to read rates for all of July 2025:
# Variables
# {
# "dateRange": {
# "start": "2025-07-01",
# "end": "2025-07-31"
# }
# }
query RatesAndRestrictions($dateRange:DateRangeInput!) {
settings {
categories {
edges {
node {
...MyCategoryData
}
}
}
}
}
fragment MyCategoryData on Category {
id
defaultPrices(filter:{date:$dateRange} first:31) {
edges {
node {
date
amount
}
}
}
}
Similarly, restrictions can be read by using Category.restrictions
field:
fragment MyCategoryData on Category {
id
restrictions(filter:{date:$dateRange} first:31) {
edges {
node {
date
stopSell
minStay
maxStay
closedToArrival
closedToDeparture
guarantee
cancellation
breakfastIncluded
}
}
}
}
Best Practice
defaultPrices
and restrictions
fields are *Connection
types. Like all *Connection
types, they support cursor pagination and are limited to at most 100 results per page. However, as each date appears only once, its more convenient to use multiple date ranges to read more data. instead of cursor arguments.
Field | Description |
---|---|
stopSell |
When active, category is not bookable |
minStay |
Minimum Length of Stay. Value is between 1 and 99 (inclusive) |
maxStay |
Maximum Length of Stay. NULL represents a no limit on maximum stay |
closedToArrival |
When active, arriving on this day is not allowed |
closedToDeparture |
When active, departing on this day is not allowed |
guarantee |
When active, a guarantee is required to stay on this date |
cancellation |
The amount of days whilst possible to cancel prior to arrival without penalties. NULL is non cancellable, 0 is a standard policy as defined in booking portals. |
breakfastIncluded |
Whether breakfast is included in price or not. |
Channel Manager Limitations
Not all restrictions are supported by all Channel Managers. Some hotels might chose to not use all restrictions because of this.
Occupancy-Based Pricing¶
Some categories might have different rates based on how many people are staying in the room. For example, a standard rate might be set up for 2 people, with a cheaper rate if room is booked by 1 person. If your integration also wants to query occupancy based prices, the query can be augmented to include this data as well:
fragment MyCategoryData on Category {
id
standardOccupancy
defaultPrices(filter:{date:$dateRange} first:31) {
edges {
node {
date
amount
occupancies {
occupancy
amount
}
}
}
}
top-level amount
refers to rate used by standard occupancy (standardOccupancy
field), while occupancies.occupancy
field refers to rate used by each occupancy other than standard occupancy.
occupancies
field will be empty when a category does not use occupancy based pricing, so if your integration needs these rates, it’s safe to include the fields for all categories.
Updating Rates and Restrictions¶
API Access
Updating rates and restrictions requires read/write permissions
Rates can be updated by using the updateCategoryPrices
mutation. It requires:
- Category ID
- Date Range (inclusive)
- Amount
# Variables:
# {
# "updates": [
# {category: "<category id>", dateRange: {start: "2025-07-07", end: "2025-07-11"}, amount: "123.45"},
# {category: "<category id>", dateRange: {start: "2025-07-14", end: "2025-07-18"}, amount: "111.99"},
# ],
# }
#
mutation UpdatePrice($updates:[CategoryPriceInput!]!) {
updateCategoryPrices(input:{prices: $updates}) {
__typename
}
}
Similarly, restrictions can be updated by using updateCategoryRestrictions
mutation. It requires:
- Category ID
- Date Range (inclusive)
- Changeset - any subset of restriction fields. Non-provided fields will not be updated.
# Variables:
# {
# "restrictions": [
# {
# "category": "<category id>",
# "dateRange": {
# "start": "2025-07-01",
# "end": "2025-07-31"
# },
# "stopSell": true,
# "minStay": 4,
# "maxStay": 5,
# "closedToArrival": true,
# "closedToDeparture": true,
# "guarantee": true,
# "cancellation": 2,
# "breakfastIncluded": true
# }
# ]
# }
mutation UpdateRestrictions($restrictions: [CategoryRestrictionInput!]!) {
updateCategoryRestrictions(input:{restrictions:$restrictions}) { __typename }
}
Update Limit
At most 1000 updates can be sent in one mutation. 1 update is a category and date pair. For example, updating 1 category for July is 31 updates. To update more than 1000 days, multiple requests must be sent.
Occupancy-Based Pricing¶
Occupancy-based pricing by default is derived from the standard rate. Updating these rates is optional. However, if the default behaviour is not suitable, your integration may still provide a different rate for each occupancy by providing an additional occupancy
value:
{
"updates": [
{category: "<category id>", dateRange: {start: "2023-09-13", end: "2023-09-13"}, occupancy: 2, amount: "123.45"},
],
}
To reset back to using a derived rate for an occupancy, the amount value can be NULL
:
{
"updates": [
{category: "<category id>", dateRange: {start: "2023-09-13", end: "2023-09-13"}, occupancy: 2, amount: null},
],
}
No Duplicates
Avoid sending multiple updates for the same (date,category, ?occupancy)
tuple in one request. We provide no guarantee on the order in which updates processed.